changeset 1070:862bbb9698c8

Automated merge with ssh://jfxsrc.us.oracle.com//javafx/2.2/MASTER/rt
author leifs
date Mon, 21 May 2012 14:09:46 -0700
parents 3c075255b974 2f812ef410af
children 28f01d4898b6 ae1d114a26e3
files
diffstat 32 files changed, 1351 insertions(+), 221 deletions(-) [+]
line wrap: on
line diff
--- a/javafx-ui-common/src/com/sun/javafx/menu/MenuItemBase.java	Thu May 17 15:19:29 2012 -0700
+++ b/javafx-ui-common/src/com/sun/javafx/menu/MenuItemBase.java	Mon May 21 14:09:46 2012 -0700
@@ -116,5 +116,10 @@
      * Fires a new ActionEvent.
      */
     public void fire();
+    
+    /**
+     * Fires when the accelerator for this MenuItem is invoked.
+     */
+    public void fireValidation();
 
 }
--- a/javafx-ui-controls/src/com/sun/javafx/scene/control/GlobalMenuAdapter.java	Thu May 17 15:19:29 2012 -0700
+++ b/javafx-ui-controls/src/com/sun/javafx/scene/control/GlobalMenuAdapter.java	Mon May 21 14:09:46 2012 -0700
@@ -161,6 +161,19 @@
         });
     }
 
+    @Override
+    public void fireValidation() {
+        if (menu.getOnMenuValidation() != null) {
+            Event.fireEvent(menu, new Event(GlobalMenuAdapter.this.MENU_VALIDATION_EVENT));
+        }
+        Menu target = (Menu)menu.getParentMenu();
+        if(target != null && target.getOnMenuValidation() != null) {
+            Event.fireEvent(target, new Event(target.MENU_VALIDATION_EVENT));
+        }
+        if (!menu.isDisable()) menu.fire();
+        
+    }
+
 
     private class MenuItemAdapter extends MenuItem implements MenuItemBase {
         private MenuItem menuItem;
@@ -173,6 +186,18 @@
             bindMenuItemProperties(this, menuItem);
         }
 
+        @Override
+        public void fireValidation() {
+            if (menuItem.getOnMenuValidation() != null) {
+                Event.fireEvent(menuItem, new Event(menuItem.MENU_VALIDATION_EVENT));
+            }
+            Menu target = (Menu)menuItem.getParentMenu();
+            if(target.getOnMenuValidation() != null) {
+                Event.fireEvent(target, new Event(target.MENU_VALIDATION_EVENT));
+            }
+            if (!menuItem.isDisable()) menuItem.fire();
+        }
+
     }
 
     private class CheckMenuItemAdapter extends CheckMenuItem implements CheckMenuItemBase {
@@ -180,7 +205,6 @@
 
         private CheckMenuItemAdapter(final CheckMenuItem menuItem) {
             super(menuItem.getText());
-
             this.menuItem = menuItem;
 
             bindMenuItemProperties(this, menuItem);
@@ -188,6 +212,18 @@
             selectedProperty().bindBidirectional(menuItem.selectedProperty());
         }
 
+        @Override
+        public void fireValidation() {
+            if (getOnMenuValidation() != null) {
+                Event.fireEvent(menuItem, new Event(CheckMenuItemAdapter.this.MENU_VALIDATION_EVENT));
+            }
+            Menu target = (Menu)menuItem.getParentMenu();
+            if(target.getOnMenuValidation() != null) {
+                Event.fireEvent(target, new Event(target.MENU_VALIDATION_EVENT));
+            }
+            if (!menuItem.isDisable()) menuItem.fire();
+        }
+
     }
 
     private class RadioMenuItemAdapter extends RadioMenuItem implements RadioMenuItemBase {
@@ -203,6 +239,18 @@
             selectedProperty().bindBidirectional(menuItem.selectedProperty());
         }
 
+        @Override
+        public void fireValidation() {
+            if (getOnMenuValidation() != null) {
+                Event.fireEvent(menuItem, new Event(RadioMenuItemAdapter.this.MENU_VALIDATION_EVENT));
+            }
+            Menu target = (Menu)menuItem.getParentMenu();
+            if(target.getOnMenuValidation() != null) {
+                Event.fireEvent(target, new Event(target.MENU_VALIDATION_EVENT));
+            }
+            if (!menuItem.isDisable()) menuItem.fire();
+        }
+
     }
 
     private class SeparatorMenuItemAdapter extends SeparatorMenuItem implements SeparatorMenuItemBase {
@@ -214,6 +262,18 @@
             bindMenuItemProperties(this, menuItem);
         }
 
+        @Override
+        public void fireValidation() {
+            if (getOnMenuValidation() != null) {
+                Event.fireEvent(menuItem, new Event(SeparatorMenuItemAdapter.this.MENU_VALIDATION_EVENT));
+            }
+            Menu target = (Menu)menuItem.getParentMenu();
+            if(target.getOnMenuValidation() != null) {
+                Event.fireEvent(target, new Event(target.MENU_VALIDATION_EVENT));
+            }
+            if (!menuItem.isDisable()) menuItem.fire();
+        }
+
     }
 
     private class CustomMenuItemAdapter extends CustomMenuItem implements CustomMenuItemBase {
@@ -225,5 +285,17 @@
             bindMenuItemProperties(this, menuItem);
         }
 
+        @Override
+        public void fireValidation() {
+            if (getOnMenuValidation() != null) {
+                Event.fireEvent(menuItem, new Event(CustomMenuItemAdapter.this.MENU_VALIDATION_EVENT));
+            }
+            Menu target = (Menu)menuItem.getParentMenu();
+            if(target.getOnMenuValidation() != null) {
+                Event.fireEvent(target, new Event(target.MENU_VALIDATION_EVENT));
+            }
+            if (!menuItem.isDisable()) menuItem.fire();
+        }
+
     }
 }
--- a/javafx-ui-controls/src/com/sun/javafx/scene/control/behavior/ComboBoxBaseBehavior.java	Thu May 17 15:19:29 2012 -0700
+++ b/javafx-ui-controls/src/com/sun/javafx/scene/control/behavior/ComboBoxBaseBehavior.java	Mon May 21 14:09:46 2012 -0700
@@ -182,9 +182,8 @@
 
     @Override public void mouseEntered(MouseEvent e) {
         if (getControl().isEditable()) {
-            // Fix for RT-19274
             Node arrowButton = getControl().lookup("#arrow-button");
-            mouseInsideButton = arrowButton != null && arrowButton.contains(e.getX(), e.getY());
+            mouseInsideButton = arrowButton != null && arrowButton.localToScene(arrowButton.getBoundsInLocal()).contains(e.getSceneX(), e.getSceneY());
         } else {
             mouseInsideButton = true;
         }
--- a/javafx-ui-controls/src/com/sun/javafx/scene/control/behavior/ListCellBehavior.java	Thu May 17 15:19:29 2012 -0700
+++ b/javafx-ui-controls/src/com/sun/javafx/scene/control/behavior/ListCellBehavior.java	Mon May 21 14:09:46 2012 -0700
@@ -25,6 +25,7 @@
 
 package com.sun.javafx.scene.control.behavior;
 
+import com.sun.javafx.PlatformUtil;
 import com.sun.javafx.logging.PlatformLogger;
 import com.sun.javafx.scene.control.Logging;
 import java.util.WeakHashMap;
@@ -69,20 +70,31 @@
     // the best feel:
     //  - when you click on a not-selected item, you can select immediately on press
     //  - when you click on a selected item, you need to wait whether DragDetected or Release comes first 
-    private boolean selected = false;
+    //
+    // To support touch devices, we have to slightly modify this behavior, such
+    // that selection only happens on mouse release, if only minimal dragging
+    // has occurred.
     private boolean latePress = false;
+    private final boolean isEmbedded = PlatformUtil.isEmbedded();
+    private boolean wasSelected = false;
 
     public ListCellBehavior(ListCell control) {
         super(control);
     }
     
     @Override public void mousePressed(MouseEvent event) {
-        if (selected) {
+        boolean selectedBefore = getControl().isSelected();
+        
+        if (getControl().isSelected()) {
             latePress = true;
             return;
         }
+
+        doSelect(event);
         
-        doSelect(event);
+        if (isEmbedded && selectedBefore) {
+            wasSelected = getControl().isSelected();
+        }
     }
     
     @Override public void mouseReleased(MouseEvent event) {
@@ -90,10 +102,19 @@
             latePress = false;
             doSelect(event);
         }
+        
+        wasSelected = false;
     }
     
     @Override public void mouseDragged(MouseEvent event) {
         latePress = false;
+
+        // the mouse has now been dragged on a touch device, we should
+        // remove the selection if we just added it in the last mouse press
+        // event
+        if (isEmbedded && ! wasSelected && getControl().isSelected()) {
+            getControl().getListView().getSelectionModel().clearSelection(getControl().getIndex());
+        }
     }
     
     private void doSelect(MouseEvent e) {
--- a/javafx-ui-controls/src/com/sun/javafx/scene/control/behavior/PasswordFieldBehavior.java	Thu May 17 15:19:29 2012 -0700
+++ b/javafx-ui-controls/src/com/sun/javafx/scene/control/behavior/PasswordFieldBehavior.java	Mon May 21 14:09:46 2012 -0700
@@ -47,6 +47,9 @@
     protected void selectNextWord() { }
     protected void previousWord() { }
     protected void nextWord() { }
+    protected void selectWord() {
+        getControl().selectAll();
+    }
     protected void mouseDoubleClick(HitInfo hit) {
         getControl().selectAll();
     }
--- a/javafx-ui-controls/src/com/sun/javafx/scene/control/behavior/ScrollBarBehavior.java	Thu May 17 15:19:29 2012 -0700
+++ b/javafx-ui-controls/src/com/sun/javafx/scene/control/behavior/ScrollBarBehavior.java	Mon May 21 14:09:46 2012 -0700
@@ -186,8 +186,9 @@
         timeline = new Timeline();
         timeline.setCycleCount(Timeline.INDEFINITE);
 
-        final EventHandler<ActionEvent> step =
-                new EventHandler<ActionEvent>() {
+        final KeyFrame kf1 = new KeyFrame(
+            Duration.millis(0),
+            new EventHandler<ActionEvent>() {
                 @Override
                 public void handle(ActionEvent event) {
                     boolean i = (pos > ((bar.getValue() - bar.getMin())/(bar.getMax() - bar.getMin())));
@@ -202,12 +203,10 @@
                         timeline = null;
                     }
                 }
-            };
-
-        final KeyFrame kf = new KeyFrame(Duration.millis(200), step);
-        timeline.getKeyFrames().add(kf);
-        // do the first step immediately
-        step.handle(null);
+            }
+        );
+        final KeyFrame kf2 = new KeyFrame(Duration.millis(200));
+        timeline.getKeyFrames().addAll(kf1, kf2);
         timeline.play();
 
     }
@@ -236,7 +235,8 @@
         timeline = new Timeline();
         timeline.setCycleCount(Timeline.INDEFINITE);
 
-        final EventHandler<ActionEvent> dec =
+        final KeyFrame kf1 = new KeyFrame(
+            Duration.millis(0),
             new EventHandler<ActionEvent>() {
                 @Override
                 public void handle(ActionEvent event) {
@@ -248,12 +248,10 @@
                         timeline = null;
                     }
                 }
-            };
-
-        final KeyFrame kf = new KeyFrame(Duration.millis(200), dec);
-        timeline.getKeyFrames().add(kf);
-        // do the first step immediately
-        dec.handle(null);
+            }
+        );
+        final KeyFrame kf2 = new KeyFrame(Duration.millis(200));
+        timeline.getKeyFrames().addAll(kf1, kf2);
         timeline.play();
     }
 
@@ -280,7 +278,8 @@
         timeline = new Timeline();
         timeline.setCycleCount(Timeline.INDEFINITE);
 
-        final EventHandler<ActionEvent> inc =
+        final KeyFrame kf1 = new KeyFrame(
+            Duration.millis(0),
             new EventHandler<ActionEvent>() {
                 @Override
                 public void handle(ActionEvent event) {
@@ -292,12 +291,10 @@
                         timeline = null;
                     }
                 }
-            };
-
-        final KeyFrame kf = new KeyFrame(Duration.millis(200), inc);
-        timeline.getKeyFrames().add(kf);
-        // do the first step immediately
-        inc.handle(null);
+            }
+        );
+        final KeyFrame kf2 = new KeyFrame(Duration.millis(200));
+        timeline.getKeyFrames().addAll(kf1, kf2);
         timeline.play();
     }
 
--- a/javafx-ui-controls/src/com/sun/javafx/scene/control/behavior/TextAreaBehavior.java	Thu May 17 15:19:29 2012 -0700
+++ b/javafx-ui-controls/src/com/sun/javafx/scene/control/behavior/TextAreaBehavior.java	Mon May 21 14:09:46 2012 -0700
@@ -27,9 +27,16 @@
 
 import javafx.beans.value.ChangeListener;
 import javafx.beans.value.ObservableValue;
+import javafx.event.EventHandler;
+import javafx.geometry.Point2D;
+import javafx.scene.Scene;
+import javafx.scene.control.ContextMenu;
 import javafx.scene.control.TextArea;
 import javafx.scene.input.MouseButton;
 import javafx.scene.input.MouseEvent;
+import javafx.scene.input.TouchEvent;
+import javafx.stage.Screen;
+import javafx.stage.Window;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -119,14 +126,20 @@
     }
 
     private TextAreaSkin skin;
+    private ContextMenu contextMenu;
 
     /**************************************************************************
      * Constructors                                                           *
      *************************************************************************/
 
-    public TextAreaBehavior(TextArea textArea) {
+    public TextAreaBehavior(final TextArea textArea) {
         super(textArea);
 
+        contextMenu = new ContextMenu();
+        if (PlatformUtil.isEmbedded()) {
+            contextMenu.getStyleClass().add("text-input-context-menu");
+        }
+        
         // Register for change events
         textArea.focusedProperty().addListener(new ChangeListener<Boolean>() {
             @Override
@@ -142,8 +155,7 @@
                     setCaretAnimating(false);
                 }
             }
-        });
-
+        });        
     }
 
     // An unholy back-reference!
@@ -258,8 +270,9 @@
                 final int anchor = textArea.getAnchor();
                 final int caretPosition = textArea.getCaretPosition();
                 if (e.getClickCount() < 2 &&
-                        anchor != caretPosition &&
-                        ((i > anchor && i < caretPosition) || (i < anchor && i > caretPosition))) {
+                    (PlatformUtil.isEmbedded() ||
+                     (anchor != caretPosition &&
+                      ((i > anchor && i < caretPosition) || (i < anchor && i > caretPosition))))) {
                     // if there is a selection, then we will NOT handle the
                     // press now, but will defer until the release. If you
                     // select some text and then press down, we change the
@@ -295,6 +308,9 @@
 //                if (textInputControl.editable)
 //                    displaySoftwareKeyboard(true);
             }
+            if (contextMenu.isShowing()) {
+                contextMenu.hide();                
+            }            
         }
     }
 
@@ -311,7 +327,7 @@
         }
     }
 
-    @Override public void mouseReleased(MouseEvent e) {
+    @Override public void mouseReleased(final MouseEvent e) {
         final TextArea textArea = getControl();
         super.mouseReleased(e);
         // we never respond to events if disabled, but we do notify any onXXX
@@ -325,6 +341,61 @@
             }
             setCaretAnimating(true);
         }
+        if (e.getButton() == MouseButton.SECONDARY) {
+            if (contextMenu.isShowing()) {
+                contextMenu.hide();
+            } else {
+                double screenX = e.getScreenX();
+                double screenY = e.getScreenY();
+                double sceneX = e.getSceneX();
+
+                if (PlatformUtil.isEmbedded()) {
+                    Point2D menuPos;
+                    if (textArea.getSelection().getLength() == 0) {
+                        skin.positionCaret(skin.getIndex(e), false, false);
+                        menuPos = skin.getMenuPosition();
+                    } else {
+                        menuPos = skin.getMenuPosition();
+                        if (menuPos != null && (menuPos.getX() <= 0 || menuPos.getY() <= 0)) {
+                            skin.positionCaret(skin.getIndex(e), false, false);
+                            menuPos = skin.getMenuPosition();
+                        }
+                    }
+
+                    if (menuPos != null) {
+                        Point2D p = skin.localToScene(menuPos);
+                        Scene scene = skin.getScene();
+                        Window window = scene.getWindow();
+                        Point2D location = new Point2D(window.getX() + scene.getX() + p.getX(),
+                                                       window.getY() + scene.getY() + p.getY());
+                        screenX = location.getX();
+                        sceneX = p.getX();
+                        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();
+
+                if (menuX < 0) {
+                    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);
+                    skin.getProperties().put("CONTEXT_MENU_SCREEN_X", screenX);
+                    skin.getProperties().put("CONTEXT_MENU_SCENE_X", sceneX);
+                    contextMenu.show(getControl(), screenX - leftOver, screenY);
+                } else {
+                    skin.getProperties().put("CONTEXT_MENU_SCREEN_X", 0);
+                    skin.getProperties().put("CONTEXT_MENU_SCENE_X", 0);
+                    contextMenu.show(getControl(), menuX, screenY);
+                }
+            }
+        }
     }
 
     @Override protected void setCaretAnimating(boolean play) {
--- a/javafx-ui-controls/src/com/sun/javafx/scene/control/behavior/TextFieldBehavior.java	Thu May 17 15:19:29 2012 -0700
+++ b/javafx-ui-controls/src/com/sun/javafx/scene/control/behavior/TextFieldBehavior.java	Mon May 21 14:09:46 2012 -0700
@@ -32,13 +32,21 @@
 import javafx.event.ActionEvent;
 import javafx.event.EventHandler;
 import javafx.geometry.HorizontalDirection;
+import javafx.geometry.Point2D;
+import javafx.scene.Scene;
+import javafx.scene.control.ContextMenu;
 import javafx.scene.control.IndexRange;
 import javafx.scene.control.TextField;
 import javafx.scene.input.KeyEvent;
+import javafx.scene.input.MouseButton;
 import javafx.scene.input.MouseEvent;
+import javafx.scene.input.TouchEvent;
+import javafx.stage.Screen;
+import javafx.stage.Window;
 import javafx.util.Duration;
 import java.util.List;
 
+import com.sun.javafx.PlatformUtil;
 import com.sun.javafx.scene.control.skin.TextFieldSkin;
 import com.sun.javafx.scene.text.HitInfo;
 
@@ -86,9 +94,17 @@
             }
         }
     };
+    
+    private ContextMenu contextMenu;
 
-    public TextFieldBehavior(TextField textField) {
+    public TextFieldBehavior(final TextField textField) {
         super(textField);
+        
+        contextMenu = new ContextMenu();
+        if (PlatformUtil.isEmbedded()) {
+            contextMenu.getStyleClass().add("text-input-context-menu");
+        }
+        
         // Initialize scroll timeline
         scrollSelectionTimeline.setCycleCount(Timeline.INDEFINITE);
         List<KeyFrame> scrollTimelineKeyFrames = scrollSelectionTimeline.getKeyFrames();
@@ -191,8 +207,9 @@
                 final int anchor = textField.getAnchor();
                 final int caretPosition = textField.getCaretPosition();
                 if (e.getClickCount() < 2 &&
-                        anchor != caretPosition &&
-                        ((i > anchor && i < caretPosition) || (i < anchor && i > caretPosition))) {
+                    (PlatformUtil.isEmbedded() ||
+                     (anchor != caretPosition &&
+                      ((i > anchor && i < caretPosition) || (i < anchor && i > caretPosition))))) {
                     // if there is a selection, then we will NOT handle the
                     // press now, but will defer until the release. If you
                     // select some text and then press down, we change the
@@ -229,6 +246,9 @@
 //                    displaySoftwareKeyboard(true);
             }
         }
+        if (contextMenu.isShowing()) {
+            contextMenu.hide();                
+        }         
     }
 
     @Override public void mouseDragged(MouseEvent e) {
@@ -258,6 +278,61 @@
             }
             setCaretAnimating(true);
         }
+        if (e.getButton() == MouseButton.SECONDARY) {
+            if (contextMenu.isShowing()) {
+                contextMenu.hide();
+            } else {
+                double screenX = e.getScreenX();
+                double screenY = e.getScreenY();
+                double sceneX = e.getSceneX();
+
+                if (PlatformUtil.isEmbedded()) {
+                    Point2D menuPos;
+                    if (textField.getSelection().getLength() == 0) {
+                        skin.positionCaret(skin.getIndex(e), false);
+                        menuPos = skin.getMenuPosition();
+                    } else {
+                        menuPos = skin.getMenuPosition();
+                        if (menuPos != null && (menuPos.getX() <= 0 || menuPos.getY() <= 0)) {
+                            skin.positionCaret(skin.getIndex(e), false);
+                            menuPos = skin.getMenuPosition();
+                        }
+                    }
+
+                    if (menuPos != null) {
+                        Point2D p = skin.localToScene(menuPos);
+                        Scene scene = skin.getScene();
+                        Window window = scene.getWindow();
+                        Point2D location = new Point2D(window.getX() + scene.getX() + p.getX(),
+                                                       window.getY() + scene.getY() + p.getY());
+                        screenX = location.getX();
+                        sceneX = p.getX();
+                        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();
+
+                if (menuX < 0) {
+                    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);
+                    skin.getProperties().put("CONTEXT_MENU_SCREEN_X", screenX);
+                    skin.getProperties().put("CONTEXT_MENU_SCENE_X", sceneX);
+                    contextMenu.show(getControl(), screenX - leftOver, screenY);
+                } else {
+                    skin.getProperties().put("CONTEXT_MENU_SCREEN_X", 0);
+                    skin.getProperties().put("CONTEXT_MENU_SCENE_X", 0);
+                    contextMenu.show(getControl(), menuX, screenY);
+                }
+            }
+        }
     }
 
 //    var hadFocus = false;
--- a/javafx-ui-controls/src/com/sun/javafx/scene/control/behavior/TextInputControlBehavior.java	Thu May 17 15:19:29 2012 -0700
+++ b/javafx-ui-controls/src/com/sun/javafx/scene/control/behavior/TextInputControlBehavior.java	Mon May 21 14:09:46 2012 -0700
@@ -136,6 +136,7 @@
             else if ("NextWord".equals(name)) nextWord();
             else if ("SelectPreviousWord".equals(name)) selectPreviousWord();
             else if ("SelectNextWord".equals(name)) selectNextWord();
+            else if ("SelectWord".equals(name)) selectWord();
             else if ("SelectAll".equals(name)) textInputControl.selectAll();
             else if ("Home".equals(name)) textInputControl.home();
             else if ("End".equals(name)) textInputControl.end();
@@ -323,6 +324,16 @@
         }
     }
 
+    protected void selectWord() {
+        final TextInputControl textInputControl = getControl();
+        textInputControl.previousWord();
+        if (isWindows()) {
+            textInputControl.selectNextWord();
+        } else {
+            textInputControl.selectEndOfNextWord();
+        }
+    }
+
     protected void previousWord() {
         getControl().previousWord();
     }
--- a/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/ComboBoxListViewSkin.java	Thu May 17 15:19:29 2012 -0700
+++ b/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/ComboBoxListViewSkin.java	Mon May 21 14:09:46 2012 -0700
@@ -72,6 +72,11 @@
         this.comboBox = comboBox;
         this.listView = createListView();
         
+        // Fix for RT-21207. Additional code related to this bug is further below.
+        this.listView.setManaged(false);
+        getChildren().add(listView);
+        // -- end of fix
+                
         updateListViewItems();
         updateCellFactory();
         
@@ -174,6 +179,17 @@
             new WeakListChangeListener(listViewItemsListener);
     
     @Override protected void handleControlPropertyChanged(String p) {
+        // Fix for RT-21207
+        if (p == "SHOWING") {
+            if (getSkinnable().isShowing()) {
+                this.listView.setManaged(true);
+                this.listView.impl_processCSS(true);
+            } else {
+                this.listView.setManaged(false);
+            }
+        }
+        // -- end of fix
+        
         super.handleControlPropertyChanged(p);
         
         if (p == "ITEMS") {
@@ -221,9 +237,10 @@
         // to the TextField. This ensures that the ComboBox appears focused
         // externally for people listening to the focus property.
         textField.focusedProperty().addListener(new ChangeListener<Boolean>() {
-            @Override public void changed(ObservableValue<? extends Boolean> ov, Boolean t, Boolean t1) {
-	        // RT-20657 focus ring gets stuck in a editable combobox
-                // comboBox.requestFocus();
+            @Override public void changed(ObservableValue<? extends Boolean> ov, Boolean t, Boolean hasFocus) {
+                if (hasFocus) {
+                    comboBox.requestFocus();
+                }
             }
         });
 
--- a/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/ContextMenuSkin.java	Thu May 17 15:19:29 2012 -0700
+++ b/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/ContextMenuSkin.java	Mon May 21 14:09:46 2012 -0700
@@ -33,6 +33,8 @@
 import javafx.scene.control.Skin;
 import javafx.scene.layout.StackPane;
 
+import com.sun.javafx.PlatformUtil;
+
 /**
  * Default Skin implementation for PopupMenu. Several controls use PopupMenu in
  * order to display items in a drop down. It deals mostly with show hide logic for
@@ -57,11 +59,18 @@
         // keyboard navigation.
         popupMenu.addEventHandler(Menu.ON_SHOWN, new EventHandler() {
             @Override public void handle(Event event) {
-                 ContextMenuContent cmContent = (ContextMenuContent)popupMenu.getSkin().getNode();
+                Node cmContent = popupMenu.getSkin().getNode();
                 if (cmContent != null) cmContent.requestFocus();
             }
         });
-        root = new ContextMenuContent(popupMenu);
+
+        if (PlatformUtil.isEmbedded() &&
+            popupMenu.getStyleClass().contains("text-input-context-menu")) {
+
+            root = new EmbeddedTextContextMenuContent(popupMenu);
+        } else {
+            root = new ContextMenuContent(popupMenu);
+        }
         root.idProperty().bind(popupMenu.idProperty());
         root.styleProperty().bind(popupMenu.styleProperty());
         root.getStyleClass().addAll(popupMenu.getStyleClass()); // TODO needs to handle updates
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/EmbeddedTextContextMenuContent.java	Mon May 21 14:09:46 2012 -0700
@@ -0,0 +1,186 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.javafx.scene.control.skin;
+
+import javafx.beans.InvalidationListener;
+import javafx.beans.Observable;
+import javafx.collections.ListChangeListener;
+import javafx.event.ActionEvent;
+import javafx.event.Event;
+import javafx.geometry.HPos;
+import javafx.geometry.VPos;
+import javafx.scene.control.*;
+import javafx.scene.layout.HBox;
+import javafx.scene.layout.StackPane;
+
+public class EmbeddedTextContextMenuContent extends StackPane {
+
+    private ContextMenu contextMenu;
+    private StackPane pointer;
+    private HBox menuBox;
+
+    public EmbeddedTextContextMenuContent(final ContextMenu popupMenu) {
+        this.contextMenu = popupMenu;
+        this.menuBox = new HBox();
+        this.pointer = new StackPane();
+        pointer.getStyleClass().add("pointer");
+
+        updateMenuItemContainer();
+        getChildren().addAll(pointer, menuBox);
+
+        contextMenu.ownerNodeProperty().addListener(new InvalidationListener() {
+            @Override public void invalidated(Observable arg0) {
+                if (contextMenu.getOwnerNode() instanceof TextArea) {
+                    TextAreaSkin tas = (TextAreaSkin)((TextArea)contextMenu.getOwnerNode()).getSkin();
+                    tas.getProperties().addListener(new InvalidationListener() {
+                        @Override public void invalidated(Observable arg0) {
+                            requestLayout();
+                        }
+                    });
+                } else if (contextMenu.getOwnerNode() instanceof TextField) {
+                    TextFieldSkin tfs = (TextFieldSkin)((TextField)contextMenu.getOwnerNode()).getSkin();
+                    tfs.getProperties().addListener(new InvalidationListener() {
+                        @Override public void invalidated(Observable arg0) {
+                            requestLayout();
+                        }
+                    });
+                }
+            }
+        });
+
+        contextMenu.getItems().addListener(new ListChangeListener<MenuItem>() {
+            @Override public void onChanged(Change<? extends MenuItem> c) {
+                // Listener to items in PopupMenu to update items in PopupMenuContent
+                updateMenuItemContainer();
+            }
+        });
+    }
+
+    private void updateMenuItemContainer() {
+        menuBox.getChildren().clear();
+        for (MenuItem item: contextMenu.getItems()) {
+            MenuItemContainer menuItemContainer = new MenuItemContainer(item);
+            menuItemContainer.visibleProperty().bind(item.visibleProperty());
+            menuBox.getChildren().add(menuItemContainer);
+        }
+    }
+
+    private void hideAllMenus(MenuItem item) {
+        contextMenu.hide();
+
+        Menu parentMenu;
+        while ((parentMenu = item.getParentMenu()) != null) {
+            parentMenu.hide();
+            item = parentMenu;
+        }
+        if (parentMenu == null && item.getParentPopup() != null) {
+            item.getParentPopup().hide();
+        }
+    }
+
+    @Override protected double computePrefHeight(double width) {
+        double top = snapSpace(getInsets().getTop());
+        double bottom = snapSpace(getInsets().getBottom());
+        double pointerHeight = snapSize(pointer.prefHeight(width));
+        double menuBoxHeight = snapSize(menuBox.prefHeight(width));
+
+        return top + pointerHeight + menuBoxHeight + bottom;
+    }
+
+    @Override protected double computePrefWidth(double height) {
+        double left = snapSpace(getInsets().getLeft());
+        double right = snapSpace(getInsets().getRight());
+        double menuBoxWidth = snapSize(menuBox.prefWidth(height));
+
+        return left + menuBoxWidth + right;
+    }
+    
+    @Override protected void layoutChildren() {
+        double left = snapSpace(getInsets().getLeft());
+        double right = snapSpace(getInsets().getRight());
+        double top = snapSpace(getInsets().getTop());
+        double width = snapSize(getWidth() - (left + right));
+        double pointerWidth = snapSize(Utils.boundedSize(pointer.prefWidth(-1), pointer.minWidth(-1), pointer.maxWidth(-1)));
+        double pointerHeight = snapSize(Utils.boundedSize(pointer.prefWidth(-1), pointer.minWidth(-1), pointer.maxWidth(-1)));
+        double menuBoxWidth = snapSize(Utils.boundedSize(menuBox.prefWidth(-1), menuBox.minWidth(-1), menuBox.maxWidth(-1)));
+        double menuBoxHeight = snapSize(Utils.boundedSize(menuBox.prefWidth(-1), menuBox.minWidth(-1), menuBox.maxWidth(-1)));
+        double sceneX = 0;
+        double screenX = 0;
+        double pointerX = 0;
+
+        if (contextMenu.getOwnerNode() instanceof TextArea) {
+            TextArea ta = (TextArea)contextMenu.getOwnerNode();
+            TextAreaSkin tas = (TextAreaSkin)ta.getSkin();
+            sceneX = Double.valueOf(tas.getProperties().get("CONTEXT_MENU_SCENE_X").toString());
+            screenX = Double.valueOf(tas.getProperties().get("CONTEXT_MENU_SCREEN_X").toString());
+            tas.getProperties().clear();
+        } else if (contextMenu.getOwnerNode() instanceof TextField) {
+            TextField tf = (TextField)contextMenu.getOwnerNode();
+            TextFieldSkin tfs = (TextFieldSkin)tf.getSkin();
+            sceneX = Double.valueOf(tfs.getProperties().get("CONTEXT_MENU_SCENE_X").toString());
+            screenX = Double.valueOf(tfs.getProperties().get("CONTEXT_MENU_SCREEN_X").toString());
+            tfs.getProperties().clear();
+        }
+        if (sceneX == 0) {
+            pointerX = width/2;
+        } else {
+            pointerX = (screenX - sceneX - contextMenu.getX()) + sceneX;
+        }
+
+        pointer.resize(pointerWidth, pointerHeight);
+        positionInArea(pointer, pointerX, top, pointerWidth, pointerHeight, 0, HPos.CENTER, VPos.CENTER);
+        menuBox.resize(menuBoxWidth, menuBoxHeight);
+        positionInArea(menuBox, left, top + pointerHeight, menuBoxWidth, menuBoxHeight, 0, HPos.CENTER, VPos.CENTER);
+    }
+
+    class MenuItemContainer extends Button {
+        private MenuItem item;
+
+        public MenuItemContainer(MenuItem item){
+            getStyleClass().addAll(item.getStyleClass());
+            setId(item.getId());
+            this.item = item;
+            setText(item.getText());
+            setStyle(item.getStyle());
+
+            // bind to text property in menu item
+            textProperty().bind(item.textProperty());
+        }
+
+        public MenuItem getItem() {
+            return item;
+        }
+
+        @Override public void fire() {
+            Event.fireEvent(item, new ActionEvent());
+            if (Boolean.TRUE.equals((Boolean)item.getProperties().get("refreshMenu"))) {
+                //refreshMenu();
+            } else {
+                hideAllMenus(item);
+            }
+        }
+    }
+}
--- a/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/FXVKSkin.java	Thu May 17 15:19:29 2012 -0700
+++ b/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/FXVKSkin.java	Mon May 21 14:09:46 2012 -0700
@@ -92,8 +92,10 @@
 
     private State state = State.NORMAL;
 
-    static final double VK_WIDTH = 640 /*800*/;
+    static final double VK_WIDTH = 640;
     static final double VK_HEIGHT = 243;
+//     static final double VK_WIDTH = 480;
+//     static final double VK_HEIGHT = 326;
     static final double VK_PORTRAIT_HEIGHT = 326;
     static final double VK_SLIDE_MILLIS = 250;
     static final double PREF_KEY_WIDTH = 56;
@@ -171,11 +173,12 @@
                                 com.sun.javafx.Utils.getScreen(attachedNode).getBounds().getHeight();
                             double screenVisualHeight =
                                 com.sun.javafx.Utils.getScreen(attachedNode).getVisualBounds().getHeight();
+                            screenVisualHeight = Math.min(screenHeight, screenVisualHeight + 4 /*??*/);
 
                             slideInTimeline = new Timeline();
                             slideInTimeline.getKeyFrames().setAll(
                                 new KeyFrame(Duration.millis(VK_SLIDE_MILLIS),
-                                             new KeyValue(winY, screenVisualHeight - fxvk.prefHeight(-1) + 4 /*????*/,
+                                             new KeyValue(winY, screenVisualHeight - fxvk.prefHeight(-1),
                                                           Interpolator.EASE_BOTH)));
 
                             slideOutTimeline = new Timeline();
@@ -549,7 +552,7 @@
             }
 
             graphic = new Label((chars.length > 1) ? chars[1] : " ");
-            graphic.setPrefWidth(keyWidth - 12);
+            graphic.setPrefWidth(keyWidth - 6);
             graphic.setMinWidth(USE_PREF_SIZE);
             graphic.setPrefHeight(keyHeight / 2 - 8);
             setGraphic(graphic);
@@ -590,7 +593,7 @@
             @Override public void handle(ActionEvent e) {
                 showSecondaryVK(null);
                 long time = System.currentTimeMillis();
-                if (state == State.SHIFTED && lastTime > 0L && time - lastTime < 600L) {
+                if (lastTime > 0L && time - lastTime < 600L) {
                     setState(State.SHIFT_LOCK);
                 } else if (state == State.SHIFTED || state == State.SHIFT_LOCK) {
                     setState(State.NORMAL);
@@ -724,6 +727,7 @@
                 secondaryPopup = new Popup();
                 secondaryPopup.setAutoHide(true);
                 secondaryPopup.getContent().add(secondaryVK);
+                secondaryVK.impl_processCSS(false);
             }
 
             if (state == State.NUMERIC) {
@@ -734,14 +738,24 @@
                     }
                 }
                 secondaryVK.chars = symbols.toArray(new String[symbols.size()]);
-            } else if (state == State.SHIFTED || state == State.SHIFT_LOCK) {
-                secondaryVK.chars = new String[key.chars.length];
-                System.arraycopy(key.chars, 0, secondaryVK.chars, 0, secondaryVK.chars.length);
-                for (int i = 0; i < secondaryVK.chars.length; i++) {
-                    secondaryVK.chars[i] = key.chars[i].toUpperCase();
+            } else {
+                ArrayList<String> secondaryChars = new ArrayList<String>();
+                // Add all letters
+                for (String ch : key.chars) {
+                    if (Character.isLetter(ch.charAt(0))) {
+                        if (state == State.SHIFTED || state == State.SHIFT_LOCK) {
+                            secondaryChars.add(ch.toUpperCase());
+                        } else {
+                            secondaryChars.add(ch);
+                        }
+                    }
                 }
-            } else {
-                secondaryVK.chars = key.chars;
+                // Add secondary character if not a letter
+                if (key.chars.length > 1 &&
+                    !Character.isLetter(key.chars[1].charAt(0))) {
+                    secondaryChars.add(key.chars[1]);
+                }
+                secondaryVK.chars = secondaryChars.toArray(new String[secondaryChars.size()]);
             }
 
             if (secondaryVK.chars.length > 1) {
--- a/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/LabeledImpl.java	Thu May 17 15:19:29 2012 -0700
+++ b/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/LabeledImpl.java	Mon May 21 14:09:46 2012 -0700
@@ -50,6 +50,9 @@
         labeledImpl.setText(labeled.getText());
         labeled.textProperty().addListener(shuttler);
         
+        labeledImpl.setGraphic(labeled.getGraphic());
+        labeled.graphicProperty().addListener(shuttler);
+        
         final List<StyleableProperty> styleables = Labeled.impl_CSS_STYLEABLES();
         
         for(int n=0, nMax=styleables.size(); n<nMax; n++) {
@@ -87,8 +90,16 @@
           
             if (valueModel == labeled.textProperty()) {
                 labeledImpl.setText(labeled.getText());
-            } else 
-            if (valueModel instanceof WritableValue) { 
+            } else if (valueModel == labeled.graphicProperty()) {
+                // If the user set the graphic, then mirror that.
+                // Otherwise, the graphic was set via the imageUrlProperty which
+                // will be mirrored onto the labeledImpl by the next block.
+                Stylesheet.Origin origin = StyleableProperty.getOrigin(labeled.graphicProperty());
+                if (origin == null || origin == Stylesheet.Origin.USER) {
+                    labeledImpl.setGraphic(labeled.getGraphic());
+                }
+                
+            } else if (valueModel instanceof WritableValue) { 
                 WritableValue writable = (WritableValue)valueModel;
                 StyleableProperty styleable = 
                         StyleableProperty.getStyleableProperty(writable);
--- a/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/MenuBarSkin.java	Thu May 17 15:19:29 2012 -0700
+++ b/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/MenuBarSkin.java	Mon May 21 14:09:46 2012 -0700
@@ -25,8 +25,6 @@
 
 package com.sun.javafx.scene.control.skin;
 
-import com.sun.javafx.css.StyleManager;
-import java.lang.reflect.Field;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.WeakHashMap;
@@ -52,14 +50,10 @@
 import javafx.scene.control.MenuButton;
 import javafx.scene.control.MenuItem;
 import javafx.scene.control.SeparatorMenuItem;
-import javafx.scene.input.KeyCode;
-import javafx.scene.input.KeyCodeCombination;
 import javafx.scene.input.KeyEvent;
 import javafx.scene.input.MouseEvent;
 import javafx.scene.layout.HBox;
-import javafx.stage.Modality;
 import javafx.stage.Stage;
-import javafx.stage.Window;
 
 import com.sun.javafx.menu.MenuBase;
 import com.sun.javafx.scene.control.GlobalMenuAdapter;
@@ -69,11 +63,8 @@
 import com.sun.javafx.scene.traversal.TraverseListener;
 import com.sun.javafx.stage.StageHelper;
 import com.sun.javafx.tk.Toolkit;
-import javafx.beans.property.*;
-import javafx.event.Event;
+import javafx.event.ActionEvent;
 import javafx.event.EventType;
-import javafx.geometry.Side;
-import javafx.scene.control.*;
 import javafx.scene.input.*;
 
 
@@ -335,6 +326,10 @@
         return null;
     }
     
+    int getFocusedMenuIndex() {
+        return focusedMenuIndex;
+    }
+    
     private boolean menusContainCustomMenuItem() {
         for (Menu menu : getSkinnable().getMenus()) {
             if (menuContainsCustomMenuItem(menu)) {
@@ -368,7 +363,30 @@
         return -1;
     }
     
+    // RT-20411 : reset menu selected/focused state 
+    private EventHandler<ActionEvent> menuActionEventHandler = new EventHandler<ActionEvent>() {
+        @Override
+        public void handle(ActionEvent t) {
+            unSelectMenus();
+        }
+    };
+    
+    private void updateActionListeners(Menu m, boolean add) {
+        for (MenuItem mi : m.getItems()) {
+            if (mi instanceof Menu) {
+                updateActionListeners((Menu)mi, add);
+            } else {
+                if (add) {
+                    mi.addEventHandler(ActionEvent.ACTION, menuActionEventHandler);
+                } else {
+                    mi.removeEventHandler(ActionEvent.ACTION, menuActionEventHandler);
+                }
+            }
+        }
+    }
+    
     private void rebuildUI() {
+        int index = 0;
         for(Node n : container.getChildren()) {
             //Stop observing menu's showing & disable property for changes.
             //Need to unbind before clearing container's children.
@@ -379,6 +397,8 @@
             menuButton.textProperty().unbind();
             menuButton.graphicProperty().unbind();
             menuButton.styleProperty().unbind();
+            updateActionListeners(getSkinnable().getMenus().get(index), false);
+            index++;
         }
         container.getChildren().clear();
 
@@ -625,6 +645,7 @@
                     }
                 }
             });
+            updateActionListeners(menu, true);
         }
         requestLayout();
     }
--- a/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/PaginationSkin.java	Thu May 17 15:19:29 2012 -0700
+++ b/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/PaginationSkin.java	Mon May 21 14:09:46 2012 -0700
@@ -73,7 +73,8 @@
 import javafx.geometry.VPos;
 import javafx.scene.Node;
 import javafx.scene.control.*;
-import javafx.scene.input.TouchEvent;
+import javafx.scene.input.ScrollEvent;
+import javafx.scene.input.SwipeEvent;
 import javafx.scene.layout.HBox;
 import javafx.scene.layout.StackPane;
 import javafx.scene.shape.Rectangle;
@@ -158,29 +159,39 @@
     private double pressPos;
     private boolean touchMoved = false;
     private void initializeSwipeAndTouchHandlers() {
-//        setOnSwipeLeft(new EventHandler<SwipeEvent>() {
-//            @Override public void handle(SwipeEvent t) {
-//                selectNext();
-//            }
-//        });
-//
-//        setOnSwipeRight(new EventHandler<SwipeEvent>() {
-//            @Override public void handle(SwipeEvent t) {
-//                selectPrevious();
-//            }
-//        });
+        setOnSwipeLeft(new EventHandler<SwipeEvent>() {
+            @Override public void handle(SwipeEvent t) {
+                touchMoved = false;
+                selectNext();
+                t.consume();
+            }
+        });
 
-        setOnTouchPressed(new EventHandler<TouchEvent>() {
-            @Override public void handle(TouchEvent e) {
-                pressPos = e.getTouchPoint().getSceneX();
+        setOnSwipeRight(new EventHandler<SwipeEvent>() {
+            @Override public void handle(SwipeEvent t) {
+                touchMoved = false;
+                selectPrevious();
+                t.consume();
+            }
+        });
+
+        setOnScrollStarted(new EventHandler<ScrollEvent>() {
+            @Override public void handle(ScrollEvent e) {
+                pressPos = e.getSceneX();
+                touchMoved = true;
                 e.consume();
             }
         });
 
-        setOnTouchMoved(new EventHandler<TouchEvent>() {
-            @Override public void handle(TouchEvent e) {
+        setOnScroll(new EventHandler<ScrollEvent>() {
+            @Override public void handle(ScrollEvent e) {
+                if (!touchMoved) {
+                    // Ignore any scroll events after the scrolling has finished.
+                    return;
+                }
+                
                 touchMoved = true;
-                double delta = e.getTouchPoint().getSceneX() - pressPos;
+                double delta = e.getSceneX() - pressPos;
                 double width = getWidth() - (getInsets().getLeft() + getInsets().getRight());
                 double currentScrollPaneX;
                 double nextScrollPaneX;
@@ -224,21 +235,21 @@
             }
         });
 
-        setOnTouchReleased(new EventHandler<TouchEvent>() {
+        setOnScrollFinished(new EventHandler<ScrollEvent>() {
             @Override
-            public void handle(TouchEvent e) {
-                double delta = Math.abs(e.getTouchPoint().getSceneX() - pressPos);
+            public void handle(ScrollEvent e) {
+                double delta = Math.abs(e.getSceneX() - pressPos);
                 double width = getWidth() - (getInsets().getLeft() + getInsets().getRight());
                 double threshold = delta/width;
                 if (touchMoved) {
                     if (threshold > THRESHOLD) {
-                        if (pressPos > e.getTouchPoint().getSceneX()) {
+                        if (pressPos > e.getSceneX()) {
                             selectNext();
                         } else {
                             selectPrevious();
                         }
                     } else {
-                        animateClamping(pressPos > e.getTouchPoint().getSceneX());
+                        animateClamping(pressPos > e.getSceneX());
                     }
                 }
                 touchMoved = false;
--- a/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/ScrollPaneSkin.java	Thu May 17 15:19:29 2012 -0700
+++ b/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/ScrollPaneSkin.java	Mon May 21 14:09:46 2012 -0700
@@ -28,6 +28,7 @@
 import com.sun.javafx.PlatformUtil;
 import static com.sun.javafx.Utils.clamp;
 import static com.sun.javafx.scene.control.skin.Utils.boundedSize;
+import javafx.animation.Animation.Status;
 import javafx.animation.Interpolator;
 import javafx.animation.KeyFrame;
 import javafx.animation.KeyValue;
@@ -344,8 +345,12 @@
                      dragDetected = false;
                  }
 
-                 if (posY > getSkinnable().getVmax() || posY < getSkinnable().getVmin() ||
-                     posX > getSkinnable().getHmax() || posX < getSkinnable().getHmin()) {
+                 /*
+                 ** if the contents need repositioning, and there's is no
+                 ** touch event in progress, then start the repositioning.
+                 */
+                 if ((posY > getSkinnable().getVmax() || posY < getSkinnable().getVmin() ||
+                     posX > getSkinnable().getHmax() || posX < getSkinnable().getHmin()) && !touchDetected) {
                      startContentsToViewport();
                  }
             }
@@ -475,12 +480,17 @@
                         }
                     }
                     else {
-                        vsb.setValue(newValue);
-                        if ((newValue > vsb.getMax() || newValue < vsb.getMin()) && !(mouseDown || touchDetected)) {
-                            startContentsToViewport();
+                        /*
+                        ** if there is a repositioning in progress then we only
+                        ** set the value for 'real' events
+                        */
+                        if (!(((ScrollEvent)event).isInertia()) || (((ScrollEvent)event).isInertia()) && (contentsToViewTimeline == null || contentsToViewTimeline.getStatus() == Status.STOPPED)) {
+                            vsb.setValue(newValue);
+                            if ((newValue > vsb.getMax() || newValue < vsb.getMin()) && (!mouseDown && !touchDetected)) {
+                                startContentsToViewport();
+                            }
+                            event.consume();
                         }
-
-                        event.consume();
                     }
                 }
 
@@ -496,13 +506,18 @@
                         }
                     }
                     else {
+                        /*
+                        ** if there is a repositioning in progress then we only
+                        ** set the value for 'real' events
+                        */
+                        if (!(((ScrollEvent)event).isInertia()) || (((ScrollEvent)event).isInertia()) && (contentsToViewTimeline == null || contentsToViewTimeline.getStatus() == Status.STOPPED)) {
+                            hsb.setValue(newValue);
 
-                        hsb.setValue(newValue);
-
-                        if (newValue > hsb.getMax() || newValue < hsb.getMin() && !(mouseDown || touchDetected)) {
-                            startContentsToViewport();
+                            if ((newValue > hsb.getMax() || newValue < hsb.getMin()) && (!mouseDown && !touchDetected)) {
+                                startContentsToViewport();
+                            }
+                            event.consume();
                         }
-                        event.consume();
                     }
                 }
             }
@@ -933,6 +948,7 @@
     Timeline contentsToViewTimeline;
     KeyFrame contentsToViewKF1;
     KeyFrame contentsToViewKF2;
+    KeyFrame contentsToViewKF3;
 
     private boolean tempVisibility;
 
@@ -998,7 +1014,14 @@
             contentsToViewTimeline.stop();
         }
         contentsToViewTimeline = new Timeline();
-        contentsToViewKF2 = new KeyFrame(Duration.millis(100), new EventHandler<ActionEvent>() {
+	/*
+	** short pause before animation starts
+	*/
+        contentsToViewKF1 = new KeyFrame(Duration.millis(50));
+	/*
+	** reposition
+	*/
+        contentsToViewKF2 = new KeyFrame(Duration.millis(150), new EventHandler<ActionEvent>() {
                 @Override public void handle(ActionEvent event) {
                     requestLayout();
                 }
@@ -1006,7 +1029,12 @@
             new KeyValue(contentPosX, newPosX),
             new KeyValue(contentPosY, newPosY)
             );
-        contentsToViewTimeline.getKeyFrames().addAll(contentsToViewKF2);
+	/*
+	** block out 'aftershocks', but real events will
+	** still reactivate
+	*/
+        contentsToViewKF3 = new KeyFrame(Duration.millis(1500));
+        contentsToViewTimeline.getKeyFrames().addAll(contentsToViewKF1, contentsToViewKF2, contentsToViewKF3);
         contentsToViewTimeline.playFromStart();
     }
 
--- a/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/TableHeaderRow.java	Thu May 17 15:19:29 2012 -0700
+++ b/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/TableHeaderRow.java	Mon May 21 14:09:46 2012 -0700
@@ -226,7 +226,6 @@
 
         // the header lives inside a NestedTableColumnHeader
         header = new NestedTableColumnHeader(table, null);
-        getChildren().add(0, header);
         header.setFocusTraversable(false);
         header.setTableHeaderRow(this);
 
@@ -278,7 +277,7 @@
         // the region that is anchored above the vertical scrollbar
         // a 'ghost' of the header being dragged by the user to force column
         // reordering
-        getChildren().addAll(filler, cornerRegion, dragHeader);
+        getChildren().addAll(filler, header, cornerRegion, dragHeader);
     }
     
     
--- a/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/TextAreaSkin.java	Thu May 17 15:19:29 2012 -0700
+++ b/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/TextAreaSkin.java	Mon May 21 14:09:46 2012 -0700
@@ -50,7 +50,6 @@
 import javafx.geometry.VerticalDirection;
 import javafx.scene.Group;
 import javafx.scene.Node;
-import javafx.scene.control.ContextMenu;
 import javafx.scene.control.IndexRange;
 import javafx.scene.control.ScrollPane;
 import javafx.scene.control.TextArea;
@@ -60,11 +59,11 @@
 import javafx.scene.shape.MoveTo;
 import javafx.scene.shape.Path;
 import javafx.scene.shape.PathElement;
-import javafx.scene.text.Font;
 import javafx.scene.text.Text;
 import javafx.util.Duration;
 import java.util.List;
 
+import com.sun.javafx.PlatformUtil;
 import com.sun.javafx.scene.control.behavior.TextAreaBehavior;
 import com.sun.javafx.scene.text.HitInfo;
 
@@ -236,12 +235,54 @@
             IndexRange selection = textArea.getSelection();
             Bounds oldCaretBounds = caretPath.getBoundsInParent();
 
-            caretPath.getElements().clear();
             selectionHighlightGroup.getChildren().clear();
 
+            int caretPos = textArea.getCaretPosition();
+            int anchorPos = textArea.getAnchor();
+
+            if (PlatformUtil.isEmbedded()) {
+                // Install and resize the handles for caret and anchor.
+                if (selection.getLength() > 0) {
+                    selectionHandle1.resize(selectionHandle1.prefWidth(-1),
+                                            selectionHandle1.prefHeight(-1));
+                    selectionHandle2.resize(selectionHandle2.prefWidth(-1),
+                                            selectionHandle2.prefHeight(-1));
+                } else {
+                    caretHandle.resize(caretHandle.prefWidth(-1),
+                                       caretHandle.prefHeight(-1));
+                }
+
+                // Position the handle for the anchor. This could be handle1 or handle2.
+                // Do this before positioning the actual caret.
+                if (selection.getLength() > 0) {
+                    int paragraphIndex = paragraphNodes.getChildren().size();
+                    int paragraphOffset = textArea.getLength() + 1;
+                    Text paragraphNode = null;
+                    do {
+                        paragraphNode = (Text)paragraphNodes.getChildren().get(--paragraphIndex);
+                        paragraphOffset -= paragraphNode.getText().length() + 1;
+                    } while (anchorPos < paragraphOffset);
+
+                    paragraphNode.setImpl_caretPosition(anchorPos - paragraphOffset);
+                    caretPath.getElements().clear();
+                    caretPath.getElements().addAll(paragraphNode.getImpl_caretShape());
+                    caretPath.setLayoutX(paragraphNode.getLayoutX());
+                    caretPath.setLayoutY(paragraphNode.getLayoutY());
+
+                    Bounds b = caretPath.getBoundsInParent();
+                    if (caretPos < anchorPos) {
+                        selectionHandle2.setLayoutX(b.getMinX() - selectionHandle2.getWidth() / 2);
+                        selectionHandle2.setLayoutY(b.getMaxY());
+                    } else {
+                        selectionHandle1.setLayoutX(b.getMinX() - selectionHandle1.getWidth() / 2);
+                        //selectionHandle1.setLayoutY(b.getMinY() - selectionHandle1.getHeight());
+                        selectionHandle1.setLayoutY(b.getMaxY());
+                    }
+                }
+            }
+
             {
-                int caretPos = textArea.getCaretPosition();
-
+                // Position caret
                 int paragraphIndex = paragraphNodes.getChildren().size();
                 int paragraphOffset = textArea.getLength() + 1;
 
@@ -253,6 +294,7 @@
 
                 paragraphNode.setImpl_caretPosition(caretPos - paragraphOffset);
 
+                caretPath.getElements().clear();
                 caretPath.getElements().addAll(paragraphNode.getImpl_caretShape());
 
                 caretPath.setLayoutX(paragraphNode.getLayoutX());
@@ -293,6 +335,24 @@
                 end   = Math.max(0, end   - paragraphLength);
             }
 
+            if (PlatformUtil.isEmbedded()) {
+                // Position handle for the caret. This could be handle1 or handle2 when
+                // a selection is active.
+                Bounds b = caretPath.getBoundsInParent();
+                if (selection.getLength() > 0) {
+                    if (caretPos < anchorPos) {
+                        selectionHandle1.setLayoutX(b.getMinX() - selectionHandle1.getWidth() / 2);
+                        //selectionHandle1.setLayoutY(b.getMinY() - selectionHandle1.getHeight());
+                        selectionHandle1.setLayoutY(b.getMaxY());
+                    } else {
+                        selectionHandle2.setLayoutX(b.getMinX() - selectionHandle2.getWidth() / 2);
+                        selectionHandle2.setLayoutY(b.getMaxY());
+                    }
+                } else {
+                    caretHandle.setLayoutX(b.getMinX() - caretHandle.getWidth() / 2 + 1);
+                    caretHandle.setLayoutY(b.getMaxY());
+                }
+            }
 
             if (scrollPane.getPrefViewportWidth() == 0
                 || scrollPane.getPrefViewportHeight() == 0) {
@@ -343,6 +403,8 @@
 
     public static final int SCROLL_RATE = 30;
 
+    private double pressX, pressY; // For dragging handles on embedded
+
     public TextAreaSkin(final TextArea textArea) {
         super(textArea, new TextAreaBehavior(textArea));
         getBehavior().setTextAreaSkin(this);
@@ -369,11 +431,6 @@
         scrollPane.setContent(contentView);
         getChildren().add(scrollPane);
 
-        // Workaround
-        if (textArea.getContextMenu() != null) {
-            scrollPane.setContextMenu(textArea.getContextMenu());
-        }
-
         // Add selection
         selectionHighlightGroup.setManaged(false);
         selectionHighlightGroup.setVisible(false);
@@ -391,6 +448,10 @@
         caretPath.visibleProperty().bind(caretVisible);
         contentView.getChildren().add(caretPath);
 
+        if (PlatformUtil.isEmbedded()) {
+            contentView.getChildren().addAll(caretHandle, selectionHandle1, selectionHandle2);
+        }
+
         scrollPane.hvalueProperty().addListener(new ChangeListener<Number>() {
             @Override
             public void changed(ObservableValue<? extends Number> observable, Number oldValue, Number newValue) {
@@ -566,6 +627,104 @@
         updatePrefViewportWidth();
         updatePrefViewportHeight();
         if (textArea.isFocused()) setCaretAnimating(true);
+
+        if (PlatformUtil.isEmbedded()) {
+            //selectionHandle1.setRotate(180);
+
+            EventHandler<MouseEvent> handlePressHandler = new EventHandler<MouseEvent>() {
+                @Override public void handle(MouseEvent e) {
+                    pressX = e.getX();
+                    pressY = e.getY();
+                    e.consume();
+                }
+            };
+
+            caretHandle.setOnMousePressed(handlePressHandler);
+            selectionHandle1.setOnMousePressed(handlePressHandler);
+            selectionHandle2.setOnMousePressed(handlePressHandler);
+
+            caretHandle.setOnMouseDragged(new EventHandler<MouseEvent>() {
+                @Override public void handle(MouseEvent e) {
+                    Text textNode = getTextNode();
+                    Point2D p = new Point2D(caretHandle.getLayoutX() + e.getX() + pressX - textNode.getLayoutX(),
+                                            caretHandle.getLayoutY() + e.getY() - pressY - 6 - getTextTranslateY());
+                    HitInfo hit = textNode.impl_hitTestChar(translateCaretPosition(p));
+                    int pos = hit.getCharIndex();
+                    if (pos > 0) {
+                        int oldPos = textNode.getImpl_caretPosition();
+                        textNode.setImpl_caretPosition(pos);
+                        PathElement element = textNode.getImpl_caretShape()[0];
+                        if (element instanceof MoveTo && ((MoveTo)element).getY() > e.getY() - getTextTranslateY()) {
+                            hit.setCharIndex(pos - 1);
+                        }
+                        textNode.setImpl_caretPosition(oldPos);
+                    }
+                    positionCaret(hit, false, false);
+                    e.consume();
+                }
+            });
+
+            selectionHandle1.setOnMouseDragged(new EventHandler<MouseEvent>() {
+                @Override public void handle(MouseEvent e) {
+                    TextArea textArea = getSkinnable();
+                    Text textNode = getTextNode();
+                    Point2D tp = textNode.localToScene(0, 0);
+                    Point2D p = new Point2D(e.getSceneX() - tp.getX() + 10/*??*/ - pressX + selectionHandle1.getWidth() / 2,
+                                            //e.getSceneY() - tp.getY() - pressY + selectionHandle1.getHeight() + 5);
+                                            e.getSceneY() - tp.getY() - pressY - 6);
+                    HitInfo hit = textNode.impl_hitTestChar(translateCaretPosition(p));
+                    int pos = hit.getCharIndex();
+                    if (textArea.getAnchor() < textArea.getCaretPosition()) {
+                        // Swap caret and anchor
+                        textArea.selectRange(textArea.getCaretPosition(), textArea.getAnchor());
+                    }
+                    if (pos >= 0) {
+                        if (pos >= textArea.getAnchor()) {
+                            pos = textArea.getAnchor();
+                        }
+                        int oldPos = textNode.getImpl_caretPosition();
+                        textNode.setImpl_caretPosition(pos);
+                        PathElement element = textNode.getImpl_caretShape()[0];
+                        if (element instanceof MoveTo && ((MoveTo)element).getY() > e.getY() - getTextTranslateY()) {
+                            hit.setCharIndex(pos - 1);
+                        }
+                        textNode.setImpl_caretPosition(oldPos);
+                        positionCaret(hit, true, false);
+                    }
+                    e.consume();
+                }
+            });
+
+            selectionHandle2.setOnMouseDragged(new EventHandler<MouseEvent>() {
+                @Override public void handle(MouseEvent e) {
+                    TextArea textArea = getSkinnable();
+                    Text textNode = getTextNode();
+                    Point2D tp = textNode.localToScene(0, 0);
+                    Point2D p = new Point2D(e.getSceneX() - tp.getX() + 10/*??*/ - pressX + selectionHandle2.getWidth() / 2,
+                                            e.getSceneY() - tp.getY() - pressY - 6);
+                    HitInfo hit = textNode.impl_hitTestChar(translateCaretPosition(p));
+                    int pos = hit.getCharIndex();
+                    if (textArea.getAnchor() > textArea.getCaretPosition()) {
+                        // Swap caret and anchor
+                        textArea.selectRange(textArea.getCaretPosition(), textArea.getAnchor());
+                    }
+                    if (pos > 0) {
+                        if (pos <= textArea.getAnchor() + 1) {
+                            pos = Math.min(textArea.getAnchor() + 2, textArea.getLength());
+                        }
+                        int oldPos = textNode.getImpl_caretPosition();
+                        textNode.setImpl_caretPosition(pos);
+                        PathElement element = textNode.getImpl_caretShape()[0];
+                        if (element instanceof MoveTo && ((MoveTo)element).getY() > e.getY() - getTextTranslateY()) {
+                            hit.setCharIndex(pos - 1);
+                        }
+                        textNode.setImpl_caretPosition(oldPos);
+                        positionCaret(hit, true, false);
+                    }
+                    e.consume();
+                }
+            });
+        }
     }
 
     private void createPromptNode() {
@@ -791,17 +950,6 @@
         return new Rectangle2D(x, y, width, height);
     }
 
-    @Override public boolean showContextMenu(ContextMenu menu, double x, double y, boolean isKeyboardTrigger) {
-        if (isKeyboardTrigger) {
-            Bounds caretBounds = caretPath.getLayoutBounds();
-            Point2D p = com.sun.javafx.Utils.pointRelativeTo(contentView, null, caretBounds.getMinX(),
-                                                             caretBounds.getMaxY(), false);
-            x = p.getX();
-            y = p.getY();
-        }
-        return super.showContextMenu(menu, x, y, isKeyboardTrigger);
-    }
-
     @Override public void scrollCharacterToVisible(final int index) {
         // TODO We queue a callback because when characters are added or
         // removed the bounds are not immediately updated; is this really
@@ -1127,4 +1275,15 @@
 //            scrollAfterDelete(textMaxXOld, caretMaxXOld);
         }
     }
+
+    @Override public Point2D getMenuPosition() {
+        contentView.layoutChildren();
+        Point2D p = super.getMenuPosition();
+        if (p != null) {
+            Insets padding = contentView.getInsets();
+            p = new Point2D(Math.max(0, p.getX() - padding.getLeft() - getSkinnable().getScrollLeft()),
+                            Math.max(0, p.getY() - padding.getTop() - getSkinnable().getScrollTop()));
+        }
+        return p;
+    }
 }
--- a/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/TextFieldSkin.java	Thu May 17 15:19:29 2012 -0700
+++ b/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/TextFieldSkin.java	Mon May 21 14:09:46 2012 -0700
@@ -41,13 +41,13 @@
 import javafx.beans.value.ObservableDoubleValue;
 import javafx.beans.value.ObservableIntegerValue;
 import javafx.beans.value.ObservableValue;
+import javafx.event.EventHandler;
 import javafx.geometry.Bounds;
 import javafx.geometry.Insets;
 import javafx.geometry.Point2D;
 import javafx.geometry.Rectangle2D;
 import javafx.scene.Group;
 import javafx.scene.Node;
-import javafx.scene.control.ContextMenu;
 import javafx.scene.control.IndexRange;
 import javafx.scene.control.TextField;
 import javafx.scene.input.MouseEvent;
@@ -58,7 +58,7 @@
 import javafx.scene.text.Text;
 import java.util.List;
 
-import com.sun.javafx.Utils;
+import com.sun.javafx.PlatformUtil;
 import com.sun.javafx.scene.control.behavior.TextFieldBehavior;
 import com.sun.javafx.scene.text.HitInfo;
 import com.sun.javafx.tk.FontMetrics;
@@ -142,16 +142,7 @@
      */
     protected ObservableDoubleValue textRight;
 
-    @Override public boolean showContextMenu(ContextMenu menu, double x, double y, boolean isKeyboardTrigger) {
-        if (isKeyboardTrigger) {
-            Bounds caretBounds = caretPath.getLayoutBounds();
-            Point2D p = Utils.pointRelativeTo(textNode, null, caretBounds.getMinX(),
-                                              caretBounds.getMaxY(), false);
-            x = p.getX();
-            y = p.getY();
-        }
-        return super.showContextMenu(menu, x, y, isKeyboardTrigger);
-    }
+    private double pressX, pressY; // For dragging handles on embedded
 
     /**
      * Create a new TextFieldSkin.
@@ -244,6 +235,9 @@
         textGroup.setClip(clip);
         textGroup.getChildren().addAll(selectionHighlightPath, textNode, caretPath);
         getChildren().add(textGroup);
+        if (PlatformUtil.isEmbedded()) {
+            /*textGroup.*/getChildren().addAll(caretHandle, selectionHandle1, selectionHandle2);
+        }
 
         // Add text
         textNode.setManaged(false);
@@ -355,6 +349,75 @@
                 requestLayout();
             }
         });
+
+        if (PlatformUtil.isEmbedded()) {
+            EventHandler<MouseEvent> handlePressHandler = new EventHandler<MouseEvent>() {
+                @Override public void handle(MouseEvent e) {
+                    pressX = e.getX();
+                    pressY = e.getY();
+                    e.consume();
+                }
+            };
+
+            caretHandle.setOnMousePressed(handlePressHandler);
+            selectionHandle1.setOnMousePressed(handlePressHandler);
+            selectionHandle2.setOnMousePressed(handlePressHandler);
+
+            caretHandle.setOnMouseDragged(new EventHandler<MouseEvent>() {
+                @Override public void handle(MouseEvent e) {
+                    Point2D p = new Point2D(caretHandle.getLayoutX() + e.getX() + pressX - textNode.getLayoutX(),
+                                            caretHandle.getLayoutY() + e.getY() - pressY - 6);
+                    HitInfo hit = textNode.impl_hitTestChar(translateCaretPosition(p));
+                    int pos = hit.getCharIndex();
+                    positionCaret(hit, false);
+                    e.consume();
+                }
+            });
+
+            selectionHandle1.setOnMouseDragged(new EventHandler<MouseEvent>() {
+                @Override public void handle(MouseEvent e) {
+                    TextField textField = getSkinnable();
+                    Point2D tp = textNode.localToScene(0, 0);
+                    Point2D p = new Point2D(e.getSceneX() - tp.getX() + 10/*??*/ - pressX + selectionHandle1.getWidth() / 2,
+                                            e.getSceneY() - tp.getY() - pressY - 6);
+                    HitInfo hit = textNode.impl_hitTestChar(translateCaretPosition(p));
+                    int pos = hit.getCharIndex();
+                    if (textField.getAnchor() < textField.getCaretPosition()) {
+                        // Swap caret and anchor
+                        textField.selectRange(textField.getCaretPosition(), textField.getAnchor());
+                    }
+                    if (pos >= 0) {
+                        if (pos >= textField.getAnchor() - 1) {
+                            hit.setCharIndex(Math.max(0, textField.getAnchor() - 1));
+                        }
+                        positionCaret(hit, true);
+                    }
+                    e.consume();
+                }
+            });
+
+            selectionHandle2.setOnMouseDragged(new EventHandler<MouseEvent>() {
+                @Override public void handle(MouseEvent e) {
+                    TextField textField = getSkinnable();
+                    Point2D tp = textNode.localToScene(0, 0);
+                    Point2D p = new Point2D(e.getSceneX() - tp.getX() + 10/*??*/ - pressX + selectionHandle2.getWidth() / 2,
+                                            e.getSceneY() - tp.getY() - pressY - 6);
+                    HitInfo hit = textNode.impl_hitTestChar(translateCaretPosition(p));
+                    int pos = hit.getCharIndex();
+                    if (textField.getAnchor() > textField.getCaretPosition()) {
+                        // Swap caret and anchor
+                        textField.selectRange(textField.getCaretPosition(), textField.getAnchor());
+                    }
+                    if (pos > 0) {
+                        if (pos <= textField.getAnchor()) {
+                            hit.setCharIndex(Math.min(textField.getAnchor() + 1, textField.getLength()));
+                        }
+                        positionCaret(hit, true);
+                    }
+                    e.consume();
+                }
+            });
+        }
     }
 
     private void createPromptNode() {
@@ -391,6 +454,12 @@
         } else {
             selectionHighlightPath.getElements().setAll(elements);
         }
+
+        if (PlatformUtil.isEmbedded() && newValue != null && newValue.getLength() > 0) {
+            Bounds b = selectionHighlightPath.getBoundsInParent();
+            selectionHandle1.setLayoutX(b.getMinX() - selectionHandle1.getWidth() / 2);
+            selectionHandle2.setLayoutX(b.getMaxX() - selectionHandle2.getWidth() / 2);
+        }
     }
 
     @Override protected void handleControlPropertyChanged(String propertyReference) {
@@ -485,6 +554,9 @@
             textTranslateX.set(Math.min(textTranslateX.get() - delta,
                                         caretWidth / 2));
         }
+        if (PlatformUtil.isEmbedded()) {
+            caretHandle.setLayoutX(caretX - caretHandle.getWidth() / 2 + 1);
+        }
     }
 
     /**
@@ -668,5 +740,33 @@
                 promptNode.setY(textY);
             }
         }
+
+        if (PlatformUtil.isEmbedded()) {
+            TextField textField = getSkinnable();
+
+            // Resize handles for caret and anchor.
+            IndexRange selection = textField.getSelection();
+            selectionHandle1.resize(selectionHandle1.prefWidth(-1),
+                                    selectionHandle1.prefHeight(-1));
+            selectionHandle2.resize(selectionHandle2.prefWidth(-1),
+                                    selectionHandle2.prefHeight(-1));
+            caretHandle.resize(caretHandle.prefWidth(-1),
+                               caretHandle.prefHeight(-1));
+
+            Bounds b = caretPath.getBoundsInParent();
+            selectionHandle1.setLayoutY(b.getMaxY() - 3);
+            selectionHandle2.setLayoutY(b.getMaxY() - 3);
+            caretHandle.setLayoutY(b.getMaxY() - 3);
+        }
+    }
+
+    @Override public Point2D getMenuPosition() {
+        Point2D p = super.getMenuPosition();
+        if (p != null) {
+            Insets padding = getInsets();
+            p = new Point2D(Math.max(0, p.getX() - textNode.getLayoutX() - padding.getLeft() + textTranslateX.get()),
+                            Math.max(0, p.getY() - textNode.getLayoutY() - padding.getTop()));
+        }
+        return p;
     }
 }
--- a/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/TextInputControlSkin.java	Thu May 17 15:19:29 2012 -0700
+++ b/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/TextInputControlSkin.java	Mon May 21 14:09:46 2012 -0700
@@ -55,7 +55,7 @@
 import javafx.scene.input.InputMethodHighlight;
 import javafx.scene.input.InputMethodRequests;
 import javafx.scene.input.InputMethodTextRun;
-import javafx.scene.input.TouchEvent;
+import javafx.scene.layout.StackPane;
 import javafx.scene.paint.Color;
 import javafx.scene.paint.Paint;
 import javafx.scene.shape.ClosePath;
@@ -230,6 +230,28 @@
      */
     protected final Path caretPath = new Path();
 
+    protected StackPane caretHandle = null;
+    protected StackPane selectionHandle1 = null;
+    protected StackPane selectionHandle2 = null;
+
+    public Point2D getMenuPosition() {
+        if (PlatformUtil.isEmbedded()) {
+            if (caretHandle.isVisible()) {
+                return new Point2D(caretHandle.getLayoutX() + caretHandle.getWidth() / 2,
+                                   caretHandle.getLayoutY());
+            } else if (selectionHandle1.isVisible() && selectionHandle2.isVisible()) {
+                return new Point2D((selectionHandle1.getLayoutX() + selectionHandle1.getWidth() / 2 +
+                                    selectionHandle2.getLayoutX() + selectionHandle2.getWidth() / 2) / 2,
+                                   selectionHandle2.getLayoutY() + selectionHandle2.getHeight() / 2);
+            } else {
+                return null;
+            }
+        } else {
+            throw new UnsupportedOperationException();
+        }
+    }
+
+
     private static boolean useFXVK = PlatformUtil.isEmbedded();
 
     /* For testing only */
@@ -287,76 +309,72 @@
         };
 
         if (PlatformUtil.isEmbedded()) {
-            textInput.focusedProperty().addListener(new InvalidationListener() {
-                @Override public void invalidated(Observable observable) {
-                    if (useFXVK) {
-                        Platform.runLater(new Runnable() {
-                            public void run() {
-                                if (textInput.isFocused()) {
-                                    FXVK.attach(textInput);
-                                } else if (!(getScene().getFocusOwner() instanceof TextInputControl)) {
-                                    FXVK.detach();
-                                }
-                            }
-                        });
-                    }
+            caretHandle      = new StackPane();
+            selectionHandle1 = new StackPane();
+            selectionHandle2 = new StackPane();
+
+            caretHandle.setManaged(false);
+            selectionHandle1.setManaged(false);
+            selectionHandle2.setManaged(false);
+
+            caretHandle.visibleProperty().bind(new BooleanBinding() {
+                { bind(textInput.focusedProperty(), textInput.anchorProperty(),
+                       textInput.caretPositionProperty(), textInput.disabledProperty(),
+                       textInput.editableProperty(), textInput.lengthProperty(), displayCaret);}
+                @Override protected boolean computeValue() {
+                    return (displayCaret.get() && textInput.isFocused() &&
+                            textInput.getCaretPosition() == textInput.getAnchor() &&
+                            !textInput.isDisabled() && textInput.isEditable() &&
+                            textInput.getLength() > 0);
                 }
             });
 
-            if (textInput.getOnTouchStationary() == null) {
-                textInput.setOnTouchStationary(new EventHandler<TouchEvent>() {
-                    @Override public void handle(TouchEvent event) {
-                        ContextMenu menu = textInput.getContextMenu();
-                        if (menu != null &&
-                            showContextMenu(menu, event.getTouchPoint().getScreenX(),
-                                            event.getTouchPoint().getScreenY(), false)) {
-                            event.consume();
-                        }
-                    }
-                });
-            }
-        }
 
-        if (textInput.getContextMenu() == null) {
-            class ContextMenuItem extends MenuItem {
-                ContextMenuItem(final String action) {
-                    super(getString("TextInputControl.menu." + action));
-                    setOnAction(new EventHandler<ActionEvent>() {
-                        @Override public void handle(ActionEvent e) {
-                            behavior.callAction(action);
-                        }
-                    });
-                }
-            }
-
-            final MenuItem undoMI   = new ContextMenuItem("Undo");
-            final MenuItem redoMI   = new ContextMenuItem("Redo");
-            final MenuItem cutMI    = new ContextMenuItem("Cut");
-            final MenuItem copyMI   = new ContextMenuItem("Copy");
-            final MenuItem pasteMI  = new ContextMenuItem("Paste");
-            final MenuItem deleteMI = new ContextMenuItem("DeleteSelection");
-            final MenuItem selectMI = new ContextMenuItem("SelectAll");
-
-            final ContextMenu cm = new ContextMenu(undoMI, redoMI, cutMI, copyMI, pasteMI, deleteMI,
-                                                   new SeparatorMenuItem(), selectMI);
-
-            cm.setOnShowing(new EventHandler<WindowEvent>() {
-                public void handle(WindowEvent e) {
-                    boolean hasSelection = (textInput.getSelection().getLength() > 0);
-                    boolean maskText = (maskText("A") != "A");
-
-                    undoMI.setDisable(!getBehavior().canUndo());
-                    redoMI.setDisable(!getBehavior().canRedo());
-                    cutMI.setDisable(maskText || !hasSelection);
-                    copyMI.setDisable(maskText || !hasSelection);
-                    pasteMI.setDisable(!Clipboard.getSystemClipboard().hasString());
-                    deleteMI.setDisable(!hasSelection);
+            selectionHandle1.visibleProperty().bind(new BooleanBinding() {
+                { bind(textInput.focusedProperty(), textInput.anchorProperty(), textInput.caretPositionProperty(),
+                       textInput.disabledProperty(), displayCaret);}
+                @Override protected boolean computeValue() {
+                    return (displayCaret.get() && textInput.isFocused() &&
+                            textInput.getCaretPosition() != textInput.getAnchor() &&
+                            !textInput.isDisabled());
                 }
             });
 
-            textInput.setContextMenu(cm);
+
+            selectionHandle2.visibleProperty().bind(new BooleanBinding() {
+                { bind(textInput.focusedProperty(), textInput.anchorProperty(), textInput.caretPositionProperty(),
+                       textInput.disabledProperty(), displayCaret);}
+                @Override protected boolean computeValue() {
+                    return (displayCaret.get() && textInput.isFocused() &&
+                            textInput.getCaretPosition() != textInput.getAnchor() &&
+                            !textInput.isDisabled());
+                }
+            });
+
+
+            caretHandle.getStyleClass().setAll("caret-handle");
+            selectionHandle1.getStyleClass().setAll("selection-handle");
+            selectionHandle2.getStyleClass().setAll("selection-handle");
+
+            selectionHandle1.setId("selection-handle-1");
+            selectionHandle2.setId("selection-handle-2");
+
+//             textInput.focusedProperty().addListener(new InvalidationListener() {
+//                 @Override public void invalidated(Observable observable) {
+//                     if (useFXVK) {
+//                         if (textInput.isFocused()) {
+//                             FXVK.attach(textInput);
+//                         } else if (getScene() == null ||
+//                                    getScene().getWindow() == null ||
+//                                    !getScene().getWindow().isFocused() ||
+//                                    !(getScene().getFocusOwner() instanceof TextInputControl)) {
+//                             FXVK.detach();
+//                         }
+//                     }
+//                 }
+//             });
         }
-
+                    
         if (textInput.getOnInputMethodTextChanged() == null) {
             textInput.setOnInputMethodTextChanged(new EventHandler<InputMethodEvent>() {
                 @Override public void handle(InputMethodEvent event) {
@@ -396,7 +414,7 @@
             }
         });
     }
-
+    
     @Override public void dispose() {
         caretTimeline.stop();
         caretTimeline = null;
@@ -430,6 +448,10 @@
      */
     public Rectangle2D getCharacterBounds(int index) { return null; }
 
+    public double getLineHeight() {
+        return fontMetrics.get().getLineHeight();
+    }
+
     /**
      * Ensures that the character at a given index is visible.
      *
@@ -563,6 +585,63 @@
         }
     }
 
+    class ContextMenuItem extends MenuItem {
+        ContextMenuItem(final String action) {
+            super(getString("TextInputControl.menu." + action));
+            setOnAction(new EventHandler<ActionEvent>() {
+                @Override public void handle(ActionEvent e) {
+                    getBehavior().callAction(action);
+                }
+            });
+        }
+    }
+
+    final MenuItem undoMI   = new ContextMenuItem("Undo");
+    final MenuItem redoMI   = new ContextMenuItem("Redo");
+    final MenuItem cutMI    = new ContextMenuItem("Cut");
+    final MenuItem copyMI   = new ContextMenuItem("Copy");
+    final MenuItem pasteMI  = new ContextMenuItem("Paste");
+    final MenuItem deleteMI = new ContextMenuItem("DeleteSelection");
+    final MenuItem selectWordMI = new ContextMenuItem("SelectWord");
+    final MenuItem selectAllMI = new ContextMenuItem("SelectAll");
+
+    public void populateContextMenu(ContextMenu contextMenu) {
+        boolean hasText = (getSkinnable().getLength() > 0);
+        boolean hasSelection = (getSkinnable().getSelection().getLength() > 0);
+        boolean maskText = (maskText("A") != "A");
+        ObservableList<MenuItem> items = contextMenu.getItems();
+
+        if (PlatformUtil.isEmbedded()) {
+            items.clear();
+            if (!maskText && hasSelection) {
+                items.add(cutMI);
+                items.add(copyMI);
+            }
+            if (Clipboard.getSystemClipboard().hasString()) {
+                items.add(pasteMI);
+            }
+            if (hasText) {
+                if (!hasSelection) {
+                    items.add(selectWordMI);
+                }
+                items.add(selectAllMI);
+            }
+            selectWordMI.getProperties().put("refreshMenu", Boolean.TRUE);
+            selectAllMI.getProperties().put("refreshMenu", Boolean.TRUE);
+        } else {
+            if (items.size() == 0) {
+                items.addAll(undoMI, redoMI, cutMI, copyMI, pasteMI, deleteMI,
+                             new SeparatorMenuItem(), selectAllMI);
+            }
+            undoMI.setDisable(!getBehavior().canUndo());
+            redoMI.setDisable(!getBehavior().canRedo());
+            cutMI.setDisable(maskText || !hasSelection);
+            copyMI.setDisable(maskText || !hasSelection);
+            pasteMI.setDisable(!Clipboard.getSystemClipboard().hasString());
+            deleteMI.setDisable(!hasSelection);
+        }
+    }
+
     private static class StyleableProperties {
         private static final StyleableProperty<TextInputControlSkin,Font> FONT =
            new StyleableProperty.FONT<TextInputControlSkin>("-fx-font", Font.getDefault()) {
--- a/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/caspian/caspian.css	Thu May 17 15:19:29 2012 -0700
+++ b/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/caspian/caspian.css	Mon May 21 14:09:46 2012 -0700
@@ -794,6 +794,7 @@
     -fx-stroke: -fx-text-fill;
 } 
 
+
 /*******************************************************************************
  *                                                                             *
  * Menu                                                                        *
@@ -3039,11 +3040,16 @@
 
 /* ------- OPEN BUTTON ------- */
 .combo-box-base .arrow-button {
-    -fx-background-color: null;
+    -fx-background-color: -fx-outer-border, -fx-inner-border, -fx-body-color;
     -fx-background-insets: 0, 1, 2;
     -fx-background-radius: 0 5 5 0, 0 4 4 0, 0 3 3 0;
-    -fx-padding: 0.5em 0.416667em 0.5em 0.416667em; /* 6 5 6 5 */
-}
+    -fx-padding: 0.5em 0.416667em 0.5em 0.416667em; /* 6 5 6 5  */
+}
+/*    -fx-background-color: null;
+    -fx-background-insets: 0, 1, 2;
+    -fx-background-radius: 0 5 5 0, 0 4 4 0, 0 3 3 0;
+    -fx-padding: 0.5em 0.416667em 0.5em 0.416667em;  6 5 6 5 
+}*/
 /*.combo-box-base.split-button .arrow-button {
     -fx-background-color: -fx-outer-border, -fx-inner-border, -fx-body-color;
     -fx-background-insets: 0, 1, 2;
@@ -3133,11 +3139,18 @@
     -fx-skin: "com.sun.javafx.scene.control.skin.ColorPickerSkin";
 }
 
+.color-picker .arrow-button {
+    -fx-background-color: null;
+    -fx-background-insets: 0, 1, 2;
+    -fx-background-radius: 0 5 5 0, 0 4 4 0, 0 3 3 0;
+    -fx-padding: 0.5em 0.416667em 0.5em 0.416667em; /* 6 5 6 5 */
+}
+
 .color-picker .color-picker-label .text {
     -fx-padding: 0.0em 0.833333em 0.0em 0.0em;  /* 0 10 0 0 */
 }
 
-.color-picker.split-button .arrow-button {
+.color-picker .split-button .arrow-button {
     -fx-background-color: -fx-outer-border, -fx-inner-border, -fx-body-color;
     -fx-background-insets: 0, 1, 2;
     -fx-background-radius: 0 5 5 0, 0 4 4 0, 0 3 3 0;
@@ -3148,11 +3161,11 @@
     -fx-color: -fx-base;
 }
 
-.color-picker.split-button .arrow-button:hover {
+.color-picker .split-button .arrow-button:hover {
     -fx-color: -fx-hover-base;
 }
 
-.color-picker.split-button .color-picker-label:hover {
+.color-picker .split-button .color-picker-label:hover {
      -fx-color: -fx-hover-base;
 }
 
@@ -3491,4 +3504,4 @@
 }
 .pagination .pagination-control .page-information {   
     -fx-padding: 0.416em 0 0 0;
-}
\ No newline at end of file
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/caspian/embedded-qvga.css	Mon May 21 14:09:46 2012 -0700
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. 
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 
+ *  
+ * This code is free software; you can redistribute it and/or modify it 
+ * under the terms of the GNU General Public License version 2 only, as 
+ * published by the Free Software Foundation.  Oracle designates this 
+ * particular file as subject to the "Classpath" exception as provided 
+ * by Oracle in the LICENSE file that accompanied this code. 
+ *  
+ * This code is distributed in the hope that it will be useful, but WITHOUT 
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License 
+ * version 2 for more details (a copy is included in the LICENSE file that 
+ * accompanied this code). 
+ *  
+ * You should have received a copy of the GNU General Public License version 
+ * 2 along with this work; if not, write to the Free Software Foundation, 
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 
+ *  
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 
+ * or visit www.oracle.com if you need additional information or have any 
+ * questions.
+ *                                                                              
+ */
+
+/*******************************************************************************
+ *                                                                             *
+ * CSS Styles for embedded devices that have QVGA screens. These styles either *
+ * override or supplement those in caspian.css and embedded.css (which is      *
+ * targeted at VGA screens).                                                   *
+ *                                                                             *
+ ******************************************************************************/
--- a/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/caspian/embedded.css	Thu May 17 15:19:29 2012 -0700
+++ b/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/caspian/embedded.css	Mon May 21 14:09:46 2012 -0700
@@ -33,6 +33,31 @@
 
 /*******************************************************************************
  *                                                                             *
+ * PopupMenu                                                                   *
+ *                                                                             *
+ ******************************************************************************/
+
+.context-menu .text-input-context-menu {
+    -fx-background-color: transparent;
+    -fx-background-radius: 0;
+    -fx-padding: 0;
+}
+
+.context-menu .text-input-context-menu .button {
+    -fx-background-radius: 0;   
+    -fx-background-color: derive(-fx-color,-40%);
+    -fx-text-fill: white;
+}
+
+.context-menu .text-input-context-menu .pointer {    
+    -fx-background-color: derive(-fx-color,-40%);    
+    -fx-padding: 6px;
+    -fx-shape: "M 6 0 L 12 12 L 0 12 z";
+    -fx-scale-shape: true;
+}
+
+/*******************************************************************************
+ *                                                                             *
  * ScrollBar                                                                   *
  *                                                                             *
  ******************************************************************************/
@@ -67,6 +92,39 @@
 }
 
 
+.caret-handle {
+    -fx-background-color: black /*#ACACAC*/,
+                          linear-gradient(to bottom, #AFAFAF 0%, #DFDFDF 100%);
+    -fx-background-insets: 0, 1;
+    -fx-shape: "M11.974,2.579L20,12.358V28H4V12.356L11.974,2.579z";
+/*
+    -fx-shape: "M11.972,1L3,12v17h18V12L11.972,1L11.972,1z";
+    -fx-padding: 0.375em 0.291em 0.375em 0.291em;
+*/
+    -fx-padding: 0.45em 0.3em 0.45em 0.3em;
+    -fx-cursor: hand;
+}
+
+.selection-handle {
+    -fx-background-color: transparent, #0071bc /*-fx-accent*/,
+                          linear-gradient(to bottom, #0063AA 0%, #008AED 100%);
+    -fx-background-insets: 0, 0, 1;
+    -fx-shape: "M10.974,2.579L19,12.358V28H3V12.356L10.974,2.579z";
+/*
+    -fx-shape: "M10.972,1L2,12v17h18V12L10.972,1L10.972,1z";
+    -fx-padding: 0.375em 0.291em 0.375em 0.291em;
+*/
+    -fx-padding: 0.45em 0.3em 0.45em 0.3em;
+    -fx-cursor: hand;
+}
+
+#selection-handle-1 {
+    -fx-background-insets: -4 0 -4 -4, 0, 1;
+}
+
+#selection-handle-2 {
+    -fx-background-insets: -4 -4 -4 0, 0, 1;
+}
 
 /*******************************************************************************
  *                                                                             *
@@ -105,7 +163,7 @@
     -fx-font-weight: bold;
     -fx-font: bold 36px "Amble";
     -fx-text-fill: #333333;
-    -fx-padding: 3 6 5 0;
+    -fx-padding: 3 3 5 0;
     -fx-background-radius: 4;
     -fx-effect: dropshadow(three-pass-box, rgba(0, 0, 0, 0.75), 2, 0.0, 0, 1);
 }
@@ -142,6 +200,7 @@
     -fx-background-insets: 0, 1, 2;
     -fx-font: bold 22px "Amble";
     -fx-text-fill: white;
+    -fx-padding: 3 0 5 0;
 }
 
 .fxvk .special-key:disabled { 
--- a/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/resources/controls.properties	Thu May 17 15:19:29 2012 -0700
+++ b/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/resources/controls.properties	Mon May 21 14:09:46 2012 -0700
@@ -20,6 +20,7 @@
 TextInputControl.menu.Paste=Paste
 TextInputControl.menu.DeleteSelection=Delete
 TextInputControl.menu.SelectAll=Select All
+TextInputControl.menu.SelectWord=Select
 
 # Virtual Keyboard for embedded FX. This will not be localized for FX 2.2.
 #
@@ -36,7 +37,7 @@
 FXVK.text.row1.key07=u 7 laquo ugrave uacute ucirc uuml
 FXVK.text.row1.key08=i 8 raquo igrave iacute icirc iuml
 FXVK.text.row1.key09=o 9 ` ograve oacute ocirc otilde ouml oslash deg
-FXVK.text.row1.key10=p 0 ~ sect para pi
+FXVK.text.row1.key10=p 0 ~ para pi
 
 FXVK.text.row2.key01=a # agrave aacute acirc atilde auml aring
 FXVK.text.row2.key02=s $ euro pound yen scedil scaron szlig sigma
@@ -116,7 +117,7 @@
 FXVK.url.row1.key07=u 7 laquo ugrave uacute ucirc uuml
 FXVK.url.row1.key08=i 8 raquo igrave iacute icirc iuml
 FXVK.url.row1.key09=o 9 ` ograve oacute ocirc otilde ouml oslash deg
-FXVK.url.row1.key10=p 0 ~ sect para pi
+FXVK.url.row1.key10=p 0 ~ para pi
 
 FXVK.url.row2.key01=a # agrave aacute acirc atilde auml aring
 FXVK.url.row2.key02=s $ euro pound yen scedil scaron szlig sigma
@@ -162,7 +163,7 @@
 FXVK.email.row1.key07=u 7 laquo ugrave uacute ucirc uuml
 FXVK.email.row1.key08=i 8 raquo igrave iacute icirc iuml
 FXVK.email.row1.key09=o 9 ` ograve oacute ocirc otilde ouml oslash deg
-FXVK.email.row1.key10=p 0 ~ sect para pi
+FXVK.email.row1.key10=p 0 ~ para pi
 
 FXVK.email.row2.key01=a # agrave aacute acirc atilde auml aring
 FXVK.email.row2.key02=s $ euro pound yen scedil scaron szlig sigma
--- a/javafx-ui-controls/src/javafx/scene/control/Pagination.java	Thu May 17 15:19:29 2012 -0700
+++ b/javafx-ui-controls/src/javafx/scene/control/Pagination.java	Mon May 21 14:09:46 2012 -0700
@@ -68,9 +68,9 @@
  * <p>
  * The control can be customized to display numeric page indicators or bullet style indicators by
  * setting the style class {@link STYLE_CLASS_BULLET}.  The 
- * {@link #pageIndicatorCountProperty() pageIndicatorCountProperty} can be used to change 
+ * {@link #maxPageIndicatorCountProperty() maxPageIndicatorCountProperty} can be used to change 
  * the number of page indicators.  The property value can also be changed 
- * via CSS using -fx-page-indicator-count
+ * via CSS using -fx-max-page-indicator-count.
  *</p> 
  * 
  * <h3>Page count</h3>
@@ -188,8 +188,8 @@
      * The maximum number of page indicators to use for this pagination control.  This
      * value must be greater than or equal to 1.  The page indicators will 
      * be unselected when the {@link #currentPageIndexProperty currentPageIndex} 
-     * is greater than the pageIndicatorCount.  The number of page indicators will be
-     * reduced if MaxPageIndicatorCount cannot fit within this control. 
+     * is greater than the maxPageIndicatorCount.  The number of page indicators will be
+     * reduced if maxPageIndicatorCount cannot fit within this control. 
      * 
      * The default is 10 page indicators.
      */    
@@ -216,7 +216,7 @@
 
                 @Override
                 public String getName() {
-                    return "pageIndicatorCount";
+                    return "maxPageIndicatorCount";
                 }
             };
         }
@@ -278,7 +278,7 @@
     /**
      * The current page index to display for this pagination control.  This value
      * must be greater than or equal to 0.  The page indicators will be unselected when
-     * the currentPageIndex is greater than the {@link #pageIndicatorCountProperty pageIndicatorCount}.
+     * the currentPageIndex is greater than the {@link #maxPageIndicatorCountProperty maxPageIndicatorCount}.
      * 
      * The default is 0 for the first page.
      */    
--- a/javafx-ui-controls/src/javafx/scene/control/UAStylesheetLoader.java	Thu May 17 15:19:29 2012 -0700
+++ b/javafx-ui-controls/src/javafx/scene/control/UAStylesheetLoader.java	Mon May 21 14:09:46 2012 -0700
@@ -65,6 +65,11 @@
                             url = SkinBase.class.getResource("caspian/embedded.css");
                             StyleManager.getInstance().addUserAgentStylesheet(url.toExternalForm());
                         }
+                        
+                        if (com.sun.javafx.Utils.isQVGAScreen()) {
+                            url = SkinBase.class.getResource("caspian/embedded-qvga.css");
+                            StyleManager.getInstance().addUserAgentStylesheet(url.toExternalForm());
+                        }
                         stylesheetLoaded = true;
                     return null;
                 }
--- a/javafx-ui-controls/src/javafx/scene/control/cell/CheckBoxTableCell.java	Thu May 17 15:19:29 2012 -0700
+++ b/javafx-ui-controls/src/javafx/scene/control/cell/CheckBoxTableCell.java	Mon May 21 14:09:46 2012 -0700
@@ -24,6 +24,7 @@
  */
 package javafx.scene.control.cell;
 
+import com.sun.javafx.css.StyleableProperty;
 import javafx.beans.binding.Bindings;
 import javafx.beans.property.BooleanProperty;
 import javafx.beans.property.ObjectProperty;
@@ -243,10 +244,14 @@
         this.showLabel = converter != null;
         
         this.checkBox = new CheckBox();
-//        this.checkBox.setAlignment(Pos.TOP_CENTER);
+        setGraphic(checkBox);
         
-//        setAlignment(Pos.CENTER);
-        setGraphic(checkBox);
+//        // alignment is styleable through css. Calling setAlignment
+//        // makes it look to css like the user set the value and css will not 
+//        // override. Initializing alignment by calling set on the 
+//        // StyleableProperty ensures that css will be able to override the value.
+//        final StyleableProperty prop = StyleableProperty.getStyleableProperty(alignmentProperty());
+//        prop.set(this, Pos.CENTER);
         
         if (showLabel) {
             this.checkBox.setAlignment(Pos.CENTER_LEFT);
--- a/javafx-ui-controls/src/javafx/scene/control/cell/MapValueFactory.java	Thu May 17 15:19:29 2012 -0700
+++ b/javafx-ui-controls/src/javafx/scene/control/cell/MapValueFactory.java	Mon May 21 14:09:46 2012 -0700
@@ -71,6 +71,14 @@
 
     private final Object key;
     
+    /**
+     * Creates a default MapValueFactory, which will use the provided key to 
+     * lookup the value for cells in the {@link TableColumn} in which this
+     * MapValueFactory is installed (via the 
+     * {@link TableColumn#cellValueFactoryProperty() cell value factory} property.
+     * 
+     * @param key The key to use to lookup the value in the {@code Map}.
+     */
     public MapValueFactory(final Object key) {
         this.key = key;
     }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/javafx-ui-controls/test/com/sun/javafx/scene/control/skin/LabeledImplTestOther.java	Mon May 21 14:09:46 2012 -0700
@@ -0,0 +1,58 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package com.sun.javafx.scene.control.skin;
+
+import com.sun.javafx.css.StyleConverter;
+import com.sun.javafx.css.StyleableProperty;
+import java.net.URL;
+import java.util.ArrayList;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+import javafx.beans.value.WritableValue;
+import javafx.geometry.Insets;
+import javafx.geometry.Pos;
+import javafx.scene.Cursor;
+import javafx.scene.control.ContentDisplay;
+import javafx.scene.control.Label;
+import javafx.scene.control.Labeled;
+import javafx.scene.control.OverrunStyle;
+import javafx.scene.effect.BlendMode;
+import javafx.scene.effect.ColorAdjustBuilder;
+import javafx.scene.image.Image;
+import javafx.scene.image.ImageView;
+import javafx.scene.paint.Color;
+import javafx.scene.text.Font;
+import javafx.scene.text.TextAlignment;
+import javax.swing.GroupLayout;
+
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Test;
+import static org.junit.Assert.*;
+
+public class LabeledImplTestOther {
+    
+    
+    @Test 
+    public void test_RT_21357() {
+        
+        final Labeled labeled = new Label("label");
+        final LabeledImpl labeledImpl = new LabeledImpl(labeled);
+        
+        URL url = SkinBase.class.getResource("caspian/center-btn.png");
+        Image img = new Image(url.toExternalForm());
+        ImageView iView = new ImageView(img);
+        labeled.setGraphic(iView);  
+        
+        assertEquals(labeled.getGraphic(), labeledImpl.getGraphic());
+    }
+
+}
--- a/javafx-ui-controls/test/com/sun/javafx/scene/control/skin/MenuBarMenuButtonRetriever.java	Thu May 17 15:19:29 2012 -0700
+++ b/javafx-ui-controls/test/com/sun/javafx/scene/control/skin/MenuBarMenuButtonRetriever.java	Mon May 21 14:09:46 2012 -0700
@@ -49,4 +49,8 @@
     public static void setCurrentFocusedIndex(ContextMenuContent cmc, int i) {
         cmc.setCurrentFocusedIndex(i);
     }
+    
+    public static int getFocusedIndex(MenuBarSkin skin) {
+        return skin.getFocusedMenuIndex();
+    }
 }
--- a/javafx-ui-controls/test/javafx/scene/control/MenuBarTest.java	Thu May 17 15:19:29 2012 -0700
+++ b/javafx-ui-controls/test/javafx/scene/control/MenuBarTest.java	Mon May 21 14:09:46 2012 -0700
@@ -175,6 +175,62 @@
         assertTrue(!menu.isShowing());
     }
         
+    @Test public void checkMenuBarMenusSelectionResetAfterMenuItemIsSelected() {
+        final MouseEventGenerator generator = new MouseEventGenerator();
+        AnchorPane root = new AnchorPane();
+        Menu menu = new Menu("Menu");
+        MenuItem menuItem = new MenuItem("MenuItem");
+        menu.getItems().add(menuItem);
+
+        menuBar.getMenus().add(menu);
+        menuBar.setLayoutX(100);
+        menuBar.setLayoutY(100);
+
+        root.getChildren().addAll(menuBar);
+        
+        startApp(root);
+        tk.firePulse();
+        
+        MenuBarSkin skin = (MenuBarSkin)menuBar.getSkin();
+        assertTrue(skin != null);
+        MenuButton mb = MenuBarMenuButtonRetriever.getNodeForMenu(skin, 0);
+        mb.getScene().getWindow().requestFocus();
+        
+        double xval = (menuBar.localToScene(menuBar.getLayoutBounds())).getMinX();
+        double yval = (menuBar.localToScene(menuBar.getLayoutBounds())).getMinY();
+   
+        scene.impl_processMouseEvent(
+            generator.generateMouseEvent(MouseEvent.MOUSE_PRESSED, xval+20, yval+20));
+        scene.impl_processMouseEvent(
+            generator.generateMouseEvent(MouseEvent.MOUSE_RELEASED, xval+20, yval+20));
+        assertTrue(menu.isShowing());
+         /* ------------------------------------------------------------------ */
+        
+        // Show Menu
+        ContextMenuContent menuContent = MenuBarMenuButtonRetriever.getMenuContent(mb); // ContextMenuContent
+        Node displayNode = MenuBarMenuButtonRetriever.getDisplayNodeForMenuItem(menuContent, 0); // MenuItemContainer
+        
+        displayNode.getScene().getWindow().requestFocus();
+        assertTrue(displayNode.getScene().getWindow().isFocused());
+        
+        displayNode.requestFocus(); // requestFocus on 1st Menu
+        assertTrue(displayNode.isFocused());
+        
+        // fire KeyEvent (Enter) on menuitem 
+        KeyEventFirer keyboard = new KeyEventFirer(menuContent);
+        keyboard.doKeyPress(KeyCode.ENTER);
+        tk.firePulse();     
+        
+        // confirm menu is closed. 
+        assertTrue(!menu.isShowing());
+        keyboard.doKeyPress(KeyCode.LEFT);
+        tk.firePulse();
+        
+        // check if focusedMenuIndex is reset to -1 so navigation happens.
+        int focusedIndex = MenuBarMenuButtonRetriever.getFocusedIndex(skin);
+        assertEquals(focusedIndex, -1);
+        
+    }
 //    static final class MouseEventTracker {
 //        private Node node;
 //