changeset 1058:df882c23a791

Automated merge with ssh://jfxsrc.us.oracle.com//javafx/2.2/MASTER/rt
author leifs
date Wed, 16 May 2012 17:08:21 -0700
parents aeec67bbcaa2 425d61129c94
children 36b72fb1d022 3ddd1460a76e
files javafx-ui-common/src/com/sun/javafx/css/StyleManager.java javafx-ui-controls/src/com/sun/javafx/scene/control/skin/TextInputControlSkin.java
diffstat 19 files changed, 544 insertions(+), 72 deletions(-) [+]
line wrap: on
line diff
--- a/javafx-ui-common/src/com/sun/javafx/menu/MenuItemBase.java	Wed May 16 13:13:47 2012 -0400
+++ b/javafx-ui-common/src/com/sun/javafx/menu/MenuItemBase.java	Wed May 16 17:08:21 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	Wed May 16 13:13:47 2012 -0400
+++ b/javafx-ui-controls/src/com/sun/javafx/scene/control/GlobalMenuAdapter.java	Wed May 16 17:08:21 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	Wed May 16 13:13:47 2012 -0400
+++ b/javafx-ui-controls/src/com/sun/javafx/scene/control/behavior/ComboBoxBaseBehavior.java	Wed May 16 17:08:21 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	Wed May 16 13:13:47 2012 -0400
+++ b/javafx-ui-controls/src/com/sun/javafx/scene/control/behavior/ListCellBehavior.java	Wed May 16 17:08:21 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/ScrollBarBehavior.java	Wed May 16 13:13:47 2012 -0400
+++ b/javafx-ui-controls/src/com/sun/javafx/scene/control/behavior/ScrollBarBehavior.java	Wed May 16 17:08:21 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	Wed May 16 13:13:47 2012 -0400
+++ b/javafx-ui-controls/src/com/sun/javafx/scene/control/behavior/TextAreaBehavior.java	Wed May 16 17:08:21 2012 -0700
@@ -258,8 +258,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
--- a/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/ComboBoxListViewSkin.java	Wed May 16 13:13:47 2012 -0400
+++ b/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/ComboBoxListViewSkin.java	Wed May 16 17:08:21 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/LabeledImpl.java	Wed May 16 13:13:47 2012 -0400
+++ b/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/LabeledImpl.java	Wed May 16 17:08:21 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/PaginationSkin.java	Wed May 16 13:13:47 2012 -0400
+++ b/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/PaginationSkin.java	Wed May 16 17:08:21 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/TableHeaderRow.java	Wed May 16 13:13:47 2012 -0400
+++ b/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/TableHeaderRow.java	Wed May 16 17:08:21 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	Wed May 16 13:13:47 2012 -0400
+++ b/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/TextAreaSkin.java	Wed May 16 17:08:21 2012 -0700
@@ -56,6 +56,7 @@
 import javafx.scene.control.TextArea;
 import javafx.scene.input.MouseEvent;
 import javafx.scene.layout.Region;
+import javafx.scene.layout.StackPane;
 import javafx.scene.paint.Paint;
 import javafx.scene.shape.MoveTo;
 import javafx.scene.shape.Path;
@@ -65,6 +66,7 @@
 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 +238,62 @@
             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) {
+                    contentView.getChildren().remove(caretHandle);
+                    if (!contentView.getChildren().contains(selectionHandle2)) {
+                        contentView.getChildren().addAll(selectionHandle1, selectionHandle2);
+                        selectionHandle1.resize(selectionHandle1.prefWidth(-1),
+                                                selectionHandle1.prefHeight(-1));
+                        selectionHandle2.resize(selectionHandle2.prefWidth(-1),
+                                                selectionHandle2.prefHeight(-1));
+                    }
+                } else {
+                    contentView.getChildren().remove(selectionHandle1);
+                    contentView.getChildren().remove(selectionHandle2);
+                    if (!contentView.getChildren().contains(caretHandle)) {
+                        contentView.getChildren().add(caretHandle);
+                        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());
+                    }
+                }
+            }
+
             {
-                int caretPos = textArea.getCaretPosition();
-
+                // Position caret
                 int paragraphIndex = paragraphNodes.getChildren().size();
                 int paragraphOffset = textArea.getLength() + 1;
 
@@ -253,6 +305,7 @@
 
                 paragraphNode.setImpl_caretPosition(caretPos - paragraphOffset);
 
+                caretPath.getElements().clear();
                 caretPath.getElements().addAll(paragraphNode.getImpl_caretShape());
 
                 caretPath.setLayoutX(paragraphNode.getLayoutX());
@@ -293,6 +346,23 @@
                 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());
+                    } 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) {
@@ -566,8 +636,105 @@
         updatePrefViewportWidth();
         updatePrefViewportHeight();
         if (textArea.isFocused()) setCaretAnimating(true);
+
+        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) {
+                    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);
+                    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 + selectionHandle1.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();
+                }
+            });
+        }
     }
 
+double pressX, pressY, pressSX, pressSY;
+
     private void createPromptNode() {
         if (promptNode == null && usePromptText.get()) {
             promptNode = new Text();
--- a/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/TextInputControlSkin.java	Wed May 16 13:13:47 2012 -0400
+++ b/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/TextInputControlSkin.java	Wed May 16 17:08:21 2012 -0700
@@ -56,6 +56,7 @@
 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 +231,10 @@
      */
     protected final Path caretPath = new Path();
 
+    protected StackPane caretHandle = null;
+    protected StackPane selectionHandle1 = null;
+    protected StackPane selectionHandle2 = null;
+
     private static boolean useFXVK = PlatformUtil.isEmbedded();
 
     /* For testing only */
@@ -287,6 +292,26 @@
         };
 
         if (PlatformUtil.isEmbedded()) {
+            caretHandle      = new StackPane();
+            selectionHandle1 = new StackPane();
+            selectionHandle1.setRotate(180);
+            selectionHandle2 = new StackPane();
+
+            caretHandle.visibleProperty().bind(new BooleanBinding() {
+                { bind(textInput.focusedProperty(), textInput.anchorProperty(), textInput.caretPositionProperty(),
+                       textInput.disabledProperty(), textInput.editableProperty(), displayCaret);}
+                @Override protected boolean computeValue() {
+                return displayCaret.get() && textInput.isFocused() &&
+                        textInput.getCaretPosition() == textInput.getAnchor() &&
+                        !textInput.isDisabled() && textInput.isEditable();
+                }
+            });
+
+
+            caretHandle.getStyleClass().setAll("caret-handle");
+            selectionHandle1.getStyleClass().setAll("selection-handle");
+            selectionHandle2.getStyleClass().add("selection-handle");
+
             textInput.focusedProperty().addListener(new InvalidationListener() {
                 @Override public void invalidated(Observable observable) {
                     if (useFXVK) {
--- a/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/caspian/caspian.css	Wed May 16 13:13:47 2012 -0400
+++ b/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/caspian/caspian.css	Wed May 16 17:08:21 2012 -0700
@@ -3039,11 +3039,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 +3138,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 +3160,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;
 }
 
--- /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	Wed May 16 17:08:21 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	Wed May 16 13:13:47 2012 -0400
+++ b/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/caspian/embedded.css	Wed May 16 17:08:21 2012 -0700
@@ -67,6 +67,32 @@
 }
 
 
+.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: #0071bc /*-fx-accent*/,
+                          linear-gradient(to bottom, #0063AA 0%, #008AED 100%);
+    -fx-background-insets: 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;
+}
+
 
 /*******************************************************************************
  *                                                                             *
--- a/javafx-ui-controls/src/javafx/scene/control/UAStylesheetLoader.java	Wed May 16 13:13:47 2012 -0400
+++ b/javafx-ui-controls/src/javafx/scene/control/UAStylesheetLoader.java	Wed May 16 17:08:21 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	Wed May 16 13:13:47 2012 -0400
+++ b/javafx-ui-controls/src/javafx/scene/control/cell/CheckBoxTableCell.java	Wed May 16 17:08:21 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	Wed May 16 13:13:47 2012 -0400
+++ b/javafx-ui-controls/src/javafx/scene/control/cell/MapValueFactory.java	Wed May 16 17:08:21 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	Wed May 16 17:08:21 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());
+    }
+
+}