changeset 1321:6144c0bee0f9

Automated merge with ssh://jfxsrc.us.oracle.com//javafx/2.2/MASTER/jfx/rt
author Kinsley Wong
date Mon, 18 Jun 2012 13:12:52 -0700
parents 6f2d238b4c8b 104dff9f4ebc
children bdbc42e5a633
files
diffstat 43 files changed, 770 insertions(+), 226 deletions(-) [+]
line wrap: on
line diff
--- a/javafx-ui-charts/src/javafx/scene/chart/PieChart.java	Thu Jun 14 14:06:12 2012 -0700
+++ b/javafx-ui-charts/src/javafx/scene/chart/PieChart.java	Mon Jun 18 13:12:52 2012 -0700
@@ -71,6 +71,7 @@
 import com.sun.javafx.css.converters.BooleanConverter;
 import com.sun.javafx.css.converters.SizeConverter;
 import java.util.ArrayList;
+import javafx.animation.*;
 
 /**
  * Displays a PieChart. The chart content is populated by pie slices based on
@@ -92,11 +93,11 @@
     private Data begin = null;
     private final Path labelLinePath = new Path();
     private Legend legend = new Legend();
+    private Data dataItemBeingRemoved = null;
+    private Timeline dataRemoveTimeline = null;
     private final ListChangeListener<Data> dataChangeListener = new ListChangeListener<Data>() {
         @Override public void onChanged(Change<? extends Data> c) {
             while(c.next()) {
-            // remove chart references from old data
-            for (Data item : c.getRemoved()) item.setChart(null);
             // recreate linked list & set chart on new data
             for(int i=c.getFrom(); i<c.getTo(); i++) {
                 getData().get(i).setChart(PieChart.this);
@@ -359,6 +360,17 @@
         final Text text = createPieLabel(itemIndex, item);
         item.getChart().getChartChildren().add(shape);
         if (shouldAnimate()) {
+            // if the same data item is being removed, first stop the remove animation,
+            // remove the item and then start the add animation.
+            if (dataRemoveTimeline != null && dataRemoveTimeline.getStatus().equals(Animation.Status.RUNNING)) {
+                if (dataItemBeingRemoved == item) {
+                    dataRemoveTimeline.stop();
+                    dataRemoveTimeline = null;
+                    getChartChildren().remove(item.textNode);
+                    getChartChildren().remove(shape);
+                    removeDataItemRef(item);
+                }
+            }
             animate(
                 new KeyFrame(Duration.ZERO,
                     new KeyValue(item.currentPieValueProperty(), item.getCurrentPieValue()),
@@ -368,7 +380,7 @@
                         @Override public void handle(ActionEvent actionEvent) {
                             text.setOpacity(0);
                             item.getChart().getChartChildren().add(text);
-                            FadeTransition ft = new FadeTransition(Duration.millis(300),text);
+                            FadeTransition ft = new FadeTransition(Duration.millis(150),text);
                             ft.setToValue(1);
                             ft.play();
                         }
@@ -394,12 +406,11 @@
             if(ptr != null) ptr.next = item.next;
         }
     }
-
-    private void dataItemRemoved(final Data item) {
+    
+    private Timeline createDataRemoveTimeline(final Data item) {
         final Node shape = item.getNode();
-        if (shouldAnimate()) {
-            animate(
-                new KeyFrame(Duration.ZERO,
+        Timeline t = new Timeline();
+        t.getKeyFrames().addAll(new KeyFrame(Duration.ZERO,
                     new KeyValue(item.currentPieValueProperty(), item.getCurrentPieValue()),
                     new KeyValue(item.radiusMultiplierProperty(), item.getRadiusMultiplier())),
                 new KeyFrame(Duration.millis(500),
@@ -408,25 +419,37 @@
                             // removing item
                             getChartChildren().remove(shape);
                             // fade out label
-                            FadeTransition ft = new FadeTransition(Duration.millis(300),item.textNode);
+                            FadeTransition ft = new FadeTransition(Duration.millis(150),item.textNode);
                             ft.setFromValue(1);
                             ft.setToValue(0);
                             ft.setOnFinished(new EventHandler<ActionEvent>() {
                                  @Override public void handle(ActionEvent actionEvent) {
                                      getChartChildren().remove(item.textNode);
+                                     // remove chart references from old data - RT-22553
+                                     item.setChart(null);
+                                     removeDataItemRef(item);
                                  }
                             });
                             ft.play();
-                            removeDataItemRef(item);
                         }
                     },
                     new KeyValue(item.currentPieValueProperty(), 0, Interpolator.EASE_BOTH),
-                    new KeyValue(item.radiusMultiplierProperty(), 0)
-                )
-            );
+                    new KeyValue(item.radiusMultiplierProperty(), 0))
+                );
+        return t;
+    }
+
+    private void dataItemRemoved(final Data item) {
+        final Node shape = item.getNode();
+        if (shouldAnimate()) {
+            dataRemoveTimeline = createDataRemoveTimeline(item);
+            dataItemBeingRemoved = item;
+            animate(dataRemoveTimeline);
         } else {
             getChartChildren().remove(item.textNode);
             getChartChildren().remove(shape);
+            // remove chart references from old data
+            item.setChart(null);
             removeDataItemRef(item);
         }
     }
@@ -810,7 +833,7 @@
         };
          
          private static final StyleableProperty<PieChart,Boolean> LABELS_VISIBLE = 
-             new StyleableProperty<PieChart,Boolean>("-fx-labels-visible",
+             new StyleableProperty<PieChart,Boolean>("-fx-pie-label-visible",
                  BooleanConverter.getInstance(), Boolean.TRUE) {
 
             @Override
--- a/javafx-ui-charts/src/javafx/scene/chart/ScatterChart.java	Thu Jun 14 14:06:12 2012 -0700
+++ b/javafx-ui-charts/src/javafx/scene/chart/ScatterChart.java	Mon Jun 18 13:12:52 2012 -0700
@@ -185,7 +185,9 @@
             for (int seriesIndex=0; seriesIndex< getData().size(); seriesIndex++) {
                 Series<X,Y> series = getData().get(seriesIndex);
                 LegendItem legenditem = new LegendItem(series.getName());
-                legenditem.getSymbol().getStyleClass().addAll(series.getData().get(0).getNode().getStyleClass());
+                if (series.getData().get(0).getNode() != null) {
+                    legenditem.getSymbol().getStyleClass().addAll(series.getData().get(0).getNode().getStyleClass());
+                }
                 legend.getItems().add(legenditem);
             }
         }
--- a/javafx-ui-charts/test/javafx/scene/chart/ChartTestBase.java	Thu Jun 14 14:06:12 2012 -0700
+++ b/javafx-ui-charts/test/javafx/scene/chart/ChartTestBase.java	Mon Jun 18 13:12:52 2012 -0700
@@ -31,7 +31,7 @@
 public abstract class ChartTestBase {
     private Scene scene;
     private Stage stage;
-    private StubToolkit toolkit = (StubToolkit) Toolkit.getToolkit(); 
+    StubToolkit toolkit = (StubToolkit) Toolkit.getToolkit(); 
     private Chart chart;
     
     @Before
--- a/javafx-ui-charts/test/javafx/scene/chart/StackedAreaChartTest.java	Thu Jun 14 14:06:12 2012 -0700
+++ b/javafx-ui-charts/test/javafx/scene/chart/StackedAreaChartTest.java	Mon Jun 18 13:12:52 2012 -0700
@@ -69,7 +69,8 @@
         ac.getData().addAll(series1);
         pulse();
         StringBuffer sb = getSeriesLineFromPlot();
-        assertEquals(sb.toString(), "L206.0 57.0 L247.0 171.0 L412.0 171.0 L658.0 284.0 ");
+//        assertEquals("L206.0 57.0 L247.0 171.0 L412.0 171.0 L658.0 284.0 ", sb.toString());
+        assertEquals("L220.0 59.0 L264.0 175.0 L440.0 175.0 L704.0 291.0 ", sb.toString());
     
     }
     
--- a/javafx-ui-charts/test/javafx/scene/chart/StackedBarChartTest.java	Thu Jun 14 14:06:12 2012 -0700
+++ b/javafx-ui-charts/test/javafx/scene/chart/StackedBarChartTest.java	Mon Jun 18 13:12:52 2012 -0700
@@ -68,17 +68,17 @@
         // compute bounds for the first series
         sb = computeBoundsString((Region)childrenList.get(0), (Region)childrenList.get(1),
                 (Region)childrenList.get(2));
-        assertEquals("10 472 216 35 236 426 216 81 461 369 216 138 ", sb.toString());
+        assertEquals("10 483 236 36 256 436 236 83 501 378 236 141 ", sb.toString());
         
         // compute bounds for the second series
         sb = computeBoundsString((Region)childrenList.get(3), (Region)childrenList.get(4),
                 (Region)childrenList.get(5));
-        assertEquals("10 412 216 60 236 321 216 105 461 214 216 155 ", sb.toString());
+        assertEquals("10 421 236 62 256 328 236 108 501 220 236 158 ", sb.toString());
         
         // compute bounds for the third series
         sb = computeBoundsString((Region)childrenList.get(6), (Region)childrenList.get(7),
                 (Region)childrenList.get(8));
-        assertEquals("10 362 216 50 236 258 216 63 461 37 216 177 ", sb.toString());
+        assertEquals("10 370 236 51 256 264 236 64 501 39 236 181 ", sb.toString());
     }
     
     @Test
--- a/javafx-ui-charts/test/javafx/scene/chart/XYChartTest.java	Thu Jun 14 14:06:12 2012 -0700
+++ b/javafx-ui-charts/test/javafx/scene/chart/XYChartTest.java	Mon Jun 18 13:12:52 2012 -0700
@@ -5,13 +5,18 @@
 package javafx.scene.chart;
 
 
+import com.sun.javafx.pgstub.StubToolkit;
+import com.sun.javafx.tk.Toolkit;
 import org.junit.Test;
 import javafx.collections.*;
+import javafx.scene.chart.Axis.TickMark;
+import com.sun.javafx.css.ParsedValue;
+import com.sun.javafx.css.StyleableProperty;
+import com.sun.javafx.css.parser.CSSParser;
 
-import com.sun.javafx.pgstub.StubToolkit;
-import javafx.scene.Scene;
-import javafx.stage.Stage;
-
+import javafx.scene.text.Font;
+import org.junit.Assert;
+import static org.junit.Assert.assertEquals;
 
 
 public class XYChartTest extends ChartTestBase {
@@ -36,4 +41,36 @@
         yaxis.getTickMarks().toString(); 
         System.out.println(" --- "+yaxis.getTickMarks().toString());
     }
+    
+    // RT-22166
+    @Test public void testTickLabelFont() {
+        startApp();
+        Font f = yaxis.getTickLabelFont();
+        // default caspian value for font size = 10
+        assertEquals(10, new Double(f.getSize()).intValue());
+        assertEquals(10, new Double(yaxis.measure.getFont().getSize()).intValue());
+        
+        // set tick label font via css and test if ticklabelfont, measure and tick textnode follow.
+        ParsedValue pv = CSSParser.getInstance().parseExpr("-fx-tick-label-font","0.916667em System");
+        Object val = pv.convert(null);        
+        StyleableProperty prop = StyleableProperty.getStyleableProperty(yaxis.tickLabelFontProperty());
+        try {
+            prop.set(yaxis, val, null);
+            // confirm tickLabelFont, measure and tick's textnode all are in sync with -fx-tick-label-font
+            assertEquals(11, new Double(yaxis.getTickLabelFont().getSize()).intValue());
+            assertEquals(11, new Double(yaxis.measure.getFont().getSize()).intValue());
+            final ObservableList<Axis.TickMark<Number>> yaTickMarks = yaxis.getTickMarks();
+            TickMark tm = yaTickMarks.get(0);
+            assertEquals(11, new Double(tm.textNode.getFont().getSize()).intValue());
+        } catch (Exception e) {
+            Assert.fail(e.toString());
+        }
+        // set tick label font programmatically and test.
+        yaxis.setTickLabelFont(new Font(12.0f));
+        assertEquals(12, new Double(yaxis.getTickLabelFont().getSize()).intValue());
+        assertEquals(12, new Double(yaxis.measure.getFont().getSize()).intValue());
+        final ObservableList<Axis.TickMark<Number>> yaTickMarks = yaxis.getTickMarks();
+        TickMark tm = yaTickMarks.get(0);
+        assertEquals(12, new Double(tm.textNode.getFont().getSize()).intValue());
+    }
 }
--- a/javafx-ui-common/src/com/sun/javafx/css/StyleManager.java	Thu Jun 14 14:06:12 2012 -0700
+++ b/javafx-ui-common/src/com/sun/javafx/css/StyleManager.java	Mon Jun 18 13:12:52 2012 -0700
@@ -746,7 +746,7 @@
         return mask;
     }
 
-    List<String> getPseudoclassStrings(long mask) {
+    public List<String> getPseudoclassStrings(long mask) {
         if (mask == 0) return Collections.EMPTY_LIST;
 
         Map<Long,String> stringMap = new HashMap<Long,String>();
--- a/javafx-ui-common/src/javafx/scene/layout/AnchorPane.java	Thu Jun 14 14:06:12 2012 -0700
+++ b/javafx-ui-common/src/javafx/scene/layout/AnchorPane.java	Mon Jun 18 13:12:52 2012 -0700
@@ -225,24 +225,24 @@
     public AnchorPane() {
         super();
     }
-
+    
     @Override protected double computeMinWidth(double height) {
-        return computeWidth(true);
+        return computeWidth(true, height);
     }
 
     @Override protected double computeMinHeight(double width) {
-        return computeHeight(true);
+        return computeHeight(true, width);
     }
 
     @Override protected double computePrefWidth(double height) {
-        return computeWidth(false);
+        return computeWidth(false, height);
     }
 
     @Override protected double computePrefHeight(double width) {
-        return computeHeight(false);
+        return computeHeight(false, width);
     }
 
-    private double computeWidth(boolean minimum) {
+    private double computeWidth(boolean minimum, double height) {
         double max = 0;
         for (int i = 0; i < getChildren().size(); i++) {
             Node child = getChildren().get(i);
@@ -253,14 +253,16 @@
                 double left = leftAnchor != null? leftAnchor :
                     (rightAnchor != null? 0 : child.getLayoutBounds().getMinX() + child.getLayoutX());
                 double right = rightAnchor != null? rightAnchor : 0;
-
-                max = Math.max(max, left + (minimum? child.minWidth(-1) : child.prefWidth(-1)) + right);
+                if (child.getContentBias() == Orientation.VERTICAL) {
+                    height = (minimum? child.minHeight(-1) : child.prefHeight(-1));
+                }
+                max = Math.max(max, left + (minimum? child.minWidth(height) : child.prefWidth(height)) + right);
             }
         }
         return getInsets().getLeft() + max + getInsets().getRight();
     }
 
-    private double computeHeight(boolean minimum) {
+    private double computeHeight(boolean minimum, double width) {
         double max = 0;
         for (int i = 0; i < getChildren().size(); i++) {
             Node child = getChildren().get(i);
@@ -270,9 +272,11 @@
 
                 double top = topAnchor != null? topAnchor :
                     (bottomAnchor != null? 0 : child.getLayoutBounds().getMinY() + child.getLayoutY());
-                double bottom = bottomAnchor != null? bottomAnchor : 0;
-
-                max = Math.max(max, top + (minimum? child.minHeight(-1) : child.prefHeight(-1)) + bottom);
+                double bottom = bottomAnchor != null? bottomAnchor : 0;                
+                if (child.getContentBias() == Orientation.HORIZONTAL) {
+                    width = (minimum? child.minWidth(-1) : child.prefWidth(-1));
+                }                  
+                max = Math.max(max, top + (minimum? child.minHeight(width) : child.prefHeight(width)) + bottom);
             }
         }
         return getInsets().getTop() + max + getInsets().getBottom();
@@ -294,7 +298,7 @@
 
     @Override protected void layoutChildren() {
         Insets insets = getInsets();
-
+        
         for (int i = 0; i < getChildren().size(); i++) {
             Node child = getChildren().get(i);
             if (child.isManaged()) {
--- a/javafx-ui-common/test/unit/javafx/scene/layout/AnchorPaneTest.java	Thu Jun 14 14:06:12 2012 -0700
+++ b/javafx-ui-common/test/unit/javafx/scene/layout/AnchorPaneTest.java	Mon Jun 18 13:12:52 2012 -0700
@@ -605,4 +605,23 @@
         assertEquals(30, resizable.getLayoutBounds().getWidth(), 1e-100);
         assertEquals(30, resizable.getLayoutBounds().getHeight(), 1e-100);
     }
+    
+    @Test public void testAnchorPanePrefHeightWithHorizontalBiasedChild_RT21745() {
+        AnchorPane anchorpane = new AnchorPane();
+        
+        AnchorPane internalAnchorpane = new AnchorPane();        
+
+        MockBiased biased = new MockBiased(Orientation.HORIZONTAL, 30, 256);
+                        
+        internalAnchorpane.getChildren().add(biased);
+        anchorpane.getChildren().add(internalAnchorpane);
+      
+        anchorpane.resize(500, 500);
+        anchorpane.layout();        
+        
+        assertEquals(30, anchorpane.prefWidth(-1), 1e-100);
+        assertEquals(256, anchorpane.prefHeight(-1), 1e-100);
+        assertEquals(30, internalAnchorpane.prefWidth(-1), 1e-100);
+        assertEquals(256, internalAnchorpane.prefHeight(-1), 1e-100);        
+    }    
 }
--- a/javafx-ui-controls/src/com/sun/javafx/scene/control/behavior/TabPaneBehavior.java	Thu Jun 14 14:06:12 2012 -0700
+++ b/javafx-ui-controls/src/com/sun/javafx/scene/control/behavior/TabPaneBehavior.java	Mon Jun 18 13:12:52 2012 -0700
@@ -145,7 +145,7 @@
         if (tab.isSelected()) {
             if (index == 0) {
                 if (tabPane.getTabs().size() > 1) {
-                    tabPane.getSelectionModel().selectFirst();
+                    tabPane.getSelectionModel().clearSelection();
                 }
             } else {
                 tabPane.getSelectionModel().selectPrevious();
--- a/javafx-ui-controls/src/com/sun/javafx/scene/control/behavior/TextAreaBehavior.java	Thu Jun 14 14:06:12 2012 -0700
+++ b/javafx-ui-controls/src/com/sun/javafx/scene/control/behavior/TextAreaBehavior.java	Mon Jun 18 13:12:52 2012 -0700
@@ -31,6 +31,7 @@
 import javafx.geometry.Point2D;
 import javafx.scene.Scene;
 import javafx.scene.control.ContextMenu;
+import javafx.scene.control.IndexRange;
 import javafx.scene.control.TextArea;
 import javafx.scene.input.MouseButton;
 import javafx.scene.input.MouseEvent;
@@ -47,6 +48,7 @@
 import static javafx.scene.input.KeyCode.*;
 import static javafx.scene.input.KeyEvent.*;
 import static com.sun.javafx.PlatformUtil.*;
+import javafx.geometry.Rectangle2D;
 
 
 /**
@@ -174,9 +176,23 @@
     @Override public void callAction(String name) {
         final TextArea textInputControl = getControl();
 
+        boolean done = false;
+
         if (textInputControl.isEditable()) {
 //            fnCaretAnim(false);
 //            setCaretOpacity(1.0);
+            setEditing(true);
+            done = true;
+            if ("InsertNewLine".equals(name)) insertNewLine();
+            else if ("InsertTab".equals(name)) insertTab();
+            else {
+                done = false;
+            }
+            setEditing(false);
+        }
+
+        if (!done) {
+            done = true;
             if ("LineStart".equals(name)) skin.lineStart(false, false);
             else if ("LineEnd".equals(name)) skin.lineEnd(false, false);
             else if ("SelectLineStart".equals(name)) skin.lineStart(true, false);
@@ -197,28 +213,35 @@
             else if ("NextPage".equals(name)) skin.nextPage(false);
             else if ("SelectPreviousPage".equals(name)) skin.previousPage(true);
             else if ("SelectNextPage".equals(name)) skin.nextPage(true);
-            else if ("InsertNewLine".equals(name)) insertNewLine();
-            else if ("InsertTab".equals(name)) insertTab();
-            else super.callAction(name);
+            else {
+                done = false;
+            }
+        }
 //            fnCaretAnim(true);
 
-        } else if ("Copy".equals(name)) {
-            // if the key event is for the "copy" action then we go ahead
-            // and execute it, but for all other key events which occur
-            // when not editable, we don't allow.
-            textInputControl.copy();
-        } else if (name.startsWith("Traverse")) {
-            // call super.callAction() for any focus traversal actions even if
-            // it's not editable
+        if (!done) {
             super.callAction(name);
         }
     }
 
     private void insertNewLine() {
-        getControl().replaceSelection("\n");
+        TextArea textArea = getControl();
+        IndexRange selection = textArea.getSelection();
+        int start = selection.getStart();
+        int end = selection.getEnd();
+
+        getUndoManager().addChange(start, textArea.getText().substring(start, end), "\n", false);
+        textArea.replaceSelection("\n");
     }
+
     private void insertTab() {
-        getControl().replaceSelection("\t");
+        TextArea textArea = getControl();
+        IndexRange selection = textArea.getSelection();
+        int start = selection.getStart();
+        int end = selection.getEnd();
+
+        getUndoManager().addChange(start, textArea.getText().substring(start, end), "\t", false);
+        textArea.replaceSelection("\t");
     }
 
     @Override protected void deleteChar(boolean previous) {
@@ -348,7 +371,7 @@
                 double screenX = e.getScreenX();
                 double screenY = e.getScreenY();
                 double sceneX = e.getSceneX();
-
+                
                 if (PlatformUtil.isEmbedded()) {
                     Point2D menuPos;
                     if (textArea.getSelection().getLength() == 0) {
@@ -373,19 +396,19 @@
                         screenY = location.getY();
                     }
                 }
-
+                
                 skin.populateContextMenu(contextMenu);
                 double menuWidth = contextMenu.prefWidth(-1);
                 double menuX = screenX - (PlatformUtil.isEmbedded() ? (menuWidth / 2) : 0);
-                Screen currentScreen = com.sun.javafx.Utils.getScreenForPoint(0, 0);
-                double maxWidth = currentScreen.getVisualBounds().getWidth();
+                Screen currentScreen = com.sun.javafx.Utils.getScreenForPoint(screenX, 0);
+                Rectangle2D bounds = currentScreen.getBounds();
 
-                if (menuX < 0) {
+                if (menuX < bounds.getMinX()) {
                     skin.getProperties().put("CONTEXT_MENU_SCREEN_X", screenX);
                     skin.getProperties().put("CONTEXT_MENU_SCENE_X", sceneX);
-                    contextMenu.show(getControl(), 0, screenY);
-                } else if (screenX + menuWidth > maxWidth) {
-                    double leftOver = menuWidth - (maxWidth - screenX);
+                    contextMenu.show(getControl(), bounds.getMinX(), screenY);
+                } else if (screenX + menuWidth > bounds.getMaxX()) {
+                    double leftOver = menuWidth - ( bounds.getMaxX() - screenX);
                     skin.getProperties().put("CONTEXT_MENU_SCREEN_X", screenX);
                     skin.getProperties().put("CONTEXT_MENU_SCENE_X", sceneX);
                     contextMenu.show(getControl(), screenX - leftOver, screenY);
--- a/javafx-ui-controls/src/com/sun/javafx/scene/control/behavior/TextFieldBehavior.java	Thu Jun 14 14:06:12 2012 -0700
+++ b/javafx-ui-controls/src/com/sun/javafx/scene/control/behavior/TextFieldBehavior.java	Mon Jun 18 13:12:52 2012 -0700
@@ -51,6 +51,7 @@
 import com.sun.javafx.scene.text.HitInfo;
 
 import static com.sun.javafx.PlatformUtil.*;
+import javafx.geometry.Rectangle2D;
 
 /**
  * Text field behavior.
@@ -314,15 +315,15 @@
                 skin.populateContextMenu(contextMenu);
                 double menuWidth = contextMenu.prefWidth(-1);
                 double menuX = screenX - (PlatformUtil.isEmbedded() ? (menuWidth / 2) : 0);
-                Screen currentScreen = com.sun.javafx.Utils.getScreenForPoint(0, 0);
-                double maxWidth = currentScreen.getVisualBounds().getWidth();
+                Screen currentScreen = com.sun.javafx.Utils.getScreenForPoint(screenX, 0);
+                Rectangle2D bounds = currentScreen.getBounds();
 
-                if (menuX < 0) {
+                if (menuX < bounds.getMinX()) {
                     skin.getProperties().put("CONTEXT_MENU_SCREEN_X", screenX);
                     skin.getProperties().put("CONTEXT_MENU_SCENE_X", sceneX);
-                    contextMenu.show(getControl(), 0, screenY);
-                } else if (screenX + menuWidth > maxWidth) {
-                    double leftOver = menuWidth - (maxWidth - screenX);
+                    contextMenu.show(getControl(), bounds.getMinX(), screenY);
+                } else if (screenX + menuWidth > bounds.getMaxX()) {
+                    double leftOver = menuWidth - ( bounds.getMaxX() - screenX);
                     skin.getProperties().put("CONTEXT_MENU_SCREEN_X", screenX);
                     skin.getProperties().put("CONTEXT_MENU_SCENE_X", sceneX);
                     contextMenu.show(getControl(), screenX - leftOver, screenY);
--- a/javafx-ui-controls/src/com/sun/javafx/scene/control/behavior/TextInputControlBehavior.java	Thu Jun 14 14:06:12 2012 -0700
+++ b/javafx-ui-controls/src/com/sun/javafx/scene/control/behavior/TextInputControlBehavior.java	Mon Jun 18 13:12:52 2012 -0700
@@ -177,6 +177,10 @@
         // Note, I don't have to worry about "Consume" here.
     }
 
+    protected UndoManager getUndoManager() {
+        return undoManager;
+    }
+
     /**
      * The default handler for a key typed event, which is called when none of
      * the other key bindings match. This is the method which handles basic
--- a/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/ButtonSkin.java	Thu Jun 14 14:06:12 2012 -0700
+++ b/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/ButtonSkin.java	Mon Jun 18 13:12:52 2012 -0700
@@ -68,7 +68,7 @@
     }
 
 
-    @Override protected void handleControlPropertyChanged(String p) {        
+    @Override protected void handleControlPropertyChanged(String p) {     
         super.handleControlPropertyChanged(p);
         if (p == "DEFAULT_BUTTON") {
             setDefaultButton(getSkinnable().isDefaultButton());
@@ -87,9 +87,13 @@
                 }
            }
         } else if (p == "PARENT") {
-            if (getSkinnable().getParent() == null) {
-                getScene().getAccelerators().remove(defaultAcceleratorKeyCodeCombination);
-                getScene().getAccelerators().remove(cancelAcceleratorKeyCodeCombination);
+            if (getSkinnable().getParent() == null && getScene() != null) {  
+                if (getSkinnable().isDefaultButton()) {
+                    getScene().getAccelerators().remove(defaultAcceleratorKeyCodeCombination);
+                }
+                if (getSkinnable().isCancelButton()) {
+                    getScene().getAccelerators().remove(cancelAcceleratorKeyCodeCombination);
+                }
             }
         }
     }
--- a/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/ComboBoxListViewSkin.java	Thu Jun 14 14:06:12 2012 -0700
+++ b/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/ComboBoxListViewSkin.java	Mon Jun 18 13:12:52 2012 -0700
@@ -31,6 +31,7 @@
 import javafx.scene.control.ComboBox;
 import com.sun.javafx.scene.control.behavior.ComboBoxListViewBehavior;
 import java.util.List;
+import javafx.application.Platform;
 import javafx.beans.InvalidationListener;
 import javafx.beans.Observable;
 import javafx.beans.value.ChangeListener;
@@ -124,9 +125,7 @@
         // move focus in to the textfield if the comboBox is editable
         comboBox.focusedProperty().addListener(new ChangeListener<Boolean>() {
             @Override public void changed(ObservableValue<? extends Boolean> ov, Boolean t, Boolean t1) {
-                if (textField == null) return;
-                if (! (textField instanceof FocusableTextField)) return;
-                ((FocusableTextField)textField).setFakeFocus(comboBox.isFocused());
+                updateFakeFocus(comboBox.isFocused());
             }
         });
         
@@ -156,12 +155,7 @@
         });
         
         // Fix for RT-19431 (also tested via ComboBoxListViewSkinTest)
-        updateValue(comboBox.getValue());
-        comboBox.valueProperty().addListener(new ChangeListener<T>() {
-            @Override public void changed(ObservableValue<? extends T> ov, T oldValue, T newValue) {
-                updateValue(newValue);
-            }
-        });
+        updateValue();
         
         registerChangeListener(comboBox.itemsProperty(), "ITEMS");
         registerChangeListener(comboBox.promptTextProperty(), "PROMPT_TEXT");
@@ -170,6 +164,7 @@
         registerChangeListener(comboBox.converterProperty(), "CONVERTER");
         registerChangeListener(comboBox.editorProperty(), "EDITOR");
         registerChangeListener(comboBox.buttonCellProperty(), "BUTTON_CELL");
+        registerChangeListener(comboBox.valueProperty(), "VALUE");
     }
     
     
@@ -209,6 +204,8 @@
             getEditableInputNode();
         } else if ("BUTTON_CELL".equals(p)) {
             updateButtonCell();
+        } else if ("VALUE".equals(p)) {
+            updateValue();
         }
     }
     
@@ -282,27 +279,41 @@
      *                                                                         *
      **************************************************************************/    
     
-    private void updateValue(T newValue) {
+    private void updateValue() {
+        T newValue = comboBox.getValue();
+        
+        SelectionModel sm = listView.getSelectionModel();
+        
         if (newValue == null) {
-            listView.getSelectionModel().clearSelection();
+            sm.clearSelection();
         } else {
-            int index = comboBox.getSelectionModel().getSelectedIndex();
-            if (index >= 0 && index < comboBox.getItems().size()) {
-                T itemsObj = comboBox.getItems().get(index);
-                if (itemsObj != null && itemsObj.equals(newValue)) {
-                    listView.getSelectionModel().select(index);
+            // RT-22386: We need to test to see if the value is in the comboBox
+            // items list. If it isn't, then we should clear the listview 
+            // selection
+            int indexOfNewValue = getIndexOfComboBoxValueInItemsList();
+            if (indexOfNewValue == -1) {
+                listSelectionLock = true;
+                sm.clearSelection();
+                listSelectionLock = false;
+            } else {
+                int index = comboBox.getSelectionModel().getSelectedIndex();
+                if (index >= 0 && index < comboBox.getItems().size()) {
+                    T itemsObj = comboBox.getItems().get(index);
+                    if (itemsObj != null && itemsObj.equals(newValue)) {
+                        sm.select(index);
+                    } else {
+                        sm.select(newValue);
+                    }
                 } else {
-                    listView.getSelectionModel().select(newValue);
-                }
-            } else {
-                // just select the first instance of newValue in the list
-                int listViewIndex = listView.getItems().indexOf(newValue);
-                if (listViewIndex == -1) {
-                    // RT-21336 Show the ComboBox value even though it doesn't
-                    // exist in the ComboBox items list (part one of fix)
-                    updateDisplayNode();
-                } else {
-                    listView.getSelectionModel().select(listViewIndex);
+                    // just select the first instance of newValue in the list
+                    int listViewIndex = listView.getItems().indexOf(newValue);
+                    if (listViewIndex == -1) {
+                        // RT-21336 Show the ComboBox value even though it doesn't
+                        // exist in the ComboBox items list (part one of fix)
+                        updateDisplayNode();
+                    } else {
+                        sm.select(listViewIndex);
+                    }
                 }
             }
         }
@@ -323,9 +334,20 @@
         textField.focusedProperty().addListener(new ChangeListener<Boolean>() {
             @Override public void changed(ObservableValue<? extends Boolean> ov, Boolean t, Boolean hasFocus) {
                 if (hasFocus) {
-                    comboBox.requestFocus();
+                    // Using Platform.runLater here, as without it it seems we
+                    // enter into some form of race condition where we are 
+                    // wanting to set focus on the comboBox whilst the textField
+                    // is still notifying of its focus gain.
+                    // This issue was identified in RT-21088.
+                    Platform.runLater(new Runnable() {
+                        @Override public void run() {
+                            comboBox.requestFocus();
+                        }
+                    });
                 }
                 
+                updateFakeFocus(hasFocus);
+                
                 // RT-21454 starts here
                 if (! hasFocus) {
                     setTextFromTextFieldIntoComboBoxValue();
@@ -336,6 +358,12 @@
         return textField;
     }
     
+    private void updateFakeFocus(boolean b) {
+        if (textField == null) return;
+        if (! (textField instanceof FocusableTextField)) return;
+        ((FocusableTextField)textField).setFakeFocus(b);
+    }
+    
     private void updateDisplayNode() {
         StringConverter<T> c = comboBox.getConverter();
         if (c == null) return;
@@ -349,7 +377,7 @@
                 textField.setText(stringValue);
             }
         } else {
-            int index = getSelectedIndex();
+            int index = getIndexOfComboBoxValueInItemsList();
             if (index > -1) {
                 buttonCell.updateListView(listView);
                 buttonCell.updateIndex(index);
@@ -397,7 +425,7 @@
         comboBox.setValue(value);
     }
     
-    private int getSelectedIndex() {
+    private int getIndexOfComboBoxValueInItemsList() {
         T value = comboBox.getValue();
         int index = comboBox.getItems().indexOf(value);
         return index;
--- a/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/ContextMenuContent.java	Thu Jun 14 14:06:12 2012 -0700
+++ b/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/ContextMenuContent.java	Mon Jun 18 13:12:52 2012 -0700
@@ -130,8 +130,8 @@
         setUpBinds();
     }
     
-       //For testing purpose only
-    VBox getItemsContainer() {
+    //For access from controls
+    public VBox getItemsContainer() {
         return itemsContainer;
     }
     //For testing purpose only
@@ -198,7 +198,7 @@
             }
         }
     }
-
+    
     private void updateVisualItems() {
         itemsContainer.getChildren().clear();
         for (int row = 0; row < getItems().size(); row++) {
@@ -981,7 +981,7 @@
      * words, this contains and lays out a single MenuItem, regardless of it's 
      * specific subtype.
      */
-    class MenuItemContainer extends Pane {
+    public class MenuItemContainer extends Pane {
 
         private final MenuItem item;
 
@@ -994,7 +994,7 @@
             return (Label) label;
         }
         
-        protected MenuItem getItem() {
+        public MenuItem getItem() {
             return item;
         }
 
--- a/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/MenuBarSkin.java	Thu Jun 14 14:06:12 2012 -0700
+++ b/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/MenuBarSkin.java	Mon Jun 18 13:12:52 2012 -0700
@@ -90,13 +90,30 @@
     private boolean firstF10 = true;
 
     private static WeakHashMap<Stage, MenuBarSkin> systemMenuMap;
-    private static List<MenuBase> emptyMenuList = new ArrayList<MenuBase>();
+    private static List<MenuBase> wrappedDefaultMenus = new ArrayList<MenuBase>();
     private static Stage currentMenuBarStage;
     private List<MenuBase> wrappedMenus;
 
+    public static void setDefaultSystemMenuBar(final MenuBar menuBar) {
+        if (Toolkit.getToolkit().getSystemMenu().isSupported()) {
+            wrappedDefaultMenus.clear();
+            for (Menu menu : menuBar.getMenus()) {
+                wrappedDefaultMenus.add(GlobalMenuAdapter.adapt(menu));
+            }
+            menuBar.getMenus().addListener(new ListChangeListener<Menu>() {
+                @Override public void onChanged(Change<? extends Menu> c) {
+                    wrappedDefaultMenus.clear();
+                    for (Menu menu : menuBar.getMenus()) {
+                        wrappedDefaultMenus.add(GlobalMenuAdapter.adapt(menu));
+                    }
+                }
+            });
+        }
+    }
+
     private static void setSystemMenu(Stage stage) {
-        if (stage.isFocused()) {
-            while (stage.getOwner() instanceof Stage) {
+        if (stage != null && stage.isFocused()) {
+            while (stage != null && stage.getOwner() instanceof Stage) {
                 MenuBarSkin skin = systemMenuMap.get(stage);
                 if (skin != null && skin.wrappedMenus != null) {
                     break;
@@ -108,15 +125,23 @@
                     stage = (Stage)stage.getOwner();
                 }
             }
-            if (stage != currentMenuBarStage) {
-                List<MenuBase> menuList = null;
+        } else {
+            stage = null;
+        }
+
+        if (stage != currentMenuBarStage) {
+            List<MenuBase> menuList = null;
+            if (stage != null) {
                 MenuBarSkin skin = systemMenuMap.get(stage);
                 if (skin != null) {
                     menuList = skin.wrappedMenus;
                 }
-                Toolkit.getToolkit().getSystemMenu().setMenus((menuList != null) ? menuList : emptyMenuList);
-                currentMenuBarStage = stage;
             }
+            if (menuList == null) {
+                menuList = wrappedDefaultMenus;
+            }
+            Toolkit.getToolkit().getSystemMenu().setMenus(menuList);
+            currentMenuBarStage = stage;
         }
     }
 
@@ -310,11 +335,13 @@
             public void changed(ObservableValue<? extends Scene> ov, Scene t, Scene t1) {
                 if (weakSceneKeyEventHandler != null) {
                     // remove event filter from the old scene (t)
-                    t.removeEventFilter(KeyEvent.KEY_PRESSED, weakSceneKeyEventHandler);
+                    if (t != null)
+                        t.removeEventFilter(KeyEvent.KEY_PRESSED, weakSceneKeyEventHandler);
                 }
                 if (weakSceneMouseEventHandler != null) {
                     // remove event filter from the old scene (t)
-                    t.removeEventFilter(MouseEvent.MOUSE_CLICKED, weakSceneMouseEventHandler);
+                    if (t != null)
+                        t.removeEventFilter(MouseEvent.MOUSE_CLICKED, weakSceneMouseEventHandler);
                 }
             }
         });
--- a/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/NestedTableColumnHeader.java	Thu Jun 14 14:06:12 2012 -0700
+++ b/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/NestedTableColumnHeader.java	Mon Jun 18 13:12:52 2012 -0700
@@ -51,7 +51,7 @@
  * TableHeaderRow class consists of just one instance of a NestedTableColumnHeader.
  *
  */
-class NestedTableColumnHeader extends TableColumnHeader {
+public class NestedTableColumnHeader extends TableColumnHeader {
     
     /***************************************************************************
      *                                                                         *
@@ -158,13 +158,25 @@
         // clear the column headers list before we recreate them
         getColumnHeaders().clear();
         
-        // then iterate through all columns.
-        for (int i = 0; i < getColumns().size(); i++) {
-            TableColumn<?,?> column = getColumns().get(i);
-            
-            if (column == null) continue;
-            
-            getColumnHeaders().add(createColumnHeader(column));
+        // then iterate through all columns, unless we've got no child columns
+        // any longer, in which case we should switch to a TableColumnHeader 
+        // instead
+        if (getColumns().isEmpty()) {
+            // switch out to be a TableColumn instead
+            NestedTableColumnHeader parentHeader = getParentHeader();
+            if (parentHeader != null) {
+                TableColumnHeader newHeader = createColumnHeader(getTableColumn());
+                int index = parentHeader.getColumnHeaders().indexOf(this);
+                parentHeader.getColumnHeaders().set(index, newHeader);
+            }
+        } else {
+            for (int i = 0; i < getColumns().size(); i++) {
+                TableColumn<?,?> column = getColumns().get(i);
+
+                if (column == null) continue;
+
+                getColumnHeaders().add(createColumnHeader(column));
+            }
         }
 
         // update the content
--- a/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/ScrollPaneSkin.java	Thu Jun 14 14:06:12 2012 -0700
+++ b/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/ScrollPaneSkin.java	Mon Jun 18 13:12:52 2012 -0700
@@ -787,8 +787,22 @@
         if (vsbvis) {
             /*
             ** round up position of ScrollBar, round down it's size.
+            **
+            ** Positioning the ScrollBar
+            **  The Padding should go between the content and the edge,
+            **  otherwise changes in padding move the ScrollBar, and could
+            **  in extreme cases size the ScrollBar to become unusable.
+            **  The -1, +1 plus one bit : 
+            **   If padding in => 1 then we allow one pixel to appear as the
+            **   outside border of the Scrollbar, and the rest on the inside.
+            **   If padding is < 1 then we just stick to the edge.
             */
-            vsb.resizeRelocate(snapPosition(control.getWidth() - (vsbWidth + (getInsets().getRight()-getPadding().getRight()))), snapPosition(cy), snapSize(vsbWidth), snapSize(vsbHeight));
+            if (getPadding().getRight() < 1) {
+                vsb.resizeRelocate(snapPosition(control.getWidth() - (vsbWidth + (getInsets().getRight()-getPadding().getRight()))), snapPosition(cy), snapSize(vsbWidth), snapSize(vsbHeight));
+            }
+            else {
+                vsb.resizeRelocate(snapPosition(control.getWidth() - ((vsbWidth+1) + (getInsets().getRight()-getPadding().getRight()))), snapPosition(cy), snapSize(vsbWidth)+1, snapSize(vsbHeight));
+            }
         }
         updateVerticalSB();
 
@@ -796,8 +810,22 @@
         if (hsbvis) {
             /*
             ** round up position of ScrollBar, round down it's size.
+            **
+            ** Positioning the ScrollBar
+            **  The Padding should go between the content and the edge,
+            **  otherwise changes in padding move the ScrollBar, and could
+            **  in extreme cases size the ScrollBar to become unusable.
+            **  The -1, +1 plus one bit : 
+            **   If padding in => 1 then we allow one pixel to appear as the
+            **   outside border of the Scrollbar, and the rest on the inside.
+            **   If padding is < 1 then we just stick to the edge.
             */
-            hsb.resizeRelocate(snapPosition(cx), snapPosition(control.getHeight() - (hsbHeight + (getInsets().getBottom()-getPadding().getBottom()))), snapSize(hsbWidth), snapSize(hsbHeight));
+            if (getPadding().getBottom() < 1) {
+                hsb.resizeRelocate(snapPosition(cx), snapPosition(control.getHeight() - (hsbHeight + (getInsets().getBottom()-getPadding().getBottom()))), snapSize(hsbWidth), snapSize(hsbHeight));
+            }
+            else {
+                hsb.resizeRelocate(snapPosition(cx), snapPosition(control.getHeight() - ((hsbHeight+1) + (getInsets().getBottom()-getPadding().getBottom()))), snapSize(hsbWidth), snapSize(hsbHeight)+1);
+            }
         }
         updateHorizontalSB();
 
--- a/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/SplitPaneSkin.java	Thu Jun 14 14:06:12 2012 -0700
+++ b/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/SplitPaneSkin.java	Mon Jun 18 13:12:52 2012 -0700
@@ -357,7 +357,7 @@
                     c.setAvailable(c.getArea() - min);
                     size -= portion;
                 }
-                if (size == 0) {
+                if ((int)size == 0) {
                     return size;
                 }
             }
@@ -402,7 +402,7 @@
                     c.setAvailable(c.getAvailable() - portion);
                     size -= portion;
                 }
-                if (size == 0) {
+                if ((int)size == 0) {
                     return size;
                 }
             }
@@ -1102,11 +1102,11 @@
         }
 
         @Override protected double computeMaxWidth(double height) {
-            return content.maxWidth(height);
+            return snapSize(content.maxWidth(height));
         }
 
         @Override protected double computeMaxHeight(double width) {
-            return content.maxHeight(width);
+            return snapSize(content.maxHeight(width));
         }
     }
 }
--- a/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/TableColumnHeader.java	Thu Jun 14 14:06:12 2012 -0700
+++ b/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/TableColumnHeader.java	Mon Jun 18 13:12:52 2012 -0700
@@ -246,7 +246,7 @@
     private Label label;
 
     // sort order 
-    private int sortPos;
+    private int sortPos = -1;
     private StackPane arrow;
     private Label sortOrderLabel;
     private HBox sortOrderDots;
@@ -283,6 +283,7 @@
         if (getTableColumn() != null) {
             getTableColumn().visibleProperty().removeListener(weakVisibleListener);
             getTableColumn().widthProperty().removeListener(weakWidthListener);
+            getTableColumn().sortTypeProperty().removeListener(weakSortTypeListener);
         }
         
         sceneProperty().removeListener(sceneListener);
--- a/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/TableHeaderRow.java	Thu Jun 14 14:06:12 2012 -0700
+++ b/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/TableHeaderRow.java	Mon Jun 18 13:12:52 2012 -0700
@@ -58,7 +58,7 @@
 /**
  * Region responsible for painting the entire row of column headers.
  */
-class TableHeaderRow extends StackPane {
+public class TableHeaderRow extends StackPane {
     
     private static final String MENU_SEPARATOR = 
             ControlResources.getString("TableView.nestedColumnControlMenuSeparator");
@@ -157,6 +157,10 @@
      * at that level.
      */
     private final NestedTableColumnHeader header;
+    
+    public NestedTableColumnHeader getRootHeader() {
+        return header;
+    }
 
     private Region filler;
 
--- a/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/TableRowSkin.java	Thu Jun 14 14:06:12 2012 -0700
+++ b/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/TableRowSkin.java	Mon Jun 18 13:12:52 2012 -0700
@@ -27,7 +27,6 @@
 
 
 import java.util.ArrayList;
-import java.util.HashMap;
 import java.util.List;
 import java.util.WeakHashMap;
 
@@ -188,6 +187,8 @@
         }
     }
 
+    private int columnCount = 0;
+    
     private void recreateCells() {
         // This function is smart in the sense that we don't recreate all
         // TableCell instances every time this function is called. Instead we
@@ -205,11 +206,13 @@
         
         ObservableList<TableColumn<T,?>> columns = table.getVisibleLeafColumns();
         
-        if (fullRefreshCounter == 0 || cellsMap == null) {
+        if (columns.size() != columnCount || fullRefreshCounter == 0 || cellsMap == null) {
             clearCellsMap();
             cellsMap = new WeakHashMap<TableColumn, TableCell>(columns.size());
             fullRefreshCounter = DEFAULT_FULL_REFRESH_COUNTER;
+            getChildren().clear();
         }
+        columnCount = columns.size();
         fullRefreshCounter--;
         
         for (TableColumn col : columns) {
--- a/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/TableViewSkin.java	Thu Jun 14 14:06:12 2012 -0700
+++ b/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/TableViewSkin.java	Mon Jun 18 13:12:52 2012 -0700
@@ -311,7 +311,14 @@
      *                                                                         *
      * Public API                                                              *
      *                                                                         *
-     **************************************************************************/    
+     **************************************************************************/  
+    
+    /**
+     * 
+     */
+    public TableHeaderRow getTableHeaderRow() {
+        return tableHeaderRow;
+    }
     
     /** {@inheritDoc} */
     @Override public int getItemCount() {
--- a/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/TextFieldSkin.java	Thu Jun 14 14:06:12 2012 -0700
+++ b/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/TextFieldSkin.java	Mon Jun 18 13:12:52 2012 -0700
@@ -690,8 +690,9 @@
 
             x = bounds.getMinX();
             y = bounds.getMinY();
-            width = bounds.getWidth();
-            height = bounds.getHeight();
+            // Sometimes the bounds is empty, in which case we must ignore the width/height
+            width  = bounds.isEmpty() ? 0 : bounds.getWidth();
+            height = bounds.isEmpty() ? 0 : bounds.getHeight();
         }
 
         Bounds textBounds = textGroup.getBoundsInParent();
--- a/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/VirtualFlow.java	Thu Jun 14 14:06:12 2012 -0700
+++ b/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/VirtualFlow.java	Mon Jun 18 13:12:52 2012 -0700
@@ -1325,12 +1325,34 @@
                 topPadding = bottomPadding = leftPadding = rightPadding = 0.0;
             }
 
+            /*
+            ** Positioning the ScrollBar
+            **  The Padding should go between the content and the edge,
+            **  otherwise changes in padding move the ScrollBar, and could
+            **  in extreme cases size the ScrollBar to become unusable.
+            **  The -1, +1 plus one bit : 
+            **   If padding in => 1 then we allow one pixel to appear as the
+            **   outside border of the Scrollbar, and the rest on the inside.
+            **   If padding is < 1 then we just stick to the edge.
+            */
             if (isVertical()) {
-                hbar.resizeRelocate(0-leftPadding, viewportLength+topPadding,
-                                    viewportBreadth+(leftPadding+rightPadding), hbar.prefHeight(viewportBreadth));
+                if (bottomPadding < 1) {
+                    hbar.resizeRelocate(0-leftPadding, viewportLength+bottomPadding,
+                                        viewportBreadth+(leftPadding+rightPadding), hbar.prefHeight(viewportBreadth));
+                }
+                else {
+                    hbar.resizeRelocate(0-leftPadding, viewportLength+bottomPadding-1,
+                                        viewportBreadth+(leftPadding+rightPadding), hbar.prefHeight(viewportBreadth)+1);
+                }
             } else {
-                vbar.resizeRelocate(viewportLength+leftPadding, 0-topPadding,
-                                    vbar.prefWidth(viewportBreadth), viewportBreadth+(topPadding+bottomPadding));
+                if (rightPadding < 1) {
+                    vbar.resizeRelocate(viewportLength+rightPadding, 0-topPadding,
+                                        vbar.prefWidth(viewportBreadth), viewportBreadth+(topPadding+bottomPadding));
+                }
+                else {
+                    vbar.resizeRelocate(viewportLength+rightPadding-1, 0-topPadding,
+                                        vbar.prefWidth(viewportBreadth)+1, viewportBreadth+(topPadding+bottomPadding));
+                }
             }
 
             // There was a weird bug where the newMax would sometimes go < 0
@@ -1388,10 +1410,30 @@
                 topPadding = bottomPadding = leftPadding = rightPadding = 0.0;
             }
 
+            /*
+            ** Positioning the ScrollBar
+            **  The Padding should go between the content and the edge,
+            **  otherwise changes in padding move the ScrollBar, and could
+            **  in extreme cases size the ScrollBar to become unusable.
+            **  The -1, +1 plus one bit : 
+            **   If padding in => 1 then we allow one pixel to appear as the
+            **   outside border of the Scrollbar, and the rest on the inside.
+            **   If padding is < 1 then we just stick to the edge.
+            */
             if (isVertical()) {
-                vbar.resizeRelocate(viewportBreadth+leftPadding, 0-topPadding, vbar.prefWidth(viewportLength), viewportLength+(topPadding+bottomPadding));
+                if (rightPadding < 1) {
+                    vbar.resizeRelocate(viewportBreadth+rightPadding, 0-topPadding, vbar.prefWidth(viewportLength), viewportLength+(topPadding+bottomPadding));
+                }
+                else {
+                    vbar.resizeRelocate(viewportBreadth+rightPadding-1, 0-topPadding, vbar.prefWidth(viewportLength)+1, viewportLength+(topPadding+bottomPadding));
+                }
             } else {
-                hbar.resizeRelocate(0-leftPadding, viewportBreadth+topPadding, viewportLength+(leftPadding+rightPadding), hbar.prefHeight(-1));
+                if (bottomPadding < 1) {
+                    hbar.resizeRelocate(0-leftPadding, viewportBreadth+bottomPadding, viewportLength+(leftPadding+rightPadding), hbar.prefHeight(-1));
+                }
+                else {
+                    hbar.resizeRelocate(0-leftPadding, viewportBreadth+bottomPadding-1, viewportLength+(leftPadding+rightPadding), hbar.prefHeight(-1)+1);
+                }
             }
         }
 
--- a/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/caspian/caspian.css	Thu Jun 14 14:06:12 2012 -0700
+++ b/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/caspian/caspian.css	Mon Jun 18 13:12:52 2012 -0700
@@ -1143,13 +1143,10 @@
 
 .slider .axis {
     -fx-tick-mark-stroke: ladder(-fx-background, derive(-fx-background,30%) 40%, derive(-fx-background,-30%) 41%);
-    -fx-tick-label-font-size: 0.916667em; /* 11pt - 1 less than the default font */
-}
-
-.slider .axis .tick-mark {
-    -fx-font-size: 0.833333em;
-    -fx-fill: -fx-text-background-color;
-}
+    -fx-tick-label-font: 0.833333em System; 
+    -fx-tick-label-fill: -fx-text-background-color;
+}
+
 .slider:disabled {
     -fx-opacity: -fx-disabled-opacity;
 }
@@ -2749,6 +2746,10 @@
 }
 
 /* ====== AXIS ============================================================================ */
+.axis {
+    -fx-tick-label-font: 0.833333em System; /* 10 pix */
+    -fx-tick-label-fill: -fx-text-background-color;
+}
 .axis:top {
     -fx-border-color: transparent transparent #666666 transparent;
 }
@@ -2770,7 +2771,7 @@
     -fx-stroke: #AAAAAA;
 }
 
-.tick-mark {
+.axis .text {
   -fx-font-smoothing-type: lcd;
 }
 
--- a/javafx-ui-controls/src/javafx/scene/chart/Axis.java	Thu Jun 14 14:06:12 2012 -0700
+++ b/javafx-ui-controls/src/javafx/scene/chart/Axis.java	Mon Jun 18 13:12:52 2012 -0700
@@ -73,7 +73,7 @@
 
     // -------------- PRIVATE FIELDS -----------------------------------------------------------------------------------
 
-    private Text measure = new Text();
+    Text measure = new Text();
     private Label axisLabel = new Label();
     private final Path tickMarkPath = new Path();
     private double oldLength = 0;
@@ -81,8 +81,6 @@
     private boolean rangeValid = false;
     double maxWidth = 0;
     double maxHeight = 0;
-    private boolean tickLabelFontPropertySet = false;
-    private boolean tickLabelFillPropertySet = false;
     // -------------- PUBLIC PROPERTIES --------------------------------------------------------------------------------
 
     private final ObservableList<TickMark<T>> tickMarks = FXCollections.observableArrayList();
@@ -258,7 +256,9 @@
         @Override protected void invalidated() {
             Font f = get();
             measure.setFont(f);
-            tickLabelFontPropertySet = true;
+            for(TickMark<T> tm : getTickMarks()) {
+                tm.textNode.setFont(f);
+            }
             requestAxisLayout();
         }
 
@@ -284,7 +284,6 @@
     /** The fill for all tick labels */
     private ObjectProperty<Paint> tickLabelFill = new StyleableObjectProperty<Paint>(Color.BLACK) {
         @Override protected void invalidated() {
-            tickLabelFillPropertySet = true;
             requestAxisLayout();
         }
 
@@ -379,7 +378,6 @@
         axisLabel.setAlignment(Pos.CENTER);
         tickMarkPath.getStyleClass().add("axis-tick-mark");
         getChildren().addAll(axisLabel, tickMarkPath);
-        measure.getStyleClass().addAll("text", "tick-mark");
     }
 
     // -------------- METHODS ------------------------------------------------------------------------------------------
@@ -690,15 +688,8 @@
                 final TickMark<T> tick = new TickMark<T>();
                 tick.setValue(newValue);
                 tick.textNode.setText(getTickMarkLabel(newValue));
-                // RT-19870 : font & fill is set on text node if it is set programmatically.
-                // else it will take what ever is specified via CSS
-                if (tickLabelFontPropertySet) {
-                    tick.textNode.setFont(getTickLabelFont());
-                }
-                if (tickLabelFillPropertySet) {
-                    tick.textNode.setFill(getTickLabelFill());
-                }
-                
+                tick.textNode.setFont(getTickLabelFont());
+                tick.textNode.setFill(getTickLabelFill());
                 tick.setTextVisible(isTickLabelsVisible());
                 if (shouldAnimate()) tick.textNode.setOpacity(0);
                 getChildren().add(tick.textNode);
@@ -985,7 +976,7 @@
         public final void setPosition(double value) { position.set(value); }
         public final DoubleExpression positionProperty() { return position; }
 
-        private Text textNode = new Text();
+        Text textNode = new Text();
 
         /** true if tick mark labels should be displayed */
         private BooleanProperty textVisible = new BooleanPropertyBase(true) {
@@ -1017,7 +1008,6 @@
          * Creates and initializes an instance of TickMark. 
          */
         public TickMark() {
-            textNode.getStyleClass().addAll("text", "tick-mark");
         }
 
         /**
--- a/javafx-ui-controls/src/javafx/scene/chart/ValueAxis.java	Thu Jun 14 14:06:12 2012 -0700
+++ b/javafx-ui-controls/src/javafx/scene/chart/ValueAxis.java	Mon Jun 18 13:12:52 2012 -0700
@@ -271,8 +271,13 @@
      */
     @Override protected final Object autoRange(double length) {
         // guess a sensible starting size for label size, that is approx 2 lines vertically or 2 charts horizontally        
-        double labelSize = getTickLabelFont().getSize() * 2;
-        return autoRange(dataMinValue,dataMaxValue,length,labelSize);
+        if (isAutoRanging()) {
+            // guess a sensible starting size for label size, that is approx 2 lines vertically or 2 charts horizontally
+            double labelSize = getTickLabelFont().getSize() * 2;
+            return autoRange(dataMinValue,dataMaxValue,length,labelSize);
+        } else {
+            return getRange();
+        }
     }
 
     /**
@@ -310,7 +315,9 @@
      * @return The calculated range
      */
     protected Object autoRange(double minValue, double maxValue, double length, double labelSize) {
-        return new Double[]{minValue,maxValue};
+        return null; // this method should have been abstract as there is no way for it to 
+        // return anything correct. so just return null.
+        
     }
 
     /**
--- a/javafx-ui-controls/src/javafx/scene/control/Labeled.java	Thu Jun 14 14:06:12 2012 -0700
+++ b/javafx-ui-controls/src/javafx/scene/control/Labeled.java	Mon Jun 18 13:12:52 2012 -0700
@@ -318,9 +318,7 @@
                     // css might need to be reapplied since font size affects
                     // calculated values for styles with relative values
                     Stylesheet.Origin origin = StyleableProperty.getOrigin(font);
-                    if (origin == null || origin == Stylesheet.Origin.USER) {
-                        Labeled.this.impl_reapplyCSS();
-                    }
+                    if (origin == Stylesheet.Origin.USER) Labeled.this.impl_reapplyCSS();
                 }
                 
                 @Override 
--- a/javafx-ui-controls/src/javafx/scene/control/ListView.java	Thu Jun 14 14:06:12 2012 -0700
+++ b/javafx-ui-controls/src/javafx/scene/control/ListView.java	Mon Jun 18 13:12:52 2012 -0700
@@ -979,6 +979,8 @@
          **********************************************************************/
 
         private final ListView<T> listView;
+        
+        private int previousModelSize = 0;
 
         // Listen to changes in the listview items list, such that when it 
         // changes we can update the selected indices bitset to refer to the 
@@ -1007,9 +1009,13 @@
                         // the entire items list was emptied - clear selection
                         clearSelection();
                     } else {
-                        // Fix for RT-18969: the list had setAll called on it
                         int index = getSelectedIndex();
-                        if (index < getItemCount() && index >= 0) {
+                        
+                        if (previousModelSize == c.getRemovedSize()) {
+                            // all items were removed from the model
+                            clearSelection();
+                        } else if (index < getItemCount() && index >= 0) {
+                            // Fix for RT-18969: the list had setAll called on it
                             // Use of makeAtomic is a fix for RT-20945
                             makeAtomic = true;
                             clearSelection(index);
@@ -1077,6 +1083,8 @@
                     }
                 }
             }
+            
+            previousModelSize = getItemCount();
         }
 
 
--- a/javafx-ui-controls/src/javafx/scene/control/MenuItem.java	Thu Jun 14 14:06:12 2012 -0700
+++ b/javafx-ui-controls/src/javafx/scene/control/MenuItem.java	Mon Jun 18 13:12:52 2012 -0700
@@ -47,12 +47,15 @@
 import javafx.scene.input.KeyCombination;
 
 import com.sun.javafx.event.EventHandlerManager;
+import com.sun.javafx.scene.control.skin.ContextMenuContent;
+import com.sun.javafx.scene.control.skin.ContextMenuSkin;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
 import javafx.beans.property.ReadOnlyObjectProperty;
 import javafx.beans.property.ReadOnlyObjectWrapper;
 import javafx.collections.ObservableMap;
+import javafx.scene.Parent;
 
 /**
  * <p>
@@ -101,6 +104,9 @@
      *                                                                         *
      **************************************************************************/
 
+    /**
+     * Constructs a MenuItem with no display text.
+     */
     public MenuItem() {
         this(null,null);
     }
@@ -147,6 +153,10 @@
      *                                                                         *
      **************************************************************************/
     
+    /**
+     * The id of this MenuItem. This simple string identifier is useful for finding
+     * a specific MenuItem within the scene graph. 
+     */
     private StringProperty id;
     public final void setId(String value) { idProperty().set(value); }
     public final String getId() { return id == null ? null : id.get(); }
@@ -157,6 +167,12 @@
         return id;
     }
     
+    /**
+     * A string representation of the CSS style associated with this specific MenuItem. 
+     * This is analogous to the "style" attribute of an HTML element. Note that, 
+     * like the HTML style attribute, this variable contains style properties and 
+     * values and not the selector portion of a style rule.
+     */
     private StringProperty style;
     public final void setStyle(String value) { styleProperty().set(value); }
     public final String getStyle() { return style == null ? null : style.get(); }
@@ -168,8 +184,6 @@
     }
     
     // --- Parent Menu (useful for submenus)
-    private ReadOnlyObjectWrapper<Menu> parentMenu;
-
     /**
      * This is the {@link Menu} in which this {@code MenuItem} exists. It is
      * possible for an instance of this class to not have a {@code parentMenu} -
@@ -181,6 +195,8 @@
      * {@link Menu} internally.
      * </ul>
      */
+    private ReadOnlyObjectWrapper<Menu> parentMenu;
+
     protected final void setParentMenu(Menu value) {
         parentMenuPropertyImpl().set(value);
     }
@@ -202,11 +218,11 @@
 
 
     // --- Parent Popup
+     /**
+     * This is the {@link ContextMenu} in which this {@code MenuItem} exists.
+     */
     private ReadOnlyObjectWrapper<ContextMenu> parentPopup;
 
-    /**
-     * This is the {@link ContextMenu} in which this {@code MenuItem} exists.
-     */
     protected final void setParentPopup(ContextMenu value) {
         parentPopupPropertyImpl().set(value);
     }
@@ -228,11 +244,11 @@
 
 
     // --- Text
-    private StringProperty text;
-
     /**
      * The text to display in the {@code MenuItem}.
      */
+    private StringProperty text;
+
     public final void setText(String value) {
         textProperty().set(value);
     }
@@ -250,13 +266,13 @@
 
 
     // --- Graphic
-    private ObjectProperty<Node> graphic;
-
     /**
      * An optional graphic for the {@code MenuItem}. This will normally be
      * an {@link javafx.scene.image.ImageView} node, but there is no requirement for this to be
      * the case.
      */
+    private ObjectProperty<Node> graphic;
+    
     public final void setGraphic(Node value) {
         graphicProperty().set(value);
     }
@@ -274,14 +290,14 @@
     
 
     // --- OnAction
-    private ObjectProperty<EventHandler<ActionEvent>> onAction;
-
     /**
      * The action, which is invoked whenever the MenuItem is fired. This
      * may be due to the user clicking on the button with the mouse, or by
      * a touch event, or by a key press, or if the developer programatically
      * invokes the {@link #fire()} method.
      */
+    private ObjectProperty<EventHandler<ActionEvent>> onAction;
+
     public final void setOnAction(EventHandler<ActionEvent> value) {
         onActionProperty().set( value);
     }
@@ -315,12 +331,14 @@
      * <p>Called when a accelerator for the Menuitem is invoked</p>
      */
     public final EventType<Event> MENU_VALIDATION_EVENT = new EventType<Event>();
-    private ObjectProperty<EventHandler<Event>> onMenuValidation;
+    
     /**
      * The event handler that is associated with invocation of an accelerator for a MenuItem. This 
      * can happen when a key sequence for an accelerator is pressed. The event handler is also  
      * invoked when onShowing event handler is called. 
      */
+    private ObjectProperty<EventHandler<Event>> onMenuValidation;
+    
     public final void setOnMenuValidation(EventHandler<Event> value) {
         onMenuValidationProperty().set( value);
     }
@@ -347,6 +365,10 @@
     }
     
     // --- Disable
+    /** 
+     * Sets the individual disabled state of this MenuItem.
+     * Setting disable to true will cause this MenuItem to become disabled.
+     */
     private BooleanProperty disable;
     public final void setDisable(boolean value) { disableProperty().set(value); }
     public final boolean isDisable() { return disable == null ? false : disable.get(); }
@@ -359,6 +381,9 @@
 
 
     // --- Visible
+    /**
+     * Specifies whether this MenuItem should be rendered as part of the scene graph. 
+     */
     private BooleanProperty visible;
     public final void setVisible(boolean value) { visibleProperty().set(value); }
     public final boolean isVisible() { return visible == null ? true : visible.get(); }
@@ -369,7 +394,10 @@
         return visible;
     }
 
- 
+    /**
+     * The accelerator property enables accessing the associated action in one keystroke.
+     * It is a convenience offered to perform quickly a given action. 
+     */
     private ObjectProperty<KeyCombination> accelerator;
     public final void setAccelerator(KeyCombination value) {
         acceleratorProperty().set(value);
@@ -516,12 +544,14 @@
 
     private static final String DEFAULT_STYLE_CLASS = "menu-item";
 
-    protected Styleable styleable; 
     /**
      * RT-19263
      * @treatAsPrivate implementation detail
-     * @deprecated This is an experimental API that is not intended for general use and is subject to change in future versions
-     */    
+     * @deprecated This is an experimental API that is not intended for general 
+     * use and is subject to change in future versions
+     */
+    protected Styleable styleable; 
+        
     @Deprecated // SB-dependency: RT-21094 has been filed to track this
     public Styleable impl_getStyleable() {
         
@@ -545,13 +575,16 @@
 
                 @Override
                 public Styleable getStyleableParent() {
-                    if(MenuItem.this.getParentMenu() == null) {
-                        return MenuItem.this.getParentPopup() != null 
-                            ? MenuItem.this.getParentPopup().impl_getStyleable()
+                    Menu parentMenu = MenuItem.this.getParentMenu();
+                    ContextMenu parentPopup = MenuItem.this.getParentPopup();
+                    
+                    if(parentMenu == null) {
+                        return parentPopup != null 
+                            ? parentPopup.impl_getStyleable()
                             : null;
                     } else {
-                        return MenuItem.this.getParentMenu() != null 
-                            ? MenuItem.this.getParentMenu().impl_getStyleable()
+                        return parentMenu != null 
+                            ? parentMenu.impl_getStyleable()
                             : null;
                     }
                 }
@@ -564,6 +597,30 @@
 
                 @Override
                 public Node getNode() {
+                    // Fix for RT-20582. We dive into the visual representation
+                    // of this MenuItem so that we may return it to the caller.
+                    ContextMenu parentPopup = MenuItem.this.getParentPopup();
+                    if (! (parentPopup.getSkin() instanceof ContextMenuSkin)) return null;
+                    
+                    ContextMenuSkin skin = (ContextMenuSkin) parentPopup.getSkin();
+                    if (! (skin.getNode() instanceof ContextMenuContent)) return null;
+                    
+                    ContextMenuContent content = (ContextMenuContent) skin.getNode();
+                    Parent nodes = content.getItemsContainer();
+                    
+                    MenuItem desiredMenuItem = MenuItem.this;
+                    List<Node> childrenNodes = nodes.getChildrenUnmodifiable();
+                    for (int i = 0; i < childrenNodes.size(); i++) {
+                        if (! (childrenNodes.get(i) instanceof ContextMenuContent.MenuItemContainer)) continue;
+                        
+                        ContextMenuContent.MenuItemContainer MenuRow = 
+                                (ContextMenuContent.MenuItemContainer) childrenNodes.get(i);
+                        
+                        if (desiredMenuItem.equals(MenuRow.getItem())) {
+                            return MenuRow;
+                        }
+                    }
+                    
                     return null;
                 }
 
--- a/javafx-ui-controls/src/javafx/scene/control/Tab.java	Thu Jun 14 14:06:12 2012 -0700
+++ b/javafx-ui-controls/src/javafx/scene/control/Tab.java	Mon Jun 18 13:12:52 2012 -0700
@@ -681,7 +681,14 @@
 
     private static final String DEFAULT_STYLE_CLASS = "tab";
     
+    /**
+     * RT-19263
+     * @treatAsPrivate implementation detail
+     * @deprecated This is an experimental API that is not intended for general 
+     * use and is subject to change in future versions
+     */
     protected Styleable styleable; 
+    
     /**
      * RT-19263
      * @treatAsPrivate implementation detail
--- a/javafx-ui-controls/src/javafx/scene/control/TabPane.java	Thu Jun 14 14:06:12 2012 -0700
+++ b/javafx-ui-controls/src/javafx/scene/control/TabPane.java	Mon Jun 18 13:12:52 2012 -0700
@@ -636,6 +636,7 @@
                                     tab.setSelected(false);
                                     if (c.getFrom() == 0) {
                                         if (tabPane.getTabs().size() > 1) {
+                                            clearSelection();
                                             selectFirst();
                                         }
                                     } else {
--- a/javafx-ui-controls/src/javafx/scene/control/TableCell.java	Thu Jun 14 14:06:12 2012 -0700
+++ b/javafx-ui-controls/src/javafx/scene/control/TableCell.java	Mon Jun 18 13:12:52 2012 -0700
@@ -97,8 +97,12 @@
     };
     
     @Override void indexChanged() {
-        itemDirty = true;
-        requestLayout();
+        // Ideally we would just use the following two lines of code, rather
+        // than the updateItem() call beneath, but if we do this we end up with
+        // RT-22428 where all the columns are collapsed.
+        // itemDirty = true;
+        // requestLayout();
+        updateItem();
     }
 
     /*
@@ -164,13 +168,11 @@
             updateColumnIndex();
         }
 
-        @Override
-        public Object getBean() {
+        @Override public Object getBean() {
             return TableCell.this;
         }
 
-        @Override
-        public String getName() {
+        @Override public String getName() {
             return "tableColumn";
         }
     };
--- a/javafx-ui-controls/src/javafx/scene/control/TableColumn.java	Thu Jun 14 14:06:12 2012 -0700
+++ b/javafx-ui-controls/src/javafx/scene/control/TableColumn.java	Mon Jun 18 13:12:52 2012 -0700
@@ -24,6 +24,8 @@
  */
 package javafx.scene.control;
 
+import com.sun.javafx.css.Styleable;
+import com.sun.javafx.css.StyleableProperty;
 import java.text.Collator;
 import java.util.Comparator;
 import javafx.beans.Observable;
@@ -52,6 +54,8 @@
 import com.sun.javafx.scene.control.skin.Utils;
 import com.sun.javafx.event.EventHandlerManager;
 import com.sun.javafx.scene.control.WeakListChangeListener;
+import com.sun.javafx.scene.control.skin.*;
+import java.util.Collections;
 import java.util.HashMap;
 
 import java.util.List;
@@ -269,6 +273,8 @@
      * onEditCommit implementation.
      */
     public TableColumn() {
+        getStyleClass().add(DEFAULT_STYLE_CLASS);
+        
         setOnEditCommit(DEFAULT_EDIT_COMMIT_HANDLER);
 
         // we listen to the columns list here to ensure that widths are
@@ -284,10 +290,12 @@
                     tc.setTableView(getTableView());
                 }
                 
-                // set the parent of this column to also have this tableView
-                if (getParentColumn() != null) {
-                    getParentColumn().setTableView(getTableView());
-                }
+                // This code was commented out due to RT-22391, with this enabled
+                // the parent column will be null, which is not desired
+//                // set the parent of this column to also have this tableView
+//                if (getParentColumn() != null) {
+//                    getParentColumn().setTableView(getTableView());
+//                }
             }
         });
     }
@@ -1219,6 +1227,7 @@
     }
 
     
+    
     /***************************************************************************
      *                                                                         *
      * Private Implementation                                                  *
@@ -1235,7 +1244,92 @@
     }
 
 
+    
+    /***************************************************************************
+     *                                                                         *
+     * Stylesheet Handling                                                     *
+     *                                                                         *
+     **************************************************************************/
 
+    private static final String DEFAULT_STYLE_CLASS = "table-column";
+
+    /**
+     * RT-19263
+     * @treatAsPrivate implementation detail
+     * @deprecated This is an experimental API that is not intended for general 
+     * use and is subject to change in future versions
+     */
+    protected Styleable styleable; 
+        
+    @Deprecated // SB-dependency: RT-21094 has been filed to track this
+    public Styleable impl_getStyleable() {
+        
+        if (styleable == null) {
+            styleable = new Styleable() {
+
+                @Override
+                public String getId() {
+                    return TableColumn.this.getId();
+                }
+
+                @Override
+                public List<String> getStyleClass() {
+                    return TableColumn.this.getStyleClass();
+                }
+
+                @Override
+                public String getStyle() {
+                    return TableColumn.this.getStyle();
+                }
+
+                @Override
+                public Styleable getStyleableParent() {
+                    return getTableView() == null ? null : getTableView().impl_getStyleable();
+                }
+
+                
+                @Override
+                public List<StyleableProperty> getStyleableProperties() {
+                    return Collections.EMPTY_LIST;
+                }                
+
+                @Override
+                public Node getNode() {
+                    if (! (getTableView().getSkin() instanceof TableViewSkin)) return null;
+                    TableViewSkin skin = (TableViewSkin) getTableView().getSkin();
+                    
+                    TableHeaderRow tableHeader = skin.getTableHeaderRow();
+                    NestedTableColumnHeader rootHeader = tableHeader.getRootHeader();
+                    
+                    // we now need to do a search for the header. We'll go depth-first.
+                    return scan(rootHeader);
+                }
+                
+                private TableColumnHeader scan(TableColumnHeader header) {
+                    // firstly test that the parent isn't what we are looking for
+                    if (TableColumn.this.equals(header.getTableColumn())) {
+                        return header;
+                    }
+                    
+                    if (header instanceof NestedTableColumnHeader) {
+                        NestedTableColumnHeader parent = (NestedTableColumnHeader) header;
+                        for (int i = 0; i < parent.getColumnHeaders().size(); i++) {
+                            TableColumnHeader result = scan(parent.getColumnHeaders().get(i));
+                            if (result != null) {
+                                return result;
+                            }
+                        }
+                    }
+                    
+                    return null;
+                }
+            };
+        }
+        return styleable;
+    }   
+    
+    
+    
     /***************************************************************************
      *                                                                         *
      * Support Interfaces                                                      *
--- a/javafx-ui-controls/src/javafx/scene/control/TableView.java	Thu Jun 14 14:06:12 2012 -0700
+++ b/javafx-ui-controls/src/javafx/scene/control/TableView.java	Mon Jun 18 13:12:52 2012 -0700
@@ -60,6 +60,7 @@
 import com.sun.javafx.scene.control.WeakListChangeListener;
 import com.sun.javafx.scene.control.skin.TableViewSkin;
 import com.sun.javafx.scene.control.skin.VirtualContainerBase;
+import java.lang.ref.WeakReference;
 import java.util.HashMap;
 import javafx.beans.DefaultProperty;
 import javafx.beans.WeakInvalidationListener;
@@ -821,19 +822,25 @@
     public final ObjectProperty<ObservableList<S>> itemsProperty() { return items; }
     private ObjectProperty<ObservableList<S>> items = 
         new SimpleObjectProperty<ObservableList<S>>(this, "items") {
+            WeakReference<ObservableList<S>> oldItemsRef;
+            
             @Override protected void invalidated() {
+                ObservableList<S> oldItems = oldItemsRef == null ? null : oldItemsRef.get();
+                
                 // FIXME temporary fix for RT-15793. This will need to be
                 // properly fixed when time permits
                 if (getSelectionModel() instanceof TableViewArrayListSelectionModel) {
-                    ((TableViewArrayListSelectionModel)getSelectionModel()).updateItemsObserver(null, getItems());
+                    ((TableViewArrayListSelectionModel)getSelectionModel()).updateItemsObserver(oldItems, getItems());
                 }
                 if (getFocusModel() instanceof TableViewFocusModel) {
-                    ((TableViewFocusModel)getFocusModel()).updateItemsObserver(null, getItems());
+                    ((TableViewFocusModel)getFocusModel()).updateItemsObserver(oldItems, getItems());
                 }
                 if (getSkin() instanceof TableViewSkin) {
                     TableViewSkin skin = (TableViewSkin) getSkin();
-                    skin.updateTableItems(null, getItems());
+                    skin.updateTableItems(oldItems, getItems());
                 }
+                
+                oldItemsRef = new WeakReference<ObservableList<S>>(getItems());
             }
         };
     public final void setItems(ObservableList<S> value) { itemsProperty().set(value); }
@@ -1799,11 +1806,17 @@
         final WeakListChangeListener weakItemsContentListener 
                 = new WeakListChangeListener(itemsContentListener);
         
+        private int newListHash = -1;
         private void updateItemsObserver(ObservableList<S> oldList, ObservableList<S> newList) {
             // the listview items list has changed, we need to observe
             // the new list, and remove any observer we had from the old list
-            if (oldList != null) oldList.removeListener(weakItemsContentListener);
-            if (newList != null) newList.addListener(weakItemsContentListener);
+            if (oldList != null) {
+                oldList.removeListener(weakItemsContentListener);
+            }
+            if (newList != null && newList.hashCode() != newListHash) {
+                newListHash = newList.hashCode();
+                newList.addListener(weakItemsContentListener);
+            }
 
             // when the items list totally changes, we should clear out
             // the selection
@@ -1845,6 +1858,7 @@
          *                                                                     *
          **********************************************************************/
 
+        private int previousModelSize = 0;
         
         // Listen to changes in the tableview items list, such that when it 
         // changes we can update the selected indices list to refer to the 
@@ -1852,12 +1866,26 @@
         private void updateSelection(ListChangeListener.Change<? extends S> c) {
             while (c.next()) {
                 if (c.wasReplaced()) {
-                    // Fix for RT-18969: the items list had setAll called on it
-                    if (getSelectedIndex() < getRowCount()) {
-                        int selectedIndex = getSelectedIndex();
-                        clearSelection(selectedIndex);
-                        select(selectedIndex);
+                    if (c.getList().isEmpty()) {
+                        // the entire items list was emptied - clear selection
+                        clearSelection();
+                    } else {
+                        int index = getSelectedIndex();
+                        
+                        if (previousModelSize == c.getRemovedSize()) {
+                            // all items were removed from the model
+                            clearSelection();
+                        } else if (index < getRowCount() && index >= 0) {
+                            // Fix for RT-18969: the list had setAll called on it
+                            clearSelection(index);
+                            select(index);
+                        } else {
+                            // Fix for RT-22079
+                            clearSelection();
+                        }
                     }
+                    
+                    
                 } else if (c.wasAdded() || c.wasRemoved()) {
                     int position = c.getFrom();
                     int shift = c.wasAdded() ? c.getAddedSize() : -c.getRemovedSize();
@@ -1925,6 +1953,8 @@
                     selectedCellsSeq.callObservers(new NonIterableChange.SimpleAddChange<TablePosition>(0, newIndices.size(), selectedCellsSeq));
                 }
             }
+            
+            previousModelSize = getRowCount();
         }
 
         /***********************************************************************
--- a/javafx-ui-controls/src/javafx/scene/control/Tooltip.java	Thu Jun 14 14:06:12 2012 -0700
+++ b/javafx-ui-controls/src/javafx/scene/control/Tooltip.java	Mon Jun 18 13:12:52 2012 -0700
@@ -186,17 +186,17 @@
     }
     public final String getText() { return text == null ? "" : text.getValue(); }
 
-    /**
-     * Specifies the behavior for lines of text <em>when text is multiline</em>
-     * Unlike {@link #contentDisplay} which affects the graphic and text, this setting
-     * only affects multiple lines of text relative to the text bounds.
-     */
     public final void setTextAlignment(TextAlignment value) { textAlignmentProperty().setValue(value); }
     public final TextAlignment getTextAlignment() { 
         return ((Tooltip.CSSBridge)bridge).textAlignment == null 
                 ? TextAlignment.LEFT 
                 : ((Tooltip.CSSBridge)bridge).textAlignment.getValue(); 
     }
+    /**
+     * Specifies the behavior for lines of text <em>when text is multiline</em>.
+     * Unlike {@link #contentDisplay} which affects the graphic and text, this setting
+     * only affects multiple lines of text relative to the text bounds.
+     */
     public final ObjectProperty<TextAlignment> textAlignmentProperty() {
         return ((Tooltip.CSSBridge)bridge).textAlignmentProperty();
     }
--- a/javafx-ui-controls/test/javafx/scene/control/ComboBoxTest.java	Thu Jun 14 14:06:12 2012 -0700
+++ b/javafx-ui-controls/test/javafx/scene/control/ComboBoxTest.java	Mon Jun 18 13:12:52 2012 -0700
@@ -35,13 +35,35 @@
     private ComboBox<String> comboBox;
     private SingleSelectionModel<String> sm;
     
+    /*********************************************************************
+     *                                                                   *
+     * Utility methods                                                   *
+     *                                                                   *
+     ********************************************************************/    
+    
+    public ListView getListView() {
+        return ((ComboBoxListViewSkin)comboBox.getSkin()).getListView();
+    }
+    
+    
+    
+    /*********************************************************************
+     *                                                                   *
+     * Setup                                                             *
+     *                                                                   *
+     ********************************************************************/      
+    
     @Before public void setup() {
         comboBox = new ComboBox<String>();
         sm = comboBox.getSelectionModel();
     }
     
+    
+    
     /*********************************************************************
+     *                                                                   *
      * Tests for the constructors                                        *
+     *                                                                   *
      ********************************************************************/
     
     @Test public void noArgConstructorSetsTheStyleClass() {
@@ -747,16 +769,16 @@
         comboBox.show();
         
         comboBox.setVisibleRowCount(5);
-        double initialHeight = ((ComboBoxListViewSkin)comboBox.getSkin()).getListView().getHeight();
+        double initialHeight = getListView().getHeight();
         assertFalse("initialHeight: " + initialHeight, Double.compare(0.0, initialHeight) == 0);
         
         comboBox.setVisibleRowCount(0);
-        double smallHeight = ((ComboBoxListViewSkin)comboBox.getSkin()).getListView().getHeight();
+        double smallHeight =    getListView().getHeight();
         assertTrue("smallHeight: " + smallHeight + ", initialHeight: " + initialHeight,
                 smallHeight != initialHeight && smallHeight < initialHeight);
         
         comboBox.setVisibleRowCount(7);
-        double biggerHeight = ((ComboBoxListViewSkin)comboBox.getSkin()).getListView().getHeight();
+        double biggerHeight = getListView().getHeight();
         assertTrue(biggerHeight != smallHeight && smallHeight < biggerHeight);
     } 
     
@@ -812,7 +834,7 @@
         comboBox.getSelectionModel().select(2);
         assertEquals("2", comboBox.getValue());
         
-        ListView listView = ((ComboBoxListViewSkin)comboBox.getSkin()).getListView();
+        ListView listView = getListView();
 //        listView.impl_processCSS(true);
         
         assertEquals("2", listView.getSelectionModel().getSelectedItem());
@@ -837,8 +859,7 @@
         comboBox.impl_processCSS(true);
         comboBox.show();
         
-        ListView listView = ((ComboBoxListViewSkin)comboBox.getSkin()).getListView();
-        SelectionModel sm = listView.getSelectionModel();
+        SelectionModel sm = getListView().getSelectionModel();
         
         comboBox.getSelectionModel().select(2);
         Object item = sm.getSelectedItem();
--- a/javafx-ui-controls/test/javafx/scene/control/ListViewTest.java	Thu Jun 14 14:06:12 2012 -0700
+++ b/javafx-ui-controls/test/javafx/scene/control/ListViewTest.java	Mon Jun 18 13:12:52 2012 -0700
@@ -371,4 +371,15 @@
         // used to be, so the test used to be for three hits)
         assertEquals(2, hitCount);
     }
+    
+    @Test public void test_rt21586() {
+        listView.getItems().setAll("Apple", "Orange", "Banana");
+        listView.getSelectionModel().select(1);
+        assertEquals(1, listView.getSelectionModel().getSelectedIndex());
+        assertEquals("Orange", listView.getSelectionModel().getSelectedItem());
+        
+        listView.getItems().setAll("Kiwifruit", "Pineapple", "Grape");
+        assertEquals(-1, listView.getSelectionModel().getSelectedIndex());
+        assertNull(listView.getSelectionModel().getSelectedItem());
+    }
 }
--- a/javafx-ui-controls/test/javafx/scene/control/TabPaneTest.java	Thu Jun 14 14:06:12 2012 -0700
+++ b/javafx-ui-controls/test/javafx/scene/control/TabPaneTest.java	Mon Jun 18 13:12:52 2012 -0700
@@ -708,4 +708,22 @@
         tk.firePulse();        
         assertEquals(tab2, tabPane.getSelectionModel().getSelectedItem());
     }
+    
+    @Test public void unableToSelectNextTabWhenFirstTabIsClosed_RT22326() {
+        tabPane.getTabs().add(tab1);
+        tabPane.getTabs().add(tab2);
+        tabPane.getTabs().add(tab3);
+
+        assertEquals("one", tabPane.getTabs().get(0).getText());
+        assertEquals("two", tabPane.getTabs().get(1).getText());
+        assertEquals("three", tabPane.getTabs().get(2).getText());
+        
+        tabPane.getTabs().remove(tab1);
+
+        assertEquals(2, tabPane.getTabs().size());
+        assertEquals(0, tabPane.getSelectionModel().getSelectedIndex());
+        assertEquals(tab2, tabPane.getSelectionModel().getSelectedItem());
+        tabPane.getSelectionModel().selectNext();
+        assertEquals(tab3, tabPane.getSelectionModel().getSelectedItem());
+    }
 }
--- a/javafx-ui-controls/test/javafx/scene/control/TableViewTest.java	Thu Jun 14 14:06:12 2012 -0700
+++ b/javafx-ui-controls/test/javafx/scene/control/TableViewTest.java	Mon Jun 18 13:12:52 2012 -0700
@@ -416,4 +416,15 @@
         sm.selectRange(0, 2); // select from 0 (inclusive) to 2 (exclusive)
         assertEquals(2, sm.getSelectedIndices().size());
     }
+    
+    @Test public void test_rt21586() {
+        table.getItems().setAll("Apple", "Orange", "Banana");
+        table.getSelectionModel().select(1);
+        assertEquals(1, table.getSelectionModel().getSelectedIndex());
+        assertEquals("Orange", table.getSelectionModel().getSelectedItem());
+        
+        table.getItems().setAll("Kiwifruit", "Pineapple", "Grape");
+        assertEquals(-1, table.getSelectionModel().getSelectedIndex());
+        assertNull(table.getSelectionModel().getSelectedItem());
+    }
 }
--- a/javafx-ui-controls/test/javafx/scene/control/TreeViewTest.java	Thu Jun 14 14:06:12 2012 -0700
+++ b/javafx-ui-controls/test/javafx/scene/control/TreeViewTest.java	Mon Jun 18 13:12:52 2012 -0700
@@ -408,4 +408,21 @@
         treeView.getSelectionModel().selectRange(0, 2); // select from 0 (inclusive) to 2 (exclusive)
         assertEquals(2, treeView.getSelectionModel().getSelectedIndices().size());
     }
+    
+    @Test public void test_rt21586() {
+        installChildren();
+        treeView.getSelectionModel().select(1);
+        assertEquals(1, treeView.getSelectionModel().getSelectedIndex());
+        assertEquals(child1, treeView.getSelectionModel().getSelectedItem());
+        
+        TreeItem root = new TreeItem<String>("New Root");
+        TreeItem child1 = new TreeItem<String>("New Child 1");
+        TreeItem child2 = new TreeItem<String>("New Child 2");
+        TreeItem child3 = new TreeItem<String>("New Child 3");
+        root.setExpanded(true);
+        root.getChildren().setAll(child1, child2, child3);
+        treeView.setRoot(root);
+        assertEquals(-1, treeView.getSelectionModel().getSelectedIndex());
+        assertNull(treeView.getSelectionModel().getSelectedItem());
+    }
 }