changeset 6227:18be0bd1901b

RT-21495: use content pref height/width if ScrollPane's pref height/width is USE_COMPUTED_SIZE
author David Grieve<david.grieve@oracle.com>
date Thu, 30 Jan 2014 23:51:01 -0500
parents a66288f7f241
children adeaa598a2be
files modules/controls/src/main/java/com/sun/javafx/scene/control/skin/ScrollPaneSkin.java modules/controls/src/test/java/com/sun/javafx/scene/control/skin/ScrollPaneSkinTest.java
diffstat 2 files changed, 157 insertions(+), 60 deletions(-) [+]
line wrap: on
line diff
--- a/modules/controls/src/main/java/com/sun/javafx/scene/control/skin/ScrollPaneSkin.java	Thu Jan 30 19:02:54 2014 -0800
+++ b/modules/controls/src/main/java/com/sun/javafx/scene/control/skin/ScrollPaneSkin.java	Thu Jan 30 23:51:01 2014 -0500
@@ -51,6 +51,7 @@
 import javafx.scene.input.MouseEvent;
 import javafx.scene.input.ScrollEvent;
 import javafx.scene.input.TouchEvent;
+import javafx.scene.layout.Region;
 import javafx.scene.layout.StackPane;
 import javafx.scene.shape.Rectangle;
 import javafx.util.Duration;
@@ -742,36 +743,125 @@
 
     @Override protected double computePrefWidth(double height, double topInset, double rightInset, double bottomInset, double leftInset) {
         final ScrollPane sp = getSkinnable();
-        
-        if (sp.getPrefViewportWidth() > 0) {
-            double vsbWidth = sp.getVbarPolicy() == ScrollBarPolicy.ALWAYS? vsb.prefWidth(-1) : 0;
-            return (sp.getPrefViewportWidth() + vsbWidth + snappedLeftInset() + snappedRightInset());
+
+        if (sp.getPrefWidth() == ScrollPane.USE_COMPUTED_SIZE || sp.getPrefWidth() == ScrollPane.USE_PREF_SIZE) {
+
+            double vsbWidth = sp.getVbarPolicy() == ScrollBarPolicy.ALWAYS? vsb.prefWidth(ScrollBar.USE_COMPUTED_SIZE) : 0;
+            double minWidth = vsbWidth + snappedLeftInset() + snappedRightInset();
+
+            if (sp.getPrefViewportWidth() > 0) {
+                return (sp.getPrefViewportWidth() + minWidth);
+            }
+            else if (sp.getContent() != null) {
+                return (sp.getContent().prefWidth(height) + minWidth);
+            }
+            else {
+                return Math.max(minWidth, DEFAULT_PREF_SIZE);
+            }
+        }
+        else if (sp.getPrefWidth() < 0) {
+            return DEFAULT_PREF_SIZE;
         }
         else {
-            return DEFAULT_PREF_SIZE;
+            return sp.getPrefWidth();
         }
     }
 
     @Override protected double computePrefHeight(double width, double topInset, double rightInset, double bottomInset, double leftInset) {
         final ScrollPane sp = getSkinnable();
-        
-        if (sp.getPrefViewportHeight() > 0) {
-            double hsbHeight = sp.getHbarPolicy() == ScrollBarPolicy.ALWAYS? hsb.prefHeight(-1) : 0;
-            return (sp.getPrefViewportHeight() + hsbHeight + snappedTopInset() + snappedBottomInset());
+
+        if (sp.getPrefHeight() == ScrollPane.USE_COMPUTED_SIZE || sp.getPrefWidth() == ScrollPane.USE_PREF_SIZE) {
+
+            double hsbHeight = sp.getHbarPolicy() == ScrollBarPolicy.ALWAYS ? hsb.prefHeight(ScrollBar.USE_COMPUTED_SIZE) : 0;
+            double minHeight = hsbHeight + snappedTopInset() + snappedBottomInset();
+
+            if (sp.getPrefViewportHeight() > 0) {
+                return (sp.getPrefViewportHeight() + minHeight);
+            }
+            else if (sp.getContent() != null) {
+                return (sp.getContent().prefHeight(width) + minHeight);
+            }
+            else {
+                return Math.max(minHeight, DEFAULT_PREF_SIZE);
+            }
+        }
+        else if (sp.getPrefHeight() < 0) {
+            return DEFAULT_PREF_SIZE;
         }
         else {
-            return DEFAULT_PREF_SIZE;
+            return sp.getPrefHeight();
         }
     }
 
     @Override protected double computeMinWidth(double height, double topInset, double rightInset, double bottomInset, double leftInset) {
-        double w = corner.minWidth(-1);
-        return (w > 0) ? (3 * w) : (DEFAULT_MIN_SIZE);
+        final ScrollPane sp = getSkinnable();
+
+        if (sp.getMinWidth() == ScrollPane.USE_COMPUTED_SIZE) {
+            double minWidth = corner.minWidth(Region.USE_COMPUTED_SIZE) + snappedLeftInset() + snappedRightInset();
+            return (minWidth > 0) ? minWidth : DEFAULT_MIN_SIZE;
+        }
+        else if (sp.getMinWidth() == ScrollPane.USE_PREF_SIZE) {
+            return computePrefWidth(height, topInset, rightInset, bottomInset, leftInset);
+        }
+        else if (sp.getMinWidth() < 0) {
+            return DEFAULT_MIN_SIZE;
+        }
+        else {
+            return sp.getMinWidth();
+        }
     }
 
     @Override protected double computeMinHeight(double width, double topInset, double rightInset, double bottomInset, double leftInset) {
-        double h = corner.minHeight(-1);
-        return (h > 0) ? (3 * h) : (DEFAULT_MIN_SIZE);
+        final ScrollPane sp = getSkinnable();
+
+        if (sp.getMinHeight() == ScrollPane.USE_COMPUTED_SIZE) {
+            double minHeight = corner.minHeight(Region.USE_COMPUTED_SIZE) + snappedTopInset() + snappedBottomInset();
+            return (minHeight > 0) ? minHeight : DEFAULT_MIN_SIZE;
+        }
+        else if (sp.getMinHeight() == ScrollPane.USE_PREF_SIZE) {
+            return computePrefHeight(width, topInset, rightInset, bottomInset, leftInset);
+        }
+        else if (sp.getMinHeight() < 0) {
+            return DEFAULT_MIN_SIZE;
+        }
+        else {
+            return sp.getMinHeight();
+        }
+    }
+
+    @Override protected double computeMaxWidth(double height, double topInset, double rightInset, double bottomInset, double leftInset) {
+        final ScrollPane sp = getSkinnable();
+
+        if (sp.getMaxWidth() == ScrollPane.USE_COMPUTED_SIZE) {
+            return super.computeMaxWidth(height, topInset, rightInset, bottomInset, leftInset);
+        }
+        else if (sp.getMaxWidth() == ScrollPane.USE_PREF_SIZE) {
+            return computePrefWidth(height, topInset, rightInset, bottomInset, leftInset);
+        }
+        else if (sp.getMaxWidth() < 0) {
+            return Double.MAX_VALUE;
+        }
+        else {
+            return sp.getMaxWidth();
+        }
+    }
+
+    @Override protected double computeMaxHeight(double width, double topInset, double rightInset, double bottomInset, double leftInset) {
+        final ScrollPane sp = getSkinnable();
+
+        if (sp.getMaxHeight() == ScrollPane.USE_COMPUTED_SIZE) {
+            return super.computeMaxHeight(width, topInset, rightInset, bottomInset, leftInset);
+        }
+        else if (sp.getMaxHeight() == ScrollPane.USE_PREF_SIZE) {
+            return computePrefHeight(width, topInset, rightInset, bottomInset, leftInset);
+
+        }
+        else if (sp.getMaxHeight() < 0) {
+            return Double.MAX_VALUE;
+        }
+        else {
+            return sp.getMaxHeight();
+        }
     }
 
     @Override protected void layoutChildren(final double x, final double y,
@@ -825,6 +915,7 @@
                 if (vsbvis) {
                     // now both are visible
                     contentWidth -= vsbWidth;
+                    hsbWidth -= vsbWidth;
                     computeScrollNodeSize(contentWidth, contentHeight);
                 }
             } else if (vsbvis && !hsbvis) {
@@ -833,6 +924,7 @@
                 if (hsbvis) {
                     // now both are visible
                     contentHeight -= hsbHeight;
+                    vsbHeight -= hsbHeight;
                     computeScrollNodeSize(contentWidth, contentHeight);
                 }
             }
@@ -954,12 +1046,8 @@
     private boolean determineHorizontalSBVisible() {
         final ScrollPane sp = getSkinnable();
 
-        // the conditional at the end of this calculation comes due to RT-35053
-        final double contentw = sp.getWidth() - snappedLeftInset() - snappedRightInset()
-                - (vsbvis && ! sp.isFitToHeight() ? vsb.getWidth() : 0);
-
         if (IS_TOUCH_SUPPORTED) {
-            return (tempVisibility && (nodeWidth > contentw));
+            return (tempVisibility && (nodeWidth > contentWidth));
         }
         else {
             // RT-17395: ScrollBarPolicy might be null. If so, treat it as "AS_NEEDED", which is the default
@@ -967,15 +1055,15 @@
             return (ScrollBarPolicy.NEVER == hbarPolicy) ? false :
                    ((ScrollBarPolicy.ALWAYS == hbarPolicy) ? true :
                    ((sp.isFitToWidth() && scrollNode != null ? scrollNode.isResizable() : false) ?
-                   (nodeWidth > contentw && scrollNode.minWidth(-1) > contentw) : (nodeWidth > contentw)));
+                   (nodeWidth > contentWidth && scrollNode.minWidth(-1) > contentWidth) : (nodeWidth > contentWidth)));
         }
     }
 
     private boolean determineVerticalSBVisible() {
         final ScrollPane sp = getSkinnable();
-        final double contenth = sp.getHeight() - snappedTopInset() - snappedBottomInset();
+
         if (IS_TOUCH_SUPPORTED) {
-            return (tempVisibility && (nodeHeight > contenth));
+            return (tempVisibility && (nodeHeight > contentHeight));
         }
         else {
             // RT-17395: ScrollBarPolicy might be null. If so, treat it as "AS_NEEDED", which is the default
@@ -983,7 +1071,7 @@
             return (ScrollBarPolicy.NEVER == vbarPolicy) ? false :
                    ((ScrollBarPolicy.ALWAYS == vbarPolicy) ? true :
                    ((sp.isFitToHeight() && scrollNode != null ? scrollNode.isResizable() : false) ?
-                   (nodeHeight > contenth && scrollNode.minHeight(-1) > contenth) : (nodeHeight > contenth)));
+                   (nodeHeight > contentHeight && scrollNode.minHeight(-1) > contentHeight) : (nodeHeight > contentHeight)));
         }
     }
 
--- a/modules/controls/src/test/java/com/sun/javafx/scene/control/skin/ScrollPaneSkinTest.java	Thu Jan 30 19:02:54 2014 -0800
+++ b/modules/controls/src/test/java/com/sun/javafx/scene/control/skin/ScrollPaneSkinTest.java	Thu Jan 30 23:51:01 2014 -0500
@@ -487,7 +487,48 @@
         sp.setMinWidth(40);
         sp.setMinHeight(40);
 
-        scrollPane.setPrefSize(30, 50);
+        // see comments in checkIfScrollbarsWhenFitToWidthAndWidthLessMin for why width is 60
+        scrollPane.setPrefSize(60, 30);
+        scrollPane.setContent(sp);
+        scrollPane.setPannable(true);
+        scrollPane.setFitToWidth(true);
+        scrollPane.setFitToHeight(true);
+
+        Scene scene = new Scene(new Group(), 400, 400);
+        ((Group) scene.getRoot()).getChildren().clear();
+        ((Group) scene.getRoot()).getChildren().add(scrollPane);
+        Stage stage = new Stage();
+        stage.setScene(scene);
+        stage.show();
+
+        /*
+        ** did it work?
+        */
+        assertTrue(!skin.isHSBarVisible() & skin.isVSBarVisible());
+    }
+
+    /*
+    ** check if ScrollBars appear if fitToWidth is true but width is < minWidth
+    */
+    @Test public void checkIfScrollbarsWhenFitToWidthAndWidthLessMin() {
+        scrollPane.setHbarPolicy(ScrollPane.ScrollBarPolicy.AS_NEEDED);
+        scrollPane.setVbarPolicy(ScrollPane.ScrollBarPolicy.AS_NEEDED);
+
+        StackPane sp = new StackPane();
+        sp.setPrefWidth(80);
+        sp.setPrefHeight(80);
+        sp.setMinWidth(40);
+        sp.setMinHeight(40);
+
+        // set width < content minWidth, should get horizontal scroll bar
+        // set height > content minHeight, should not get vertical scroll bar
+        // Note that the scrollPane's height has to be big enough to fit both the
+        // horizontal ScrollBar and the re-sized content. If the ScrollBar's height
+        // is 16, then the scrollPane's prefHeight needs to be 16 plus the content's
+        // minHeight of 40 plus one pixel (since the content and the ScrollBar don't
+        // overlap), all of which adds up to 57. Originally, this test had the height
+        // set to 50 which caused the vertical ScrollBar to be visible.
+        scrollPane.setPrefSize(30, 60);
         scrollPane.setContent(sp);
         scrollPane.setPannable(true);
         scrollPane.setFitToWidth(true);
@@ -507,9 +548,9 @@
     }
 
     /*
-    ** check if ScrollBars appear if fitToHeight is true but height is < minHeight
+    ** check if ScrollBars appear if fitToHeight & fitToWidth are true but height is < minHeight & width is < minWidth
     */
-    @Test public void checkIfScrollbarsWhenFitToWidthAndWidthLessMin() {
+    @Test public void checkIfScrollbarsWhenBothFitToAndBothLessMin() {
         scrollPane.setHbarPolicy(ScrollPane.ScrollBarPolicy.AS_NEEDED);
         scrollPane.setVbarPolicy(ScrollPane.ScrollBarPolicy.AS_NEEDED);
 
@@ -519,7 +560,7 @@
         sp.setMinWidth(40);
         sp.setMinHeight(40);
 
-        scrollPane.setPrefSize(50, 30);
+        scrollPane.setPrefSize(60, 30);
         scrollPane.setContent(sp);
         scrollPane.setPannable(true);
         scrollPane.setFitToWidth(true);
@@ -535,39 +576,7 @@
         /*
         ** did it work?
         */
-        assertTrue(skin.isVSBarVisible() & !skin.isHSBarVisible());
-    }
-
-    /*
-    ** check if ScrollBars appear if fitToHeight & fitToWidth are true but height is < minHeight & width is < minWidth
-    */
-    @Test public void checkIfScrollbarsWhenBothFitToAndBothLessMin() {
-        scrollPane.setHbarPolicy(ScrollPane.ScrollBarPolicy.AS_NEEDED);
-        scrollPane.setVbarPolicy(ScrollPane.ScrollBarPolicy.AS_NEEDED);
-
-        StackPane sp = new StackPane();
-        sp.setPrefWidth(80);
-        sp.setPrefHeight(80);
-        sp.setMinWidth(40);
-        sp.setMinHeight(40);
-
-        scrollPane.setPrefSize(30, 30);
-        scrollPane.setContent(sp);
-        scrollPane.setPannable(true);
-        scrollPane.setFitToWidth(true);
-        scrollPane.setFitToHeight(true);
-
-        Scene scene = new Scene(new Group(), 400, 400);
-        ((Group) scene.getRoot()).getChildren().clear();
-        ((Group) scene.getRoot()).getChildren().add(scrollPane);
-        Stage stage = new Stage();
-        stage.setScene(scene);
-        stage.show();
-
-        /*
-        ** did it work?
-        */
-        assertTrue(skin.isVSBarVisible() & skin.isHSBarVisible());
+        assertTrue(!skin.isHSBarVisible() & skin.isVSBarVisible());
     }
 
     /*