changeset 700:d4b1859ad629 2.2-b02

Automated merge with ssh://jfxsrc.us.oracle.com//javafx/2.2/MASTER/rt
author leifs
date Mon, 26 Mar 2012 10:03:10 -0700
parents 761e72716571 b29849a2da74
children d81130234a1b 8acd74a463e3
files
diffstat 23 files changed, 424 insertions(+), 383 deletions(-) [+]
line wrap: on
line diff
--- a/javafx-ui-charts/src/javafx/scene/chart/PieChart.java	Wed Mar 21 19:05:57 2012 -0700
+++ b/javafx-ui-charts/src/javafx/scene/chart/PieChart.java	Mon Mar 26 10:03:10 2012 -0700
@@ -31,6 +31,7 @@
 import javafx.animation.Interpolator;
 import javafx.animation.KeyFrame;
 import javafx.animation.KeyValue;
+import javafx.beans.DefaultProperty;
 import javafx.beans.property.BooleanProperty;
 import javafx.beans.property.DoubleProperty;
 import javafx.beans.property.DoublePropertyBase;
@@ -80,6 +81,7 @@
  * pie slice labels or not.
  *
  */
+@DefaultProperty("data")
 public class PieChart extends Chart {
 
     // -------------- PRIVATE FIELDS -----------------------------------------------------------------------------------
--- a/javafx-ui-charts/src/javafx/scene/chart/XYChart.java	Wed Mar 21 19:05:57 2012 -0700
+++ b/javafx-ui-charts/src/javafx/scene/chart/XYChart.java	Mon Mar 26 10:03:10 2012 -0700
@@ -33,6 +33,7 @@
 import javafx.animation.Interpolator;
 import javafx.animation.KeyFrame;
 import javafx.animation.KeyValue;
+import javafx.beans.DefaultProperty;
 import javafx.beans.property.BooleanProperty;
 import javafx.beans.property.ObjectProperty;
 import javafx.beans.property.ObjectPropertyBase;
@@ -1406,6 +1407,7 @@
     /**
      * A named series of data items
      */
+    @DefaultProperty("data")
     public static final class Series<X,Y> {
 
         // -------------- PRIVATE PROPERTIES ----------------------------------------
--- a/javafx-ui-common/src/javafx/scene/Parent.java	Wed Mar 21 19:05:57 2012 -0700
+++ b/javafx-ui-common/src/javafx/scene/Parent.java	Mon Mar 26 10:03:10 2012 -0700
@@ -1090,7 +1090,7 @@
      * @deprecated This is an internal API that is not intended for use and will be removed in the next version
      */
     @Deprecated
-    public final List<String> impl_getAllParentStylesheets() {
+    public /* Do not make this final! */ List<String> impl_getAllParentStylesheets() {
         
         List<String> list = null;
         final Parent myParent = getParent();
--- a/javafx-ui-controls/src/com/sun/javafx/scene/control/ColorPicker.java	Wed Mar 21 19:05:57 2012 -0700
+++ b/javafx-ui-controls/src/com/sun/javafx/scene/control/ColorPicker.java	Mon Mar 26 10:03:10 2012 -0700
@@ -11,6 +11,11 @@
  * @author paru
  */
 public class ColorPicker<Color> extends ComboBoxBase<Color> {
+
+    public static final String STYLE_CLASS_BUTTON = "button";
+    public static final String STYLE_CLASS_SPLIT_BUTTON = "split-button";
+    
+    // Need API to turn off Color Label text.
     
     public ColorPicker() {
         getStyleClass().add(DEFAULT_STYLE_CLASS);
--- a/javafx-ui-controls/src/com/sun/javafx/scene/control/ColorPickerPanel.java	Wed Mar 21 19:05:57 2012 -0700
+++ b/javafx-ui-controls/src/com/sun/javafx/scene/control/ColorPickerPanel.java	Mon Mar 26 10:03:10 2012 -0700
@@ -9,10 +9,13 @@
 import javafx.beans.property.SimpleObjectProperty;
 import javafx.collections.FXCollections;
 import javafx.event.EventHandler;
+import javafx.scene.Group;
+import javafx.scene.control.Button;
 import javafx.scene.effect.DropShadow;
 import javafx.scene.input.MouseEvent;
 import javafx.scene.layout.GridPane;
 import javafx.scene.layout.Region;
+import javafx.scene.layout.VBox;
 import javafx.scene.paint.Color;
 import javafx.scene.paint.CycleMethod;
 import javafx.scene.paint.LinearGradient;
--- a/javafx-ui-controls/src/com/sun/javafx/scene/control/Pagination.java	Wed Mar 21 19:05:57 2012 -0700
+++ b/javafx-ui-controls/src/com/sun/javafx/scene/control/Pagination.java	Mon Mar 26 10:03:10 2012 -0700
@@ -52,43 +52,31 @@
 import java.util.Collections;
 import java.util.List;
 import javafx.beans.DefaultProperty;
-import javafx.beans.InvalidationListener;
-import javafx.beans.Observable;
 import javafx.beans.property.IntegerProperty;
 import javafx.beans.property.ObjectProperty;
+import javafx.beans.property.SimpleIntegerProperty;
 import javafx.beans.property.SimpleObjectProperty;
-import javafx.beans.value.ChangeListener;
-import javafx.beans.value.ObservableValue;
-import javafx.beans.value.WeakChangeListener;
 import javafx.beans.value.WritableValue;
-import javafx.collections.FXCollections;
-import javafx.collections.ListChangeListener;
-import javafx.collections.ListChangeListener.Change;
-import javafx.collections.ObservableList;
+import javafx.scene.Node;
 import javafx.scene.control.Control;
-import javafx.scene.control.ListCell;
-import javafx.scene.control.ListView;
-import javafx.scene.control.SingleSelectionModel;
 import javafx.util.Callback;
 
 @DefaultProperty("pages")
 public class Pagination<T> extends Control {
 
     private static final int DEFAULT_NUMBER_OF_VISIBLE_PAGES = 10;
-    
+
     public static final String STYLE_CLASS_BULLET = "bullet";
 
     /**
      * Constructs a new Pagination.
      */
-    public Pagination() {
-        this(FXCollections.<T>observableArrayList());
+    public Pagination(int numberOfItems) {
+        getStyleClass().setAll(DEFAULT_STYLE_CLASS);
+        setNumberOfItems(numberOfItems);
     }
 
-    public Pagination(ObservableList<T> items) {
-        getStyleClass().setAll(DEFAULT_STYLE_CLASS);
-        setSelectionModel(new PaginationSelectionModel(this));
-        setItems(items);
+    private Pagination() {
     }
 
     /***************************************************************************
@@ -97,7 +85,9 @@
      *                                                                         *
      **************************************************************************/
 
-    // The number of visible page indicators
+    /**
+     * The number of visible page indicators
+     */
     public final IntegerProperty numberOfVisiblePagesProperty() {
         if (numberOfVisiblePages == null) {
             numberOfVisiblePages = new StyleableIntegerProperty(DEFAULT_NUMBER_OF_VISIBLE_PAGES) {
@@ -125,149 +115,42 @@
         numberOfVisiblePagesProperty().set(value);
     }
 
-    public final int getNumberOfVisiblePages() {        
+    public final int getNumberOfVisiblePages() {
         return numberOfVisiblePages == null ? DEFAULT_NUMBER_OF_VISIBLE_PAGES : numberOfVisiblePages.get();
     }
 
-    // --- Pages
-    private ObjectProperty<ObservableList<T>> items;
-
-    public final void setItems(ObservableList<T> value) {
-        itemsProperty().set(value);
-    }
-
-    public final ObservableList<T> getItems() {
-        return items == null ? null : items.get();
-    }
-
-    public final ObjectProperty<ObservableList<T>> itemsProperty() {
-        if (items == null) {
-            items = new SimpleObjectProperty<ObservableList<T>>(this, "items") {
-                @Override protected void invalidated() {
-                }
-            };
-        }
-        return items;
-    }
-
-    private ObjectProperty<Callback<ListView<T>, ListCell<T>>> cellFactory =
-            new SimpleObjectProperty<Callback<ListView<T>, ListCell<T>>>(this, "cellFactory");
-    public final void setCellFactory(Callback<ListView<T>, ListCell<T>> value) { cellFactoryProperty().set(value); }
-    public final Callback<ListView<T>, ListCell<T>> getCellFactory() {return cellFactoryProperty().get(); }
-    public ObjectProperty<Callback<ListView<T>, ListCell<T>>> cellFactoryProperty() { return cellFactory; }
-
-    private ObjectProperty<SingleSelectionModel<T>> selectionModel = new SimpleObjectProperty<SingleSelectionModel<T>>(this, "selectionModel");
+    /**
+     * The max number of items per page
+     */
+    public final IntegerProperty itemsPerPage = new SimpleIntegerProperty(this, "itemsPerPage", 10);
+    public final void setItemsPerPage(int value) { itemsPerPage.set(value); }
+    public final int getItemsPerPage() { return itemsPerPage.get(); }
+    public final IntegerProperty itemsPerPageProperty() { return itemsPerPage; }
 
     /**
-     * <p>Sets the model used for page selection.  By changing the model you can alter
-     * how the pages are selected and which pages are first or last.</p>
+     * The total number of items
      */
-    public final void setSelectionModel(SingleSelectionModel<T> value) { selectionModel.set(value); }
+    public final IntegerProperty numberOfItems = new SimpleIntegerProperty(this, "numberOfItems", 1);
+    private final void setNumberOfItems(int value) { numberOfItems.set(value); }
+    public final int getNumberOfItems() { return numberOfItems.get(); }
+    public final IntegerProperty numberOfItemsProperty() { return numberOfItems; }
 
     /**
-     * <p>Gets the model used for page selection.</p>
+     * The current page index
      */
-    public final SingleSelectionModel<T> getSelectionModel() { return selectionModel.get(); }
+    public final IntegerProperty pageIndex = new SimpleIntegerProperty(this, "pageIndex", 0);
+    public final void setPageIndex(int value) { pageIndex.set(value); }
+    public final int getPageIndex() { return pageIndex.get(); }
+    public final IntegerProperty pageIndexProperty() { return pageIndex; }
 
     /**
-     * The selection model used for selecting pages.
+     * The page callback
      */
-    public final ObjectProperty<SingleSelectionModel<T>> selectionModelProperty() { return selectionModel; }
-
-    static class PaginationSelectionModel<T> extends SingleSelectionModel<T> {
-        private final Pagination pagination;
-
-        public PaginationSelectionModel(final Pagination<T> pagination) {
-            if (pagination == null) {
-                throw new NullPointerException("Pagination can not be null");
-            }
-            this.pagination = pagination;
-
-            selectedIndexProperty().addListener(new InvalidationListener() {
-                @Override public void invalidated(Observable valueModel) {
-                    // we used to lazily retrieve the selected item, but now we just
-                    // do it when the selection changes.
-                    setSelectedItem(getModelItem(getSelectedIndex()));
-                }
-            });
-
-            /*
-             * The following two listeners are used in conjunction with
-             * SelectionModel.select(T obj) to allow for a developer to select
-             * an item that is not actually in the data model. When this occurs,
-             * we actively try to find an index that matches this object, going
-             * so far as to actually watch for all changes to the items list,
-             * rechecking each time.
-             */
-
-            this.pagination.itemsProperty().addListener(weakItemsObserver);
-            if (pagination.getItems() != null) {
-                this.pagination.getItems().addListener(weakItemsContentObserver);
-            }
-        }
-
-        // watching for changes to the items list content
-        private final ListChangeListener<T> itemsContentObserver = new ListChangeListener<T>() {
-            @Override public void onChanged(Change<? extends T> c) {
-                if (pagination.getItems() == null || pagination.getItems().isEmpty()) {
-                    setSelectedIndex(-1);
-                } else if (getSelectedIndex() == -1 && getSelectedItem() != null) {
-                    int newIndex = pagination.getItems().indexOf(getSelectedItem());
-                    if (newIndex != -1) {
-                        setSelectedIndex(newIndex);
-                    }
-                }
-
-                while (c.next()) {
-                    if (c.getFrom() <= getSelectedIndex() && getSelectedIndex()!= -1 && (c.wasAdded() || c.wasRemoved())) {
-                        int shift = c.wasAdded() ? c.getAddedSize() : -c.getRemovedSize();
-                        clearAndSelect(getSelectedIndex() + shift);
-                    }
-                }
-            }
-        };
-
-        // watching for changes to the items list
-        private final ChangeListener<ObservableList<T>> itemsObserver = new ChangeListener<ObservableList<T>>() {
-            @Override
-            public void changed(ObservableValue<? extends ObservableList<T>> valueModel,
-                ObservableList<T> oldList, ObservableList<T> newList) {
-                    updateItemsObserver(oldList, newList);
-            }
-        };
-
-        private WeakListChangeListener weakItemsContentObserver =
-                new WeakListChangeListener(itemsContentObserver);
-
-        private WeakChangeListener weakItemsObserver =
-                new WeakChangeListener(itemsObserver);
-
-        private void updateItemsObserver(ObservableList<T> oldList, ObservableList<T> newList) {
-            // update listeners
-            if (oldList != null) {
-                oldList.removeListener(weakItemsContentObserver);
-            }
-            if (newList != null) {
-                newList.addListener(weakItemsContentObserver);
-            }
-
-            // when the items list totally changes, we should clear out
-            // the selection and focus
-            setSelectedIndex(-1);
-        }
-
-        @Override protected T getModelItem(int index) {
-            final ObservableList<T> items = pagination.getItems();
-            if (items == null) return null;
-            if (index < 0 || index >= items.size()) return null;
-            return items.get(index);
-        }
-
-        @Override protected int getItemCount() {
-            final ObservableList<T> items = pagination.getItems();
-            return items == null ? 0 : items.size();
-        }
-    }
+    private ObjectProperty<Callback<Integer, Node>> pageFactory =
+            new SimpleObjectProperty<Callback<Integer, Node>>(this, "pageFactory");
+    public final void setPageFactory(Callback<Integer, Node> value) { pageFactoryProperty().set(value); }
+    public final Callback<Integer, Node> getPageFactory() {return pageFactoryProperty().get(); }
+    public ObjectProperty<Callback<Integer, Node>> pageFactoryProperty() { return pageFactory; }
 
     /***************************************************************************
      *                                                                         *
--- a/javafx-ui-controls/src/com/sun/javafx/scene/control/behavior/ColorPickerBehavior.java	Wed Mar 21 19:05:57 2012 -0700
+++ b/javafx-ui-controls/src/com/sun/javafx/scene/control/behavior/ColorPickerBehavior.java	Mon Mar 26 10:03:10 2012 -0700
@@ -35,6 +35,7 @@
 import com.sun.javafx.scene.control.ColorPicker;
 
 import javafx.scene.control.SelectionModel;
+import javafx.scene.input.MouseEvent;
 
 public class ColorPickerBehavior<T> extends ComboBoxBaseBehavior<T> {
 
@@ -59,8 +60,6 @@
 
     protected static final List<KeyBinding> COMBO_BOX_BINDINGS = new ArrayList<KeyBinding>();
     static {
-        COMBO_BOX_BINDINGS.add(new KeyBinding(UP, KEY_PRESSED, "selectPrevious"));
-        COMBO_BOX_BINDINGS.add(new KeyBinding(DOWN, "selectNext"));
         COMBO_BOX_BINDINGS.addAll(COMBO_BOX_BASE_BINDINGS);
     }
 
@@ -69,28 +68,46 @@
     }
 
     @Override protected void callAction(String name) {
-        if ("selectPrevious".equals(name)) {
-            selectPrevious();
-        } else if ("selectNext".equals(name)) {
-            selectNext();
+        super.callAction(name);
+    }
+    
+    private ColorPicker<T> getColorPicker() {
+        return (ColorPicker<T>) getControl();
+    }
+    
+     /**************************************************************************
+     *                                                                        *
+     * Mouse Events                                                           *
+     *                                                                        *
+     *************************************************************************/
+     /**
+     * When a mouse button is pressed, we either want to behave like a button or
+     * show the popup.  This will be called by the skin.
+     *
+     * @param e the mouse press event
+     * @param behaveLikeButton if true, this should act just like a button
+     */
+//    public void mousePressed(MouseEvent e) {
+//        super.mousePressed(e);
+//    }
+    
+    @Override public void mouseReleased(MouseEvent e) {
+        // Overriding to not do the usual on mouseReleased.
+        // The event is handled by the skin instead, which calls
+        // the method below.
+    }
+//    
+    /**
+     * Handles mouse release events.  This will be called by the skin.
+     *
+     * @param e the mouse press event
+     * @param behaveLikeButton if true, this should act just like a button
+     */
+    public void mouseReleased(MouseEvent e, boolean behaveLikeSplitButton) {
+        if (behaveLikeSplitButton) {
+            super.mouseReleased(e);
         } else {
-            super.callAction(name);
+            disarm();
         }
     }
-    
-    private ComboBox<T> getComboBox() {
-        return (ComboBox<T>) getControl();
-    }
-
-    private void selectPrevious() {
-        SelectionModel sm = getComboBox().getSelectionModel();
-        if (sm == null) return;
-        sm.selectPrevious();
-    }
-    
-    private void selectNext() {
-        SelectionModel sm = getComboBox().getSelectionModel();
-        if (sm == null) return;
-        sm.selectNext();
-    }
 }
--- a/javafx-ui-controls/src/com/sun/javafx/scene/control/behavior/ComboBoxBaseBehavior.java	Wed Mar 21 19:05:57 2012 -0700
+++ b/javafx-ui-controls/src/com/sun/javafx/scene/control/behavior/ComboBoxBaseBehavior.java	Mon Mar 26 10:03:10 2012 -0700
@@ -227,7 +227,7 @@
         }
     }
     
-    private boolean wasComboBoxButtonClickedForAutoHide = false;
+    boolean wasComboBoxButtonClickedForAutoHide = false;
     private boolean mouseInsideButton = false;
     public void onAutoHide() {
         // if the ComboBox button was clicked, and it was this that forced the
--- a/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/ChoiceBoxSkin.java	Wed Mar 21 19:05:57 2012 -0700
+++ b/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/ChoiceBoxSkin.java	Mon Mar 26 10:03:10 2012 -0700
@@ -304,7 +304,7 @@
             label.setText("");
         } else {
             int selectedIndex = selectionModel.getSelectedIndex();
-            if (selectedIndex == -1) {
+            if (selectedIndex == -1 || selectedIndex > popup.getItems().size()) {
                 label.setText(""); // clear label text
                 return;
             }
@@ -314,12 +314,9 @@
                     ((RadioMenuItem) selectedItem).setSelected(true);
                     toggleGroup.selectToggle(null);
                 }
+                // update the label
+                label.setText(popup.getItems().get(selectedIndex).getText());
             }
-
-            // update the label
-            Object selected = choiceBoxItems.get(selectedIndex);
-            String text = selected == null ? "" : selected.toString();
-            label.setText(text);
         }
     }
 
--- a/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/ColorPickerSkin.java	Wed Mar 21 19:05:57 2012 -0700
+++ b/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/ColorPickerSkin.java	Mon Mar 26 10:03:10 2012 -0700
@@ -4,29 +4,30 @@
  */
 package com.sun.javafx.scene.control.skin;
 
-import com.sun.javafx.scene.control.behavior.ColorPickerBehavior;
-import javafx.geometry.Insets;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Locale;
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
 import javafx.scene.Node;
-import com.sun.javafx.scene.control.ColorPicker;
-import com.sun.javafx.scene.control.ColorPickerPanel;
-import java.util.List;
 import javafx.beans.binding.ObjectBinding;
+import javafx.beans.binding.StringBinding;
 import javafx.beans.property.ObjectProperty;
 import javafx.beans.property.SimpleObjectProperty;
 import javafx.beans.value.ChangeListener;
 import javafx.beans.value.ObservableValue;
 import javafx.event.EventHandler;
-import javafx.event.EventTarget;
-import javafx.geometry.HPos;
-import javafx.geometry.Point2D;
-import javafx.geometry.VPos;
-import javafx.scene.Parent;
+import javafx.scene.control.*;
 import javafx.scene.input.MouseEvent;
 import javafx.scene.layout.StackPane;
 import javafx.scene.shape.Rectangle;
 import javafx.scene.paint.Color;
 import javafx.scene.paint.Paint;
 import javafx.scene.shape.RectangleBuilder;
+import com.sun.javafx.scene.control.behavior.ColorPickerBehavior;
+import com.sun.javafx.scene.control.ColorPicker;
+import com.sun.javafx.scene.control.ColorPickerPanel;
 
 /**
  *
@@ -34,11 +35,14 @@
  */
 public class ColorPickerSkin<T> extends ComboBoxPopupControl<T> {
 
-    private StackPane displayNode = new StackPane();
+    private Label displayNode; 
+    private StackPane icon; 
     private Rectangle colorRect; 
     private ColorPickerPanel popup = new ColorPickerPanel(Color.WHITE);
     
-    private ObjectProperty<Color> color = new SimpleObjectProperty<Color>(Color.RED);
+    private boolean behaveLikeSplitButton = false;
+    
+    private ObjectProperty<Color> color = new SimpleObjectProperty<Color>(Color.WHITE);
     public ObjectProperty<Color> colorProperty() { return color; }
     public Color getColor() { return color.get(); }
     public void setColor(Color newColor) { color.set(newColor); }
@@ -46,72 +50,122 @@
     public ColorPickerSkin(final ColorPicker<T> colorPicker) {
         super(colorPicker, new ColorPickerBehavior<T>(colorPicker));
         initialize();
+        if (arrowButton.getOnMouseReleased() == null) {
+            colorPicker.setOnMouseReleased(new EventHandler<MouseEvent>() {
+                @Override public void handle(MouseEvent e) {
+                    ((ColorPickerBehavior)getBehavior()).mouseReleased(e, behaveLikeSplitButton);
+                    e.consume();
+                }
+            });
+        }
     }
     
     private void initialize() {
-        displayNode.getStyleClass().add("picker-color");
-        colorRect = RectangleBuilder.create()
-                .width(16).height(16)
-                .build();
+        updateComboBoxMode();
+        popup.addEventFilter(MouseEvent.MOUSE_RELEASED, new EventHandler<MouseEvent>() {
+            @Override public void handle(MouseEvent t) {
+                ((ColorPicker)getSkinnable()).hide();
+            }
+        });
         popup.colorProperty().addListener(new ChangeListener<Color>() {
             @Override public void changed(ObservableValue<? extends Color> ov, Color t, Color t1) {
-                 setColor(t1);
-            }
-        });
-        colorRect.fillProperty().bind(new ObjectBinding<Paint>() {
-            { bind(color); }
-            @Override protected Paint computeValue() {
-                return getColor();
-            }
-        });          
-        displayNode.getChildren().add(colorRect);
-        getChildren().setAll(displayNode, arrowButton);
-        
-        popup.addEventFilter(MouseEvent.MOUSE_RELEASED, new EventHandler<MouseEvent>() {
-            @Override public void handle(MouseEvent t) {
-                getSkinnable().hide();
+                setColor(t1);
             }
         });
     }
+     
+    private void updateComboBoxMode() {
+        if (getSkinnable().getStyleClass().contains(ColorPicker.STYLE_CLASS_BUTTON)) {
+            setMode(ComboBoxMode.BUTTON);
+            behaveLikeSplitButton = false;
+        }
+        else if (getSkinnable().getStyleClass().contains(ColorPicker.STYLE_CLASS_SPLIT_BUTTON)) {
+            setMode(ComboBoxMode.SPLITBUTTON);
+            behaveLikeSplitButton = true;
+        }
+    }
     
-    @Override
-    protected Node getPopupContent() {
+      private static final List<String> colorNames = new ArrayList<String>();
+    static {
+        // Initializes the namedColors map
+        Color.web("white", 1.0);
+        for (Field f : Color.class.getDeclaredFields()) {
+            int modifier = f.getModifiers();
+            if (Modifier.isStatic(modifier) && Modifier.isPublic(modifier) && f.getType().equals(Color.class)) {
+                colorNames.add(f.getName());
+            }
+        }
+        Collections.sort(colorNames);
+    }
+    
+    private static String colorValueToWeb(Color c) {
+        String web = null;
+        if (colorNames != null) {
+            // Find a name for the color. Note that there can
+            // be more than one name for a color, e.g. #ff0ff
+            // is named both "fuchsia" and "magenta".
+            // We return the first name encountered (alphabetically).
+
+            // TODO: Use a hash map for performance
+            for (String name : colorNames) {
+                if (Color.web(name).equals(c)) {
+                    web = name;
+                    break;
+                }
+            }
+        }
+        if (web == null) {
+            web = String.format((Locale) null, "%02x%02x%02x", Math.round(c.getRed() * 255), Math.round(c.getGreen() * 255), Math.round(c.getBlue() * 255));
+        }
+        return web;
+    }
+    
+    @Override protected Node getPopupContent() {
        return popup;
     }
     
-    @Override
-    public Node getDisplayNode() {
+    @Override public Node getDisplayNode() {
+        if (displayNode == null) {
+            displayNode = new Label();
+            displayNode.getStyleClass().add("color-picker-label");
+            // label text
+            displayNode.textProperty().bind(new StringBinding() {
+                { bind(color); }
+                @Override protected String computeValue() {
+                    return colorValueToWeb(getColor());
+                }
+            });
+            // label graphic
+            icon = new StackPane();
+            icon.getStyleClass().add("picker-color");
+            colorRect = RectangleBuilder.create()
+                    .width(16).height(16)
+                    .build();
+            colorRect.fillProperty().bind(new ObjectBinding<Paint>() {
+                { bind(color); }
+                @Override protected Paint computeValue() {
+                    return getColor();
+                }
+            });         
+            
+            icon.getChildren().add(colorRect);
+            displayNode.setGraphic(icon);
+            if (displayNode.getOnMouseReleased() == null) {
+                displayNode.setOnMouseReleased(new EventHandler<MouseEvent>() {
+                    @Override
+                    public void handle(MouseEvent e) {
+                        ((ColorPickerBehavior)getBehavior()).mouseReleased(e, false);
+                        e.consume();
+                    }
+                });
+            }
+        }
         return displayNode;
     }
     
     @Override protected void layoutChildren() {
-        final Insets padding = getInsets();
-        final Insets arrowButtonPadding = arrowButton.getInsets();
-        
-        final double arrowWidth = snapSize(arrow.prefWidth(-1));
-        final double arrowButtonWidth = snapSpace(arrowButtonPadding.getLeft()) + 
-                                        arrowWidth + 
-                                        snapSpace(arrowButtonPadding.getRight());
-        
-        // x, y, w, h are the content area that will hold the label and arrow */
-        final double x = padding.getLeft();
-        final double y = padding.getTop();
-        final double w = getSkinnable().getWidth() - (padding.getLeft() + padding.getRight()+arrowButtonWidth);
-        final double h = getSkinnable().getHeight() - (padding.getTop() + padding.getBottom());
-        
-        if (displayNode != null) {
-            displayNode.resizeRelocate(x, y, w, h);
-        }
-        
-        arrowButton.resize(arrowButtonWidth, getHeight());
-        positionInArea(arrowButton, getWidth() - padding.getRight() - arrowButtonWidth, 0, 
-                arrowButtonWidth, getHeight(), 0, HPos.CENTER, VPos.CENTER);
-    }
-    @Override protected double computePrefWidth(double height) {
-        final double boxWidth = displayNode.prefWidth(-1)
-                + arrowButton.prefWidth(-1);
-        return getInsets().getLeft() + boxWidth +
-                + getInsets().getRight();
+        updateComboBoxMode();
+        super.layoutChildren();
     }
     
 }
--- a/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/ComboBoxBaseSkin.java	Wed Mar 21 19:05:57 2012 -0700
+++ b/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/ComboBoxBaseSkin.java	Mon Mar 26 10:03:10 2012 -0700
@@ -42,6 +42,11 @@
     protected StackPane arrowButton;
     protected StackPane arrow;
     
+    /** The mode in which this control will be represented. */
+    private ComboBoxMode mode = ComboBoxMode.COMBOBOX;
+    protected final ComboBoxMode getMode() { return mode; }
+    protected final void setMode(ComboBoxMode value) { mode = value; }
+    
     public ComboBoxBaseSkin(final ComboBoxBase<T> comboBox, final ComboBoxBaseBehavior behavior) {
         // Call the super method with the button we were just given in the 
         // constructor, as well as an instance of the behavior class.
@@ -110,7 +115,7 @@
             updateDisplayArea();
         } else if (p == "VALUE") {
             updateDisplayArea();
-        }
+        } 
     }
     
     private void updateDisplayArea() {
@@ -122,6 +127,10 @@
         getChildren().add(0, displayNode);
     }
     
+    private boolean isButton() {
+        return getMode() == ComboBoxMode.BUTTON;
+    }
+    
     @Override protected void layoutChildren() {
         if (displayNode == null) {
             updateDisplayArea();
@@ -137,21 +146,33 @@
         final double h = getSkinnable().getHeight() - (padding.getTop() + padding.getBottom());
 
         final double arrowWidth = snapSize(arrow.prefWidth(-1));
-        final double arrowButtonWidth = snapSpace(arrowButtonPadding.getLeft()) + 
-                                        arrowWidth + 
-                                        snapSpace(arrowButtonPadding.getRight());
+        final double arrowButtonWidth = (isButton()) ? 0 :
+                (snapSpace(arrowButtonPadding.getLeft()) + arrowWidth + 
+                snapSpace(arrowButtonPadding.getRight()));
         
         if (displayNode != null) {
-            displayNode.resizeRelocate(x, y, w, h);
+            displayNode.resizeRelocate(x, y, w-arrowButtonWidth, h);
         }
         
+        if (isButton()) return;
+        
         arrowButton.resize(arrowButtonWidth, getHeight());
         positionInArea(arrowButton, getWidth() - padding.getRight() - arrowButtonWidth, 0, 
                 arrowButtonWidth, getHeight(), 0, HPos.CENTER, VPos.CENTER);
     }
     
     @Override protected double computePrefWidth(double height) {
-        return displayNode == null ? 100 : displayNode.prefWidth(height);
+        final Insets arrowButtonPadding = arrowButton.getInsets();
+        final double arrowWidth = snapSize(arrow.prefWidth(-1));
+        final double arrowButtonWidth = (isButton()) ? 0 : 
+                                        (snapSpace(arrowButtonPadding.getLeft()) + 
+                                        arrowWidth + 
+                                        snapSpace(arrowButtonPadding.getRight()));
+        
+        final double totalWidth = (displayNode == null) ? 0 : (displayNode.prefWidth(height) 
+                + arrowButtonWidth);
+        return getInsets().getLeft() + totalWidth +
+                + getInsets().getRight();
     }
     
     @Override protected double computePrefHeight(double width) {
@@ -159,15 +180,19 @@
             updateDisplayArea();
         }
 
+        double ph;
         if (displayNode == null) {
             final int DEFAULT_HEIGHT = 21;
-            final Insets padding = getInsets();
             final Insets arrowButtonPadding = arrowButton.getInsets();
-            double arrowHeight = arrowButtonPadding.getTop() + arrow.prefHeight(-1) + arrowButtonPadding.getBottom();
-            return padding.getTop() + Math.max(DEFAULT_HEIGHT, arrowHeight) + padding.getBottom();
+            double arrowHeight = (isButton()) ? 0 : 
+                    (arrowButtonPadding.getTop() + arrow.prefHeight(-1) + arrowButtonPadding.getBottom());
+            ph = Math.max(DEFAULT_HEIGHT, arrowHeight);
         } else {
-            return displayNode.prefHeight(width);
+            ph = displayNode.prefHeight(width);
         }
+
+        final Insets padding = getInsets();
+        return padding.getTop()+ ph + padding.getBottom();
     }
 
     @Override protected double computeMaxWidth(double height) {
--- a/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/ComboBoxListViewSkin.java	Wed Mar 21 19:05:57 2012 -0700
+++ b/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/ComboBoxListViewSkin.java	Mon Mar 26 10:03:10 2012 -0700
@@ -217,7 +217,7 @@
                 comboBox.requestFocus();
             }
         });
-        
+
         return textField;
     }
     
@@ -228,7 +228,6 @@
         if (comboBox.isEditable()) {
             T value = comboBox.getValue();
             String stringValue = c.toString(value);
-            
             if (value == null || stringValue == null) {
                 textField.setText("");
             } else if (! stringValue.equals(textField.getText())) {
@@ -353,7 +352,6 @@
 
         listView.setId("list-view");
         listView.getSelectionModel().setSelectionMode(SelectionMode.SINGLE);
-        listView.prefWidthProperty().bind(comboBox.widthProperty());
 
         listView.getSelectionModel().selectedIndexProperty().addListener(new InvalidationListener() {
              @Override public void invalidated(Observable o) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/ComboBoxMode.java	Mon Mar 26 10:03:10 2012 -0700
@@ -0,0 +1,28 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package com.sun.javafx.scene.control.skin;
+
+/**
+ *
+ * @author paru
+ */
+public enum ComboBoxMode {
+    
+     /**
+     * The default look with display and arrow button.
+     */
+    COMBOBOX,
+
+    /**
+     * Split Menu Button look with display and arrow button separated by a line.
+     */
+    SPLITBUTTON,
+    
+    /**
+     * Simple Button look with display area only.
+     */       
+    BUTTON 
+}
+
--- a/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/ListViewSkin.java	Wed Mar 21 19:05:57 2012 -0700
+++ b/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/ListViewSkin.java	Mon Mar 26 10:03:10 2012 -0700
@@ -54,7 +54,6 @@
         updateListViewItems();
 
         // init the VirtualFlow
-        flow = new VirtualFlow();
         flow.setId("virtual-flow");
         flow.setPannable(false);
         flow.setVertical(getSkinnable().getOrientation() == Orientation.VERTICAL);
--- a/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/PaginationSkin.java	Wed Mar 21 19:05:57 2012 -0700
+++ b/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/PaginationSkin.java	Mon Mar 26 10:03:10 2012 -0700
@@ -75,15 +75,8 @@
 public class PaginationSkin<T> extends SkinBase<Pagination<T>, PaginationBehavior<T>>  {
 
     private Pagination<T> pagination;
-    private PaginationListView<T> paginationListView;
-    private ObservableList<T> pages;
-    private final ListChangeListener pageListener = new ListChangeListener() {
-        @Override public void onChanged(ListChangeListener.Change c) {
-            requestLayout();
-        }
-    };
-    private final WeakListChangeListener weakPageListener =
-            new WeakListChangeListener(pageListener);
+    private PaginationListView<T> paginationListView;    
+    private ObservableList dummyListViewItems;
 
     private Rectangle clipRect;
 
@@ -102,18 +95,15 @@
         setManaged(false);
         clipRect = new Rectangle();
         setClip(clipRect);
-
+        
         this.pagination = pagination;
-        pagination.getSelectionModel().selectFirst();
-
-        this.paginationListView = createListView();
+        this.paginationListView = new PaginationListView<T>();                
         updateListViewItems();
         updateCellFactory();
-        paginationListView.setOrientation(Orientation.HORIZONTAL);
-
         resetIndexes();
-        navigation = new NavigationControl();
-
+                
+        this.navigation = new NavigationControl();        
+        
         getChildren().addAll(paginationListView, navigation);
 
         pagination.numberOfVisiblePagesProperty().addListener(new InvalidationListener() {
@@ -125,76 +115,94 @@
                 getChildren().add(navigation);
             }
         });
+        
+        registerChangeListener(pagination.itemsPerPageProperty(), "ITEMS_PER_PAGE");
+        registerChangeListener(pagination.numberOfItemsProperty(), "NUMBER_OF_ITEMS");
+        registerChangeListener(pagination.pageIndexProperty(), "PAGE_INDEX");
+        registerChangeListener(pagination.pageFactoryProperty(), "PAGE_FACTORY");
     }
 
     private void resetIndexes() {
         numberOfVisiblePages = getSkinnable().getNumberOfVisiblePages();
-        totalNumberOfPages = pages.size();
+        totalNumberOfPages = totalNumberOfPages();
         numberOfPages = totalNumberOfPages;
         if (totalNumberOfPages > numberOfVisiblePages) {
             numberOfPages = numberOfVisiblePages;
         }
 
-        fromIndex = 0;
+        fromIndex = 0;        
         previousIndex = 0;
-        currentIndex = 0;
+        currentIndex = getSkinnable().getPageIndex();
         toIndex = numberOfPages - 1;
+        paginationListView.getSelectionModel().select(currentIndex);
     }
 
-    private PaginationListView<T> createListView() {
-        return new PaginationListView<T>();
+    private void updateListViewItems() {        
+        if (dummyListViewItems == null) {
+            dummyListViewItems = FXCollections.observableArrayList();
+        } else {
+            dummyListViewItems.removeListener(weakListViewItemsListener);
+        }
+
+        for (int i = 0; i < totalNumberOfPages(); i++) {
+            dummyListViewItems.add(i);
+        }
+        paginationListView.setItems(null);
+        paginationListView.setItems(dummyListViewItems);
+
+        if (dummyListViewItems != null) {
+            dummyListViewItems.addListener(weakListViewItemsListener);
+        }
+        requestLayout();
     }
 
-    private void updateCellFactory() {
-        Callback<ListView<T>, ListCell<T>> cf = pagination.getCellFactory();
-        paginationListView.setCellFactory(cf != null ? cf : getDefaultCellFactory());
+    private final ListChangeListener listViewItemsListener = new ListChangeListener() {
+        @Override public void onChanged(ListChangeListener.Change c) {
+            requestLayout();
+        }
+    };
+
+    private final WeakListChangeListener weakListViewItemsListener =
+            new WeakListChangeListener(listViewItemsListener);
+
+    private void updateCellFactory() {        
+        Callback<ListView<T>, ListCell<T>> cell = createCellFactory();        
+        paginationListView.setCellFactory(cell);
     }
 
-    private Callback<ListView<T>, ListCell<T>> getDefaultCellFactory() {
-        return new Callback<ListView<T>, ListCell<T>>() {
+    private Callback<ListView<T>, ListCell<T>> createCellFactory() {
+        Callback<ListView<T>, ListCell<T>> cell = new Callback<ListView<T>, ListCell<T>>() {
             @Override public ListCell<T> call(ListView<T> listView) {
                 return new PaginationCell<T>() {
                     @Override public void updateItem(T item, boolean empty) {
                         super.updateItem(item, empty);
 
-                        if (empty) {
+                        if (empty || item == null) {
                             setText(null);
                             setGraphic(null);
-                        } else if (item instanceof Node) {
+                        } else {
                             setText(null);
-                            Node currentNode = getGraphic();
-                            Node newNode = (Node) item;
-                            if (currentNode == null || ! currentNode.equals(newNode)) {
-                                setGraphic(newNode);
-                            }
-                        } else {
-                            /**
-                            * This label is used if the item associated with this cell is to be
-                            * represented as a String. While we will lazily instantiate it
-                            * we never clear it, being more afraid of object churn than a minor
-                            * "leak" (which will not become a "major" leak).
-                            */
-                            setText(item == null ? "null" : item.toString());
-                            setGraphic(null);
+                            setGraphic(pagination.getPageFactory().call(getIndex()));
                         }
                     }
                 };
             }
         };
+        return cell;
     }
 
-    private void updateListViewItems() {
-        if (pages != null) {
-            pages.removeListener(weakPageListener);
+    private int totalNumberOfPages() {
+        return getSkinnable().getNumberOfItems()/getSkinnable().getItemsPerPage();
+    }
+                    
+    @Override protected void handleControlPropertyChanged(String p) {
+        super.handleControlPropertyChanged(p);
+        // TODO need to implement
+        if (p == "ITEMS_PER_PAGE") {            
+        } else if (p == "NUMBER_OF_ITEMS") {            
+        } else if (p == "PAGE_INDEX") {
+        } else if (p == "PAGE_FACTORY") {
         }
-
-        this.pages = getSkinnable().getItems();
-        paginationListView.setItems(pages);
-
-        if (pages != null) {
-            pages.addListener(weakPageListener);
-        }
-        requestLayout();
     }
 
     @Override protected void setWidth(double value) {
@@ -273,30 +281,30 @@
             leftArrowButton.setOnMousePressed(new EventHandler<MouseEvent>() {
                 @Override
                 public void handle(MouseEvent arg0) {
-                    pagination.getSelectionModel().selectPrevious();
-                    //System.out.println("LEFT BUTTON " + pagination.getSelectionModel().getSelectedIndex());
-                    paginationListView.show(pagination.getSelectionModel().getSelectedIndex());
+                    paginationListView.getSelectionModel().selectPrevious();
+                    //System.out.println("LEFT BUTTON " + paginationListView.getSelectionModel().getSelectedIndex());
+                    paginationListView.show(paginationListView.getSelectionModel().getSelectedIndex());
                     requestLayout();
                 }
             });
 
             rightArrowButton.setOnMousePressed(new EventHandler<MouseEvent>() {
                 @Override
-                public void handle(MouseEvent arg0) {
-                    pagination.getSelectionModel().selectNext();
-                    //System.out.println("RIGHT BUTTON " + pagination.getSelectionModel().getSelectedIndex() + " TNP " + (totalNumberOfPages - 1));
-                    paginationListView.show(pagination.getSelectionModel().getSelectedIndex());
+                public void handle(MouseEvent arg0) {                   
+                    paginationListView.getSelectionModel().selectNext();
+                    //System.out.println("RIGHT BUTTON " + paginationListView.getSelectionModel().getSelectedIndex() + " TNP " + (totalNumberOfPages - 1));
+                    paginationListView.show(paginationListView.getSelectionModel().getSelectedIndex());
                     requestLayout();
                 }
             });
 
-            getSkinnable().getSelectionModel().selectedIndexProperty().addListener(new ChangeListener<Number>() {
+            paginationListView.getSelectionModel().selectedIndexProperty().addListener(new ChangeListener<Number>() {
                 @Override
                 public void changed(ObservableValue<? extends Number> arg0, Number arg1, Number arg2) {
                     previousIndex = arg1.intValue();
                     currentIndex = arg2.intValue();
 
-                    //System.out.println("\nSELECT PROPERTY FROM " + fromIndex + " TO " + toIndex + " PREVIOUS " + previousIndex + " CURRENT "+ currentIndex + " SIZE " + pages.size());
+                    //System.out.println("\nSELECT PROPERTY FROM " + fromIndex + " TO " + toIndex + " PREVIOUS " + previousIndex + " CURRENT "+ currentIndex);
                     if (currentIndex == 0) {
                         // Grey out the left arrow we are at the beginning.
                         leftArrowButton.setVisible(false);
@@ -310,6 +318,9 @@
                             scroll();
                         }
                     }
+                    // Update the current page index
+                    pagination.setPageIndex(currentIndex);
+                    
                     // Update the indictor buttons
                     for (int i = 0; i < indicatorButton.size(); i++) {
                         if (indicatorButton.get(i).getPageNumber() == previousIndex) {
@@ -463,11 +474,11 @@
             setOnMousePressed(new EventHandler<MouseEvent>() {
                 @Override
                 public void handle(MouseEvent arg0) {
-                    int selected = pagination.getSelectionModel().getSelectedIndex();
+                    int selected = paginationListView.getSelectionModel().getSelectedIndex();
                     // We do not need to update the selection if it has not changed.
                     if (selected != IndicatorButton.this.pageNumber) {
-                        pagination.getSelectionModel().select(IndicatorButton.this.pageNumber);
-                        paginationListView.show(pagination.getSelectionModel().getSelectedIndex());
+                        paginationListView.getSelectionModel().select(IndicatorButton.this.pageNumber);
+                        paginationListView.show(paginationListView.getSelectionModel().getSelectedIndex());
                         requestLayout();
                     }
                 }
@@ -522,16 +533,14 @@
 
     class PaginationListView<T> extends ListView<T> {
         public PaginationListView() {
-            this(FXCollections.<T>observableArrayList());
-        }
-
-        public PaginationListView(ObservableList<T> items) {
-            super(items);
+            super();
             setId("list-view");
+            setOrientation(Orientation.HORIZONTAL);
+            getSelectionModel().setSelectionMode(SelectionMode.SINGLE);            
         }
 
         public void show(int index) {
-            getProperties().put(VirtualContainerBase.SHOW_INDEX, index);
+            getProperties().put(VirtualContainerBase.SCROLL_TO_INDEX_TOP, index);
         }
     }
 }
--- a/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/TableViewSkin.java	Wed Mar 21 19:05:57 2012 -0700
+++ b/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/TableViewSkin.java	Mon Mar 26 10:03:10 2012 -0700
@@ -60,7 +60,6 @@
         super(tableView, new TableViewBehavior(tableView));
 
         // init the VirtualFlow
-        flow = new VirtualFlow();
         flow.setPannable(false);
         flow.setFocusTraversable(getSkinnable().isFocusTraversable());
         flow.setCreateCell(new Callback<VirtualFlow, TableRow>() {
--- a/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/TreeViewSkin.java	Wed Mar 21 19:05:57 2012 -0700
+++ b/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/TreeViewSkin.java	Mon Mar 26 10:03:10 2012 -0700
@@ -49,7 +49,6 @@
         super(treeView, new TreeViewBehavior(treeView));
 
         // init the VirtualFlow
-        flow = new VirtualFlow();
         flow.setPannable(false);
         flow.setFocusTraversable(getSkinnable().isFocusTraversable());
         flow.setCreateCell(new Callback<VirtualFlow, TreeCell>() {
--- a/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/VirtualContainerBase.java	Wed Mar 21 19:05:57 2012 -0700
+++ b/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/VirtualContainerBase.java	Mon Mar 26 10:03:10 2012 -0700
@@ -41,29 +41,33 @@
  */
 public abstract class VirtualContainerBase<C extends Control, B extends BehaviorBase<C>, I extends IndexedCell> extends SkinBase<C, B> {
 
-    public static final String SCROLL_TO_INDEX = "VirtualContainerBase.scrollToIndex";
-    public static final String SHOW_INDEX = "VirtualContainerBase.showIndex";
+    public static final String SCROLL_TO_INDEX_CENTERED = "VirtualContainerBase.scrollToIndexCentered";
+    public static final String SCROLL_TO_INDEX_TOP = "VirtualContainerBase.scrollToIndexTop";
 
     public VirtualContainerBase(C control, B behavior) {
         super(control, behavior);
+        
+        flow = new VirtualFlow();
 
         control.getProperties().addListener(new MapChangeListener<Object, Object>() {
             @Override
             public void onChanged(Change<? extends Object, ? extends Object> c) {
-                if (c.wasAdded() && SCROLL_TO_INDEX.equals(c.getKey())) {
+                if (c.wasAdded() && SCROLL_TO_INDEX_CENTERED.equals(c.getKey())) {
                     Object row = c.getValueAdded();
                     if (row instanceof Integer) {
-                        scrollTo((Integer)row);
+                        // we want the index to be centered
+                        flow.scrollTo((Integer)row, true);
                     }
 
-                    c.getMap().remove(SCROLL_TO_INDEX);
-                } else if (c.wasAdded() && SHOW_INDEX.equals(c.getKey())) {
+                    c.getMap().remove(SCROLL_TO_INDEX_CENTERED);
+                } else if (c.wasAdded() && SCROLL_TO_INDEX_TOP.equals(c.getKey())) {
                     Object index = c.getValueAdded();
                     if (index instanceof Integer) {
-                        flow.scrollTo((Integer)index);
+                        // we don't want the index to be centered
+                        flow.scrollTo((Integer)index, false);
                     }
 
-                    c.getMap().remove(SHOW_INDEX);
+                    c.getMap().remove(SCROLL_TO_INDEX_TOP);
                 }
             }
         });
@@ -73,7 +77,7 @@
      * The virtualized container which handles the layout and scrolling of
      * all the cells.
      */
-    protected VirtualFlow flow;
+    protected final VirtualFlow flow;
 
     /**
      * Returns a Cell available to be used in the virtual flow. This means you
@@ -91,39 +95,6 @@
      */
     public abstract int getItemCount();
 
-    protected void scrollTo(int index) {
-        if (/*index < 0 || index >= getItemCount() ||*/ getItemCount() == 0) return;
-        
-        boolean posSet = false;
-
-        // special-case the 'greater than row count' condition to have it
-        // be perfectly at position 1
-        if (index >= getItemCount() - 1) {
-            flow.setPosition(1);
-            posSet = true;
-        } else if (index < 0) {
-            flow.setPosition(0);
-            posSet = true;
-        }
-        
-//        IndexedCell lastVisibleCell = flow.getLastVisibleCell();
-//        if (lastVisibleCell != null) {
-//            int lastVisibleIndex = lastVisibleCell.getIndex();
-//            System.out.println(index + " >= " + lastVisibleIndex);
-//            if (index == lastVisibleIndex) {
-//                flow.setPosition(1);
-//                posSet = true;
-//            }
-//        }
-        
-        if (! posSet) {
-            // otherwise just use the default maths
-            flow.setPosition(index / (double) getItemCount());
-        }
-        
-        flow.requestLayout();
-    }
-    
     double getMaxCellWidth(int rowsToCount) {
         return getInsets().getLeft() + flow.getMaxCellWidth(rowsToCount) + getInsets().getRight();
     }
--- a/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/VirtualFlow.java	Wed Mar 21 19:05:57 2012 -0700
+++ b/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/VirtualFlow.java	Mon Mar 26 10:03:10 2012 -0700
@@ -1765,10 +1765,31 @@
         }
     }
 
-    public void scrollTo(int index) {
-        double offset = index * getCellLength(index);
-        mapper.adjustByPixelChunk(offset);
-        addAllToPile();
+    public void scrollTo(int index, boolean centered) {
+        boolean posSet = false;
+        
+        if (index >= getCellCount() - 1) {
+            setPosition(1);
+            posSet = true;
+        } else if (index < 0) {
+            setPosition(0);
+            posSet = true;
+        }
+        
+        if (! posSet) {
+            double offset = 0;
+            for (int i = 0; i < index; i++) {
+                offset += getCellLength(i);
+            }
+            
+            if (centered) {
+                offset += (getCellLength(index) / 2.0);
+                offset -= (getHeight() / 2.0);// + (getHbar() == null ? 0 : getHbar().getHeight()));
+            }
+
+            mapper.adjustByPixelChunk(offset);
+        }
+        
         requestLayout();        
     }
     
--- a/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/caspian/caspian.css	Wed Mar 21 19:05:57 2012 -0700
+++ b/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/caspian/caspian.css	Mon Mar 26 10:03:10 2012 -0700
@@ -3059,11 +3059,17 @@
 
 /* ------- OPEN BUTTON ------- */
 .combo-box-base .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 */
+}
+/*.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;
     -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 
+}*/
 
 /* ------- ARROW* ------- */
 .combo-box-base .arrow {
@@ -3113,6 +3119,29 @@
     -fx-skin: "com.sun.javafx.scene.control.skin.ColorPickerSkin";
 }
 
+.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 {
+    -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 */
+}
+
+.color-picker:hover {
+    -fx-color: -fx-base;
+}
+
+.color-picker.split-button .arrow-button:hover {
+    -fx-color: -fx-hover-base;
+}
+
+.color-picker.split-button .color-picker-label:hover {
+     -fx-color: -fx-hover-base;
+}
+
 .color-picker .picker-color {
     -fx-padding: 4;
     -fx-background-color: null;
--- a/javafx-ui-controls/src/javafx/scene/control/ListView.java	Wed Mar 21 19:05:57 2012 -0700
+++ b/javafx-ui-controls/src/javafx/scene/control/ListView.java	Mon Mar 26 10:03:10 2012 -0700
@@ -711,7 +711,7 @@
      *      size of the items list contained within the given ListView.
      */
     public void scrollTo(int index) {
-       getProperties().put(VirtualContainerBase.SCROLL_TO_INDEX, index);
+       getProperties().put(VirtualContainerBase.SCROLL_TO_INDEX_CENTERED, index);
     }
 
 
--- a/javafx-ui-controls/src/javafx/scene/control/TableView.java	Wed Mar 21 19:05:57 2012 -0700
+++ b/javafx-ui-controls/src/javafx/scene/control/TableView.java	Mon Mar 26 10:03:10 2012 -0700
@@ -1204,7 +1204,7 @@
      * @param index The index of an item that should be visible to the user.
      */
     public void scrollTo(int index) {
-       getProperties().put(VirtualContainerBase.SCROLL_TO_INDEX, index);
+       getProperties().put(VirtualContainerBase.SCROLL_TO_INDEX_CENTERED, index);
     }
 
     /**
--- a/javafx-ui-controls/src/javafx/scene/control/TreeView.java	Wed Mar 21 19:05:57 2012 -0700
+++ b/javafx-ui-controls/src/javafx/scene/control/TreeView.java	Mon Mar 26 10:03:10 2012 -0700
@@ -781,7 +781,7 @@
      *      number of the visible items in the TreeView.
      */
     public void scrollTo(int index) {
-       getProperties().put(VirtualContainerBase.SCROLL_TO_INDEX, index);
+       getProperties().put(VirtualContainerBase.SCROLL_TO_INDEX_CENTERED, index);
     }
 
     /**