changeset 1774:990e4f2d1a90

Automated merge with ssh://jpgodine@jfxsrc.us.oracle.com//javafx/8.0/MASTER/jfx/rt
author jpgodine@JPGODINE-LAP.st-users.us.oracle.com
date Tue, 25 Sep 2012 09:35:14 -0700
parents 1986b76ecd8f ed6f196e5cdc
children 174647284655 a30e7be8621e
files
diffstat 13 files changed, 190 insertions(+), 71 deletions(-) [+]
line wrap: on
line diff
--- a/javafx-ui-common/src/com/sun/javafx/scene/input/InputEventUtils.java	Thu Sep 20 16:38:38 2012 -0700
+++ b/javafx-ui-common/src/com/sun/javafx/scene/input/InputEventUtils.java	Tue Sep 25 09:35:14 2012 -0700
@@ -25,8 +25,13 @@
 
 package com.sun.javafx.scene.input;
 
+import java.util.Arrays;
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Collections;
 import javafx.geometry.Point2D;
 import javafx.scene.Node;
+import javafx.scene.input.TransferMode;
 
 /**
  * Utility class for helper methods needed by input events.
@@ -87,4 +92,34 @@
         return new Point2D(newX, newY);
     }
 
+    private static final List<TransferMode> TM_ANY =
+            Collections.unmodifiableList(Arrays.asList(
+                TransferMode.COPY,
+                TransferMode.MOVE,
+                TransferMode.LINK
+            ));
+
+    private static final List<TransferMode> TM_COPY_OR_MOVE =
+            Collections.unmodifiableList(Arrays.asList(
+                TransferMode.COPY,
+                TransferMode.MOVE
+            ));
+
+    /**
+     * Makes sure changes to the static arrays specified in TransferMode
+     * don't have any effect on the transfer modes used.
+     * @param modes Modes passed in by user
+     * @return list containing the passed modes. If one of the static arrays
+     *         is passed, the expected modes are returned regardless of the
+     *         values in those arrays.
+     */
+    public static List<TransferMode> safeTransferModes(TransferMode[] modes) {
+        if (modes == TransferMode.ANY) {
+            return TM_ANY;
+        } else if (modes == TransferMode.COPY_OR_MOVE) {
+            return TM_COPY_OR_MOVE;
+        } else {
+            return Arrays.asList(modes);
+        }
+    }
 }
--- a/javafx-ui-common/src/javafx/scene/Group.java	Thu Sep 20 16:38:38 2012 -0700
+++ b/javafx-ui-common/src/javafx/scene/Group.java	Tue Sep 25 09:35:14 2012 -0700
@@ -158,14 +158,35 @@
     // adjust.  Scene handles this in doLayoutPass().  If this becomes a
     // performance issue, we can revisit doing the proper computation/predicting here.
 
+    /**
+     * Group defines the preferred width as simply being the width of its layout bounds, which
+     * in turn is simply the sum of the positions & widths of all of its children. That is,
+     * the preferred width is the one that it is at, because a Group cannot be resized.
+     *
+     * @param height This parameter is ignored by Group
+     * @return The layout bounds width
+     */
     @Override public double prefWidth(double height) {
         return getLayoutBounds().getWidth();
     }
 
+    /**
+     * Group defines the preferred height as simply being the height of its layout bounds, which
+     * in turn is simply the sum of the positions & heights of all of its children. That is,
+     * the preferred height is the one that it is at, because a Group cannot be resized.
+     *
+     * @param width This parameter is ignored by Group
+     * @return The layout bounds height
+     */
     @Override public double prefHeight(double width) {
         return getLayoutBounds().getHeight();
     }
 
+    /**
+     * Group implements layoutChildren such that each child is resized to its preferred
+     * size, if the child is resizable. Non-resizable children are simply left alone.
+     * If {@link #autoSizeChildren} is false, then Group does nothing in this method.
+     */
     @Override protected void layoutChildren() {
         if (isAutoSizeChildren()) {
             super.layoutChildren();
--- a/javafx-ui-common/src/javafx/scene/Node.java	Thu Sep 20 16:38:38 2012 -0700
+++ b/javafx-ui-common/src/javafx/scene/Node.java	Tue Sep 25 09:35:14 2012 -0700
@@ -26,10 +26,33 @@
 package javafx.scene;
 
 
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Set;
 import javafx.beans.InvalidationListener;
 import javafx.beans.Observable;
 import javafx.beans.binding.BooleanExpression;
+import javafx.beans.property.BooleanProperty;
+import javafx.beans.property.BooleanPropertyBase;
+import javafx.beans.property.DoubleProperty;
+import javafx.beans.property.DoublePropertyBase;
+import javafx.beans.property.IntegerProperty;
+import javafx.beans.property.ObjectProperty;
+import javafx.beans.property.ObjectPropertyBase;
+import javafx.beans.property.ReadOnlyBooleanProperty;
+import javafx.beans.property.ReadOnlyBooleanPropertyBase;
+import javafx.beans.property.ReadOnlyBooleanWrapper;
+import javafx.beans.property.ReadOnlyObjectProperty;
+import javafx.beans.property.ReadOnlyObjectWrapper;
+import javafx.beans.property.SimpleBooleanProperty;
+import javafx.beans.property.SimpleObjectProperty;
+import javafx.beans.property.StringProperty;
+import javafx.beans.property.StringPropertyBase;
 import javafx.beans.value.ChangeListener;
+import javafx.beans.value.WritableValue;
 import javafx.collections.FXCollections;
 import javafx.collections.ListChangeListener.Change;
 import javafx.collections.ObservableList;
@@ -45,9 +68,11 @@
 import javafx.geometry.Orientation;
 import javafx.geometry.Point2D;
 import javafx.geometry.Point3D;
+import javafx.geometry.Rectangle2D;
 import javafx.scene.effect.Blend;
 import javafx.scene.effect.BlendMode;
 import javafx.scene.effect.Effect;
+import javafx.scene.image.WritableImage;
 import javafx.scene.input.ContextMenuEvent;
 import javafx.scene.input.DragEvent;
 import javafx.scene.input.Dragboard;
@@ -55,15 +80,18 @@
 import javafx.scene.input.InputMethodEvent;
 import javafx.scene.input.InputMethodRequests;
 import javafx.scene.input.KeyEvent;
+import javafx.scene.input.MouseDragEvent;
 import javafx.scene.input.MouseEvent;
-import javafx.scene.input.MouseDragEvent;
+import javafx.scene.input.RotateEvent;
+import javafx.scene.input.ScrollEvent;
+import javafx.scene.input.SwipeEvent;
+import javafx.scene.input.TouchEvent;
 import javafx.scene.input.TransferMode;
-import javafx.scene.input.RotateEvent;
 import javafx.scene.input.ZoomEvent;
-import javafx.scene.input.ScrollEvent;
+import javafx.scene.text.Font;
 import javafx.scene.transform.Rotate;
 import javafx.scene.transform.Transform;
-
+import javafx.util.Callback;
 import com.sun.javafx.Logging;
 import com.sun.javafx.TempState;
 import com.sun.javafx.Utils;
@@ -72,8 +100,23 @@
 import com.sun.javafx.binding.ExpressionHelper;
 import com.sun.javafx.collections.TrackableObservableList;
 import com.sun.javafx.collections.UnmodifiableListSet;
-import com.sun.javafx.css.*;
-import com.sun.javafx.css.converters.*;
+import com.sun.javafx.css.ParsedValue;
+import com.sun.javafx.css.Selector;
+import com.sun.javafx.css.Style;
+import com.sun.javafx.css.StyleConverter;
+import com.sun.javafx.css.StyleHelper;
+import com.sun.javafx.css.StyleManager;
+import com.sun.javafx.css.Styleable;
+import com.sun.javafx.css.StyleableBooleanProperty;
+import com.sun.javafx.css.StyleableDoubleProperty;
+import com.sun.javafx.css.StyleableObjectProperty;
+import com.sun.javafx.css.StyleableProperty;
+import com.sun.javafx.css.Stylesheet;
+import com.sun.javafx.css.converters.BooleanConverter;
+import com.sun.javafx.css.converters.CursorConverter;
+import com.sun.javafx.css.converters.EffectConverter;
+import com.sun.javafx.css.converters.EnumConverter;
+import com.sun.javafx.css.converters.SizeConverter;
 import com.sun.javafx.effect.EffectDirtyBits;
 import com.sun.javafx.geom.BaseBounds;
 import com.sun.javafx.geom.PickRay;
@@ -94,16 +137,6 @@
 import com.sun.javafx.scene.traversal.Direction;
 import com.sun.javafx.sg.PGNode;
 import com.sun.javafx.tk.Toolkit;
-import java.util.*;
-import javafx.beans.property.*;
-import javafx.beans.value.WritableValue;
-import javafx.geometry.Rectangle2D;
-import javafx.scene.image.WritableImage;
-import javafx.scene.input.SwipeEvent;
-import javafx.scene.input.TouchEvent;
-import javafx.scene.text.Font;
-import javafx.scene.text.Text;
-import javafx.util.Callback;
 
 /**
  * Base class for scene graph nodes. A scene graph is a set of tree data structures
@@ -664,7 +697,7 @@
             };
         }
         return parent;
-                    }
+    }
 
     private final InvalidationListener parentDisabledChangedListener = new InvalidationListener() {
         @Override public void invalidated(Observable valueModel) {
@@ -2651,11 +2684,9 @@
             if (contentBias == null) {
                 w = boundedSize(prefWidth(-1), minWidth(-1), maxWidth(-1));
                 h = boundedSize(prefHeight(-1), minHeight(-1), maxHeight(-1));
-
             } else if (contentBias == Orientation.HORIZONTAL) {
                 w = boundedSize(prefWidth(-1), minWidth(-1), maxWidth(-1));
                 h = prefHeight(w);
-
             } else { // bias == VERTICAL
                 h = boundedSize(prefHeight(-1), minHeight(-1), maxHeight(-1));
                 w = prefWidth(h);
--- a/javafx-ui-common/src/javafx/scene/Parent.java	Thu Sep 20 16:38:38 2012 -0700
+++ b/javafx-ui-common/src/javafx/scene/Parent.java	Tue Sep 25 09:35:14 2012 -0700
@@ -29,14 +29,13 @@
 import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
-
-import com.sun.javafx.jmx.MXNodeAlgorithm;
-import com.sun.javafx.jmx.MXNodeAlgorithmContext;
-import javafx.beans.property.*;
+import javafx.beans.property.ObjectProperty;
+import javafx.beans.property.ReadOnlyBooleanProperty;
+import javafx.beans.property.ReadOnlyBooleanWrapper;
+import javafx.beans.property.SimpleObjectProperty;
 import javafx.collections.FXCollections;
 import javafx.collections.ListChangeListener.Change;
 import javafx.collections.ObservableList;
-
 import com.sun.javafx.Logging;
 import com.sun.javafx.TempState;
 import com.sun.javafx.Utils;
@@ -51,6 +50,8 @@
 import com.sun.javafx.geom.RectBounds;
 import com.sun.javafx.geom.transform.BaseTransform;
 import com.sun.javafx.geom.transform.NoninvertibleTransformException;
+import com.sun.javafx.jmx.MXNodeAlgorithm;
+import com.sun.javafx.jmx.MXNodeAlgorithmContext;
 import com.sun.javafx.logging.PlatformLogger;
 import com.sun.javafx.scene.CSSFlags;
 import com.sun.javafx.scene.DirtyBits;
@@ -59,8 +60,7 @@
 import com.sun.javafx.sg.PGNode;
 import com.sun.javafx.tk.Toolkit;
 
-import static com.sun.javafx.logging.PulseLogger.PULSE_LOGGING_ENABLED;
-import static com.sun.javafx.logging.PulseLogger.PULSE_LOGGER;
+import static com.sun.javafx.logging.PulseLogger.*;
 
 /**
  * The base class for all nodes that have children in the scene graph.
@@ -567,8 +567,8 @@
                 Node e = children.get(i);
                 if (e.isManaged()) {
                     unmodifiableManagedChildren.add(e);
-                        }
                 }
+            }
         }
         return (List<E>)unmodifiableManagedChildren;
     }
--- a/javafx-ui-common/src/javafx/scene/Scene.java	Thu Sep 20 16:38:38 2012 -0700
+++ b/javafx-ui-common/src/javafx/scene/Scene.java	Tue Sep 25 09:35:14 2012 -0700
@@ -97,6 +97,7 @@
 import com.sun.javafx.robot.impl.FXRobotHelper;
 import com.sun.javafx.scene.CSSFlags;
 import com.sun.javafx.scene.SceneEventDispatcher;
+import com.sun.javafx.scene.input.InputEventUtils;
 import com.sun.javafx.scene.traversal.Direction;
 import com.sun.javafx.scene.traversal.TraversalEngine;
 import com.sun.javafx.tk.TKDragGestureListener;
@@ -5317,7 +5318,7 @@
 
         if (dndGesture != null) {
             Set<TransferMode> set = EnumSet.noneOf(TransferMode.class);
-            for (TransferMode tm : transferModes) {
+            for (TransferMode tm : InputEventUtils.safeTransferModes(transferModes)) {
                 set.add(tm);
             }
             return dndGesture.startDrag(source, set);
--- a/javafx-ui-common/src/javafx/scene/input/DragEvent.java	Thu Sep 20 16:38:38 2012 -0700
+++ b/javafx-ui-common/src/javafx/scene/input/DragEvent.java	Tue Sep 25 09:35:14 2012 -0700
@@ -602,7 +602,7 @@
         TransferMode result = null;
         Set<TransferMode> intersect = EnumSet.noneOf(TransferMode.class);
 
-        for (TransferMode tm : accepted) {
+        for (TransferMode tm : InputEventUtils.safeTransferModes(accepted)) {
             if (supported.contains(tm)) {
                 intersect.add(tm);
             }
--- a/javafx-ui-common/src/javafx/scene/layout/AnchorPane.java	Thu Sep 20 16:38:38 2012 -0700
+++ b/javafx-ui-common/src/javafx/scene/layout/AnchorPane.java	Tue Sep 25 09:35:14 2012 -0700
@@ -25,13 +25,12 @@
 
 package javafx.scene.layout;
 
+import java.util.List;
 import javafx.geometry.Bounds;
 import javafx.geometry.Insets;
 import javafx.geometry.Orientation;
 import javafx.scene.Node;
 
-import java.util.List;
-
 /**
  * AnchorPane allows the edges of child nodes to be anchored to an offset from
  * the anchor pane's edges.  If the anchor pane has a border and/or padding set, the
@@ -257,6 +256,7 @@
                     (rightAnchor != null? 0 : child.getLayoutBounds().getMinX() + child.getLayoutX());
                 double right = rightAnchor != null? rightAnchor : 0;
                 if (child.getContentBias() == Orientation.VERTICAL) {
+                    // The width depends on the node's height!
                     height = (minimum? child.minHeight(-1) : child.prefHeight(-1));
                 }
                 max = Math.max(max, left + (minimum? child.minWidth(height) : child.prefWidth(height)) + right);
--- a/javafx-ui-common/src/javafx/scene/layout/BorderImage.java	Thu Sep 20 16:38:38 2012 -0700
+++ b/javafx-ui-common/src/javafx/scene/layout/BorderImage.java	Tue Sep 25 09:35:14 2012 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
+ * 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
@@ -17,7 +17,6 @@
  * 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.
--- a/javafx-ui-common/src/javafx/scene/layout/GridPane.java	Thu Sep 20 16:38:38 2012 -0700
+++ b/javafx-ui-common/src/javafx/scene/layout/GridPane.java	Tue Sep 25 09:35:14 2012 -0700
@@ -29,22 +29,22 @@
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
-
 import javafx.beans.property.BooleanProperty;
 import javafx.beans.property.DoubleProperty;
 import javafx.beans.property.ObjectProperty;
 import javafx.beans.value.WritableValue;
+import javafx.collections.ListChangeListener;
 import javafx.collections.ListChangeListener.Change;
 import javafx.collections.ObservableList;
 import javafx.geometry.HPos;
 import javafx.geometry.Insets;
+import javafx.geometry.Orientation;
 import javafx.geometry.Pos;
 import javafx.geometry.VPos;
 import javafx.scene.Group;
 import javafx.scene.Node;
 import javafx.scene.paint.Color;
 import javafx.scene.shape.Line;
-
 import com.sun.javafx.collections.TrackableObservableList;
 import com.sun.javafx.css.StyleableBooleanProperty;
 import com.sun.javafx.css.StyleableDoubleProperty;
@@ -53,8 +53,6 @@
 import com.sun.javafx.css.converters.BooleanConverter;
 import com.sun.javafx.css.converters.EnumConverter;
 import com.sun.javafx.css.converters.SizeConverter;
-import javafx.collections.ListChangeListener;
-import javafx.geometry.Orientation;
 
 
 
--- a/javafx-ui-common/src/javafx/scene/text/Text.java	Thu Sep 20 16:38:38 2012 -0700
+++ b/javafx-ui-common/src/javafx/scene/text/Text.java	Tue Sep 25 09:35:14 2012 -0700
@@ -29,7 +29,7 @@
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.List;
-
+import javafx.beans.DefaultProperty;
 import javafx.beans.property.BooleanProperty;
 import javafx.beans.property.BooleanPropertyBase;
 import javafx.beans.property.DoubleProperty;
@@ -38,9 +38,12 @@
 import javafx.beans.property.IntegerPropertyBase;
 import javafx.beans.property.ObjectProperty;
 import javafx.beans.property.ObjectPropertyBase;
+import javafx.beans.property.ReadOnlyDoubleProperty;
+import javafx.beans.property.ReadOnlyDoubleWrapper;
 import javafx.beans.property.SimpleObjectProperty;
 import javafx.beans.property.StringProperty;
 import javafx.beans.property.StringPropertyBase;
+import javafx.beans.value.WritableValue;
 import javafx.geometry.BoundingBox;
 import javafx.geometry.Bounds;
 import javafx.geometry.Point2D;
@@ -52,7 +55,6 @@
 import javafx.scene.shape.PathElement;
 import javafx.scene.shape.Shape;
 import javafx.scene.transform.Transform;
-
 import com.sun.javafx.css.StyleableBooleanProperty;
 import com.sun.javafx.css.StyleableObjectProperty;
 import com.sun.javafx.css.StyleableProperty;
@@ -71,9 +73,6 @@
 import com.sun.javafx.sg.PGTextHelper;
 import com.sun.javafx.tk.FontLoader;
 import com.sun.javafx.tk.Toolkit;
-import javafx.beans.DefaultProperty;
-import javafx.beans.property.*;
-import javafx.beans.value.WritableValue;
 
 /**
  * The {@code Text} class defines a node that displays a text.
--- a/javafx-ui-common/test/unit/javafx/scene/input/DragAndDropTest.java	Thu Sep 20 16:38:38 2012 -0700
+++ b/javafx-ui-common/test/unit/javafx/scene/input/DragAndDropTest.java	Tue Sep 25 09:35:14 2012 -0700
@@ -645,7 +645,46 @@
         
         assertEquals(1, counter);
     }
-    
+
+    @Test
+    public void modifyingStaticArraysShouldNotInfluenceResult() {
+        TransferMode.ANY[0] = TransferMode.LINK;
+        TransferMode.ANY[1] = TransferMode.LINK;
+        TransferMode.ANY[2] = TransferMode.LINK;
+
+        TransferMode.COPY_OR_MOVE[0] = TransferMode.LINK;
+        TransferMode.COPY_OR_MOVE[1] = TransferMode.LINK;
+
+        final Node n = oneNode();
+        final MouseEventGenerator gen = new MouseEventGenerator();
+
+        dragSource = n;
+        n.setOnMousePressed(doDetect);
+        n.setOnDragDetected(stringSource(TransferMode.ANY));
+        n.setOnDragOver(acceptCopyOrMove);
+        n.setOnDragDropped(new EventHandler<DragEvent>() {
+            @Override public void handle(DragEvent event) {
+                event.acceptTransferModes(TransferMode.ANY);
+                event.setDropCompleted(true);
+            }
+        });
+
+        /* start drag */
+        n.getScene().impl_processMouseEvent(
+                gen.generateMouseEvent(MouseEvent.MOUSE_PRESSED, 50, 50));
+
+        /* drag and drop*/
+        assertSame(TransferMode.COPY, toolkit.dragTo(52, 52, TransferMode.COPY));
+        assertSame(TransferMode.COPY, toolkit.drop(52, 52, TransferMode.COPY));
+
+        TransferMode.ANY[0] = TransferMode.COPY;
+        TransferMode.ANY[1] = TransferMode.MOVE;
+        TransferMode.ANY[2] = TransferMode.LINK;
+
+        TransferMode.COPY_OR_MOVE[0] = TransferMode.COPY;
+        TransferMode.COPY_OR_MOVE[1] = TransferMode.MOVE;
+    }
+
     /************************************************************************/
     /*                           GESTURE FINISH                             */
     /************************************************************************/
--- a/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/ScrollPaneSkin.java	Thu Sep 20 16:38:38 2012 -0700
+++ b/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/ScrollPaneSkin.java	Tue Sep 25 09:35:14 2012 -0700
@@ -25,9 +25,6 @@
 
 package com.sun.javafx.scene.control.skin;
 
-import com.sun.javafx.PlatformUtil;
-import static com.sun.javafx.Utils.clamp;
-import static com.sun.javafx.scene.control.skin.Utils.boundedSize;
 import javafx.animation.Animation.Status;
 import javafx.animation.KeyFrame;
 import javafx.animation.KeyValue;
@@ -40,8 +37,8 @@
 import javafx.beans.value.ObservableValue;
 import javafx.event.ActionEvent;
 import javafx.event.Event;
+import javafx.event.EventDispatchChain;
 import javafx.event.EventDispatcher;
-import javafx.event.EventDispatchChain;
 import javafx.event.EventHandler;
 import javafx.geometry.BoundingBox;
 import javafx.geometry.Bounds;
@@ -58,12 +55,14 @@
 import javafx.scene.layout.StackPane;
 import javafx.scene.shape.Rectangle;
 import javafx.util.Duration;
-
+import com.sun.javafx.PlatformUtil;
+import com.sun.javafx.Utils;
 import com.sun.javafx.scene.control.behavior.ScrollPaneBehavior;
 import com.sun.javafx.scene.traversal.TraversalEngine;
 import com.sun.javafx.scene.traversal.TraverseListener;
-import com.sun.javafx.Utils;
-import javafx.scene.Group;
+
+import static com.sun.javafx.Utils.*;
+import static com.sun.javafx.scene.control.skin.Utils.*;
 
 public class ScrollPaneSkin extends SkinBase<ScrollPane, ScrollPaneBehavior> implements TraverseListener {
     /***************************************************************************
@@ -1011,7 +1010,7 @@
     private boolean tempVisibility;
 
 
-    void startSBReleasedAnimation() {
+    protected void startSBReleasedAnimation() {
         if (sbTouchTimeline == null) {
             /*
             ** timeline to leave the scrollbars visible for a short
@@ -1037,7 +1036,7 @@
 
 
 
-    void startContentsToViewport() {
+    protected void startContentsToViewport() {
         double newPosX = posX;
         double newPosY = posY;
         double hRange = getSkinnable().getHmax() - getSkinnable().getHmin();
@@ -1072,13 +1071,13 @@
             contentsToViewTimeline.stop();
         }
         contentsToViewTimeline = new Timeline();
-	/*
-	** short pause before animation starts
-	*/
+        /*
+        ** short pause before animation starts
+        */
         contentsToViewKF1 = new KeyFrame(Duration.millis(50));
-	/*
-	** reposition
-	*/
+        /*
+        ** reposition
+        */
         contentsToViewKF2 = new KeyFrame(Duration.millis(150), new EventHandler<ActionEvent>() {
                 @Override public void handle(ActionEvent event) {
                     requestLayout();
@@ -1087,10 +1086,10 @@
             new KeyValue(contentPosX, newPosX),
             new KeyValue(contentPosY, newPosY)
             );
-	/*
-	** block out 'aftershocks', but real events will
-	** still reactivate
-	*/
+        /*
+        ** block out 'aftershocks', but real events will
+        ** still reactivate
+        */
         contentsToViewKF3 = new KeyFrame(Duration.millis(1500));
         contentsToViewTimeline.getKeyFrames().addAll(contentsToViewKF1, contentsToViewKF2, contentsToViewKF3);
         contentsToViewTimeline.playFromStart();
--- a/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/VirtualFlow.java	Thu Sep 20 16:38:38 2012 -0700
+++ b/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/VirtualFlow.java	Tue Sep 25 09:35:14 2012 -0700
@@ -26,19 +26,16 @@
 package com.sun.javafx.scene.control.skin;
 
 import java.util.ArrayList;
-
 import javafx.beans.InvalidationListener;
 import javafx.beans.Observable;
 import javafx.beans.property.BooleanProperty;
 import javafx.beans.property.BooleanPropertyBase;
-import javafx.beans.property.DoubleProperty;
-import javafx.beans.property.DoublePropertyBase;
 import javafx.beans.value.ChangeListener;
 import javafx.beans.value.ObservableValue;
 import javafx.collections.ObservableList;
 import javafx.event.Event;
+import javafx.event.EventDispatchChain;
 import javafx.event.EventDispatcher;
-import javafx.event.EventDispatchChain;
 import javafx.event.EventHandler;
 import javafx.geometry.Orientation;
 import javafx.scene.Group;
@@ -52,7 +49,6 @@
 import javafx.scene.layout.Region;
 import javafx.scene.layout.StackPane;
 import javafx.scene.shape.Rectangle;
-
 import javafx.util.Callback;
 
 /**
@@ -1313,12 +1309,13 @@
 
         if (lengthBar.isVisible()) {
             lengthBar.setMax(1);
-            
-            if (numCellsVisibleOnScreen == 0) {
-                // special case to help resolve RT-17701
+
+            if (numCellsVisibleOnScreen == 0 && cellCount == 1) {
+                // special case to help resolve RT-17701 and the case where we have
+                // only a single row and it is bigger than the viewport
                 lengthBar.setVisibleAmount(flowLength / sumCellLength);
             } else {
-                lengthBar.setVisibleAmount(numCellsVisibleOnScreen / (float) cellCount);
+                lengthBar.setVisibleAmount(cellCount / viewportLength);
             }
 
             // Fix for RT-11873. If this isn't here, we can have a situation where