1 /*
   2  * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package com.sun.javafx.scene.control.skin;
  27 
  28 import static org.junit.Assert.assertEquals;
  29 import static org.junit.Assert.assertTrue;
  30 import javafx.beans.value.ChangeListener;
  31 import javafx.beans.value.ObservableValue;
  32 import javafx.event.Event;
  33 import javafx.event.EventHandler;
  34 import javafx.event.EventType;
  35 import javafx.scene.Group;
  36 import javafx.scene.Scene;
  37 import javafx.scene.control.Button;
  38 import javafx.scene.control.CheckBox;
  39 import javafx.scene.control.Label;
  40 import javafx.scene.control.RadioButton;
  41 import javafx.scene.control.ScrollPane;
  42 import javafx.scene.input.*;
  43 import javafx.scene.layout.HBox;
  44 import javafx.scene.layout.Pane;
  45 import javafx.scene.layout.Region;
  46 import javafx.scene.layout.StackPane;
  47 import javafx.scene.layout.VBox;
  48 import javafx.scene.shape.Rectangle;
  49 import javafx.stage.Stage;
  50 
  51 import org.junit.Before;
  52 import org.junit.Ignore;
  53 import org.junit.Test;
  54 
  55 import com.sun.javafx.pgstub.StubScene;
  56 import javafx.event.EventHandler;
  57 import javafx.scene.Group;
  58 import javafx.scene.Scene;
  59 import javafx.scene.shape.Rectangle;
  60 import javafx.stage.Stage;
  61 import org.junit.Test;
  62 import static org.junit.Assert.*;
  63 
  64 
  65 /**
  66  * @author mickf
  67  */
  68 public class ScrollPaneSkinTest {
  69     private ScrollPane scrollPane;
  70     private ScrollPaneSkinMock skin;
  71 
  72     @Before public void setup() {
  73         scrollPane = new ScrollPane();
  74         skin = new ScrollPaneSkinMock(scrollPane);
  75         scrollPane.setSkin(skin);
  76     }
  77 
  78     /*
  79     ** RT-16641 : root cause, you shouldn't be able to drag
  80     ** contents if they don't fill the scrollpane
  81     */
  82     @Test public void shouldntDragContentSmallerThanViewport() {
  83         scrollPane.setHbarPolicy(ScrollPane.ScrollBarPolicy.ALWAYS);
  84         scrollPane.setVbarPolicy(ScrollPane.ScrollBarPolicy.ALWAYS);
  85 
  86         StackPane sp = new StackPane();
  87         sp.setPrefWidth(80);
  88         sp.setPrefHeight(80);
  89 
  90         scrollPane.setContent(sp);
  91         scrollPane.setTranslateX(70);
  92         scrollPane.setTranslateY(30);
  93         scrollPane.setPrefWidth(100);
  94         scrollPane.setPrefHeight(100);
  95         scrollPane.setPannable(true);
  96 
  97         MouseEventGenerator generator = new MouseEventGenerator();
  98 
  99         Scene scene = new Scene(new Group(), 400, 400);
 100         ((Group) scene.getRoot()).getChildren().clear();
 101         ((Group) scene.getRoot()).getChildren().add(scrollPane);
 102         Stage stage = new Stage();
 103         stage.setScene(scene);
 104         stage.show();
 105 
 106         double originalValue = scrollPane.getVvalue();
 107 
 108         Event.fireEvent(sp, generator.generateMouseEvent(MouseEvent.MOUSE_PRESSED, 50, 50));
 109         Event.fireEvent(sp, generator.generateMouseEvent(MouseEvent.MOUSE_DRAGGED, 75, 75));
 110         Event.fireEvent(sp, generator.generateMouseEvent(MouseEvent.MOUSE_RELEASED, 75, 75));
 111 
 112         assertEquals(originalValue, scrollPane.getVvalue(), 0.01);
 113 
 114     }
 115 
 116     /*
 117      * check we can drag contents that are larger than the scrollpane
 118      */
 119     @Test public void shouldDragContentLargerThanViewport() {
 120         scrollPane.setHbarPolicy(ScrollPane.ScrollBarPolicy.ALWAYS);
 121         scrollPane.setVbarPolicy(ScrollPane.ScrollBarPolicy.ALWAYS);
 122 
 123         StackPane sp = new StackPane();
 124         sp.setPrefWidth(180);
 125         sp.setPrefHeight(180);
 126 
 127         scrollPane.setContent(sp);
 128         scrollPane.setTranslateX(70);
 129         scrollPane.setTranslateY(30);
 130         scrollPane.setPrefWidth(100);
 131         scrollPane.setPrefHeight(100);
 132         scrollPane.setPannable(true);
 133 
 134         MouseEventGenerator generator = new MouseEventGenerator();
 135 
 136         Scene scene = new Scene(new Group(), 400, 400);
 137         ((Group) scene.getRoot()).getChildren().clear();
 138         ((Group) scene.getRoot()).getChildren().add(scrollPane);
 139         Stage stage = new Stage();
 140         stage.setScene(scene);
 141         stage.show();
 142 
 143         double originalValue = scrollPane.getVvalue();
 144 
 145         Event.fireEvent(sp, generator.generateMouseEvent(MouseEvent.MOUSE_PRESSED, 75, 75));
 146         Event.fireEvent(sp, generator.generateMouseEvent(MouseEvent.MOUSE_DRAGGED, 50, 50));
 147         Event.fireEvent(sp, generator.generateMouseEvent(MouseEvent.MOUSE_RELEASED, 50, 50));
 148 
 149         assertTrue(originalValue < scrollPane.getVvalue());
 150     }
 151 
 152 
 153     boolean continueTest;
 154     class myPane extends Pane {
 155         public void growH() {
 156             setHeight(300);
 157         }
 158        public void growW() {
 159             setWidth(300);
 160         }
 161 
 162     }
 163     myPane pInner;
 164 
 165     /*
 166     ** check if scrollPane content vertical position compensates for content size change
 167     */
 168     @Test public void checkPositionOnContentSizeChangeHeight() {
 169         pInner = new myPane();
 170         pInner.setPrefWidth(200);
 171         pInner.setPrefHeight(200);
 172 
 173         scrollPane.setContent(pInner);
 174         scrollPane.setPrefWidth(100);
 175         scrollPane.setPrefHeight(100);
 176 
 177         Scene scene = new Scene(new Group(), 400, 400);
 178         ((Group) scene.getRoot()).getChildren().clear();
 179         ((Group) scene.getRoot()).getChildren().add(scrollPane);
 180         Stage stage = new Stage();
 181         stage.setScene(scene);
 182         stage.show();
 183 
 184         double originalValue = 0.5;
 185         scrollPane.setVvalue(originalValue);
 186 
 187         continueTest = false;
 188         scrollPane.vvalueProperty().addListener((observable, oldBounds, newBounds) -> {
 189             continueTest = true;
 190         });
 191 
 192         /*
 193         ** increase the height of the content
 194         */
 195         pInner.growH();
 196 
 197         int count = 0;
 198         while (continueTest == false && count < 10) {
 199             try {
 200                 Thread.sleep(100);
 201             }
 202             catch (Exception e) {}
 203             count++;
 204         }
 205 
 206         /*
 207         ** did it work?
 208         */
 209         assertTrue(originalValue > scrollPane.getVvalue() && scrollPane.getVvalue() > 0.0);
 210     }
 211 
 212 
 213     /*
 214     ** check if scrollPane content Horizontal position compensates for content size change
 215     */
 216     @Test public void checkPositionOnContentSizeChangeWidth() {
 217 
 218         pInner = new myPane();
 219         pInner.setPrefWidth(200);
 220         pInner.setPrefHeight(200);
 221 
 222         scrollPane.setContent(pInner);
 223         scrollPane.setPrefWidth(100);
 224         scrollPane.setPrefHeight(100);
 225 
 226         Scene scene = new Scene(new Group(), 400, 400);
 227         ((Group) scene.getRoot()).getChildren().clear();
 228         ((Group) scene.getRoot()).getChildren().add(scrollPane);
 229         Stage stage = new Stage();
 230         stage.setScene(scene);
 231         stage.show();
 232 
 233         double originalValue = 0.5;
 234         scrollPane.setHvalue(originalValue);
 235 
 236         continueTest = false;
 237         scrollPane.hvalueProperty().addListener((observable, oldBounds, newBounds) -> {
 238             continueTest = true;
 239         });
 240 
 241         /*
 242         ** increase the width of the content
 243         */
 244         pInner.growW();
 245 
 246         int count = 0;
 247         while (continueTest == false && count < 10) {
 248             try {
 249                 Thread.sleep(100);
 250             }
 251             catch (Exception e) {}
 252             count++;
 253         }
 254 
 255         /*
 256         ** did it work?
 257         */
 258         assertTrue(originalValue > scrollPane.getHvalue() && scrollPane.getHvalue() > 0.0);
 259     }
 260 
 261 
 262     private boolean scrolled;
 263     /*
 264     ** check if scrollPane content Horizontal position compensates for content size change
 265     */
 266     @Test public void checkIfScrollPaneWithinScrollPaneGetsScrollEvents() {
 267 
 268         scrolled = false;
 269 
 270         Rectangle rect = new Rectangle(100, 100, 100, 100);
 271         rect.setOnScroll(event -> {
 272             scrolled = true;
 273         });
 274 
 275         final ScrollPane scrollPaneInner = new ScrollPane();
 276         scrollPaneInner.setSkin(new com.sun.javafx.scene.control.skin.ScrollPaneSkin(scrollPaneInner));
 277         scrollPaneInner.setHbarPolicy(ScrollPane.ScrollBarPolicy.ALWAYS);
 278         scrollPaneInner.setVbarPolicy(ScrollPane.ScrollBarPolicy.ALWAYS);
 279         scrollPaneInner.setPrefWidth(100);
 280         scrollPaneInner.setPrefHeight(100);
 281         scrollPaneInner.setPannable(true);
 282         scrollPaneInner.setContent(rect);
 283 
 284         Pane pOuter = new Pane();
 285         pOuter.setPrefWidth(600);
 286         pOuter.setPrefHeight(600);
 287         pOuter.getChildren().add(scrollPaneInner);
 288 
 289         final ScrollPane scrollPaneOuter = new ScrollPane();
 290         scrollPaneOuter.setSkin(new com.sun.javafx.scene.control.skin.ScrollPaneSkin(scrollPaneOuter));
 291         scrollPaneOuter.setHbarPolicy(ScrollPane.ScrollBarPolicy.ALWAYS);
 292         scrollPaneOuter.setVbarPolicy(ScrollPane.ScrollBarPolicy.ALWAYS);
 293         scrollPaneOuter.setPrefWidth(500);
 294         scrollPaneOuter.setPrefHeight(500);
 295         scrollPaneOuter.setPannable(true);
 296         scrollPaneOuter.setOnScroll(event -> {
 297             scrolled = true;
 298         });
 299         scrollPaneOuter.setContent(pOuter);
 300 
 301         Scene scene = new Scene(new Group(), 700, 700);
 302         ((Group) scene.getRoot()).getChildren().clear();
 303         ((Group) scene.getRoot()).getChildren().add(scrollPaneOuter);
 304         scrolled = false;
 305 
 306         Stage stage = new Stage();
 307         stage.setScene(scene);
 308         stage.show();
 309 
 310         Event.fireEvent(rect,
 311               new ScrollEvent(ScrollEvent.SCROLL,
 312                           50, 50,
 313                           50, 50,
 314                           false, false, false, false, true, false,
 315                           0.0, -50.0, 0.0, -50.0,
 316                           ScrollEvent.HorizontalTextScrollUnits.NONE, 10.0,
 317                           ScrollEvent.VerticalTextScrollUnits.NONE, 10.0,
 318                           0, null));
 319 
 320         /*
 321         ** did it work?
 322         */
 323         assertTrue(scrollPaneInner.getVvalue() > 0.0);
 324     }
 325 
 326 
 327     boolean sceneClicked = false;
 328     /*
 329     ** check if unconsumed MouseClicked events on a scrollPane reach it's parent.
 330     */
 331     @Test public void checkIfScrollPaneConsumesMouseClickedEvents() {
 332         ScrollPane scrollPaneInner = new ScrollPane();
 333         scrollPaneInner.setSkin(new com.sun.javafx.scene.control.skin.ScrollPaneSkin(scrollPaneInner));
 334         scrollPaneInner.setHbarPolicy(ScrollPane.ScrollBarPolicy.ALWAYS);
 335         scrollPaneInner.setVbarPolicy(ScrollPane.ScrollBarPolicy.ALWAYS);
 336         scrollPaneInner.setTranslateX(70);
 337         scrollPaneInner.setTranslateY(30);
 338         scrollPaneInner.setPrefWidth(100);
 339         scrollPaneInner.setPrefHeight(100);
 340         scrollPaneInner.setPannable(true);
 341 
 342         Scene scene = new Scene(new Group(), 400, 400);
 343         scene.setOnMouseClicked(me -> {
 344             sceneClicked = true;
 345         });
 346 
 347         ((Group) scene.getRoot()).getChildren().clear();
 348         ((Group) scene.getRoot()).getChildren().add(scrollPaneInner);
 349 
 350         Stage stage = new Stage();
 351         stage.setScene(scene);
 352         stage.show();
 353 
 354         Event.fireEvent(scrollPaneInner,
 355               new MouseEvent(MouseEvent.MOUSE_CLICKED, 50.0, 50.0, 50.0, 50.0,
 356                          MouseButton.PRIMARY, 1,
 357                          false, false, false, false, false,
 358                          true, false, false, false, false, null
 359                          ));
 360 
 361         /*
 362         ** did it work?
 363         */
 364         assertTrue(sceneClicked == true);
 365     }
 366 
 367     /*
 368     ** check if ScrollPane gets focus on unconsumed mousePressed
 369     */
 370     @Test public void checkIfScrollPaneFocusesPressedEvents() {
 371         scrollPane.setHbarPolicy(ScrollPane.ScrollBarPolicy.ALWAYS);
 372         scrollPane.setVbarPolicy(ScrollPane.ScrollBarPolicy.ALWAYS);
 373 
 374         StackPane sp = new StackPane();
 375         sp.setPrefWidth(80);
 376         sp.setPrefHeight(80);
 377 
 378         scrollPane.setContent(sp);
 379         scrollPane.setTranslateX(70);
 380         scrollPane.setTranslateY(30);
 381         scrollPane.setPrefWidth(100);
 382         scrollPane.setPrefHeight(100);
 383         scrollPane.setPannable(true);
 384 
 385         MouseEventGenerator generator = new MouseEventGenerator();
 386 
 387         Scene scene = new Scene(new Group(), 400, 400);
 388         ((Group) scene.getRoot()).getChildren().clear();
 389         ((Group) scene.getRoot()).getChildren().add(scrollPane);
 390         Stage stage = new Stage();
 391         stage.setScene(scene);
 392         stage.show();
 393 
 394         double originalValue = scrollPane.getVvalue();
 395 
 396         Event.fireEvent(sp, generator.generateMouseEvent(MouseEvent.MOUSE_PRESSED, 50, 50));
 397 
 398         /*
 399         ** did it work?
 400         */
 401         assertTrue(scene.getFocusOwner() == scrollPane);
 402     }
 403 
 404     /*
 405     ** check if ScrollPane gets focus on unconsumed mousePressed
 406     */
 407     @Test public void checkIfScrollPaneViewportIsRounded() {
 408         scrollPane.setHbarPolicy(ScrollPane.ScrollBarPolicy.ALWAYS);
 409         scrollPane.setVbarPolicy(ScrollPane.ScrollBarPolicy.ALWAYS);
 410 
 411         StackPane sp = new StackPane();
 412         sp.setPrefWidth(80);
 413         sp.setPrefHeight(80);
 414 
 415         scrollPane.setContent(sp);
 416         scrollPane.setTranslateX(70);
 417         scrollPane.setTranslateY(30);
 418         scrollPane.setPrefViewportWidth(100.5);
 419         scrollPane.setPrefHeight(100);
 420         scrollPane.setPannable(true);
 421 
 422         Scene scene = new Scene(new Group(), 400, 400);
 423         ((Group) scene.getRoot()).getChildren().clear();
 424         ((Group) scene.getRoot()).getChildren().add(scrollPane);
 425         Stage stage = new Stage();
 426         stage.setScene(scene);
 427         stage.show();
 428 
 429         /*
 430         ** did it work?
 431         */
 432         assertTrue(scrollPane.getViewportBounds().getWidth() == Math.ceil(100.5));
 433     }
 434 
 435     /*
 436     ** check ScrollBars missing if fitToHeight is true but height is > minHeight
 437     */
 438     @Test public void checkNoScrollbarsWhenFitToAndSizeOK() {
 439         scrollPane.setHbarPolicy(ScrollPane.ScrollBarPolicy.AS_NEEDED);
 440         scrollPane.setVbarPolicy(ScrollPane.ScrollBarPolicy.AS_NEEDED);
 441 
 442         StackPane sp = new StackPane();
 443         sp.setPrefWidth(80);
 444         sp.setPrefHeight(80);
 445         sp.setMinWidth(40);
 446         sp.setMinHeight(40);
 447 
 448         scrollPane.setPrefSize(50, 50);
 449         scrollPane.setContent(sp);
 450         scrollPane.setPannable(true);
 451         scrollPane.setFitToWidth(true);
 452         scrollPane.setFitToHeight(true);
 453 
 454         Scene scene = new Scene(new Group(), 400, 400);
 455         ((Group) scene.getRoot()).getChildren().clear();
 456         ((Group) scene.getRoot()).getChildren().add(scrollPane);
 457         Stage stage = new Stage();
 458         stage.setScene(scene);
 459         stage.show();
 460 
 461         /*
 462         ** did it work?
 463         */
 464         assertTrue(!skin.isHSBarVisible() & !skin.isVSBarVisible());
 465     }
 466 
 467     /*
 468     ** check if ScrollBars appear if fitToHeight is true but height is < minHeight
 469     */
 470     @Test public void checkIfScrollbarsWhenFitToHeightAndHeightLessMin() {
 471         scrollPane.setHbarPolicy(ScrollPane.ScrollBarPolicy.AS_NEEDED);
 472         scrollPane.setVbarPolicy(ScrollPane.ScrollBarPolicy.AS_NEEDED);
 473 
 474         StackPane sp = new StackPane();
 475         sp.setPrefWidth(80);
 476         sp.setPrefHeight(80);
 477         sp.setMinWidth(40);
 478         sp.setMinHeight(40);
 479 
 480         // see comments in checkIfScrollbarsWhenFitToWidthAndWidthLessMin for why width is 60
 481         scrollPane.setPrefSize(60, 30);
 482         scrollPane.setContent(sp);
 483         scrollPane.setPannable(true);
 484         scrollPane.setFitToWidth(true);
 485         scrollPane.setFitToHeight(true);
 486 
 487         Scene scene = new Scene(new Group(), 400, 400);
 488         ((Group) scene.getRoot()).getChildren().clear();
 489         ((Group) scene.getRoot()).getChildren().add(scrollPane);
 490         Stage stage = new Stage();
 491         stage.setScene(scene);
 492         stage.show();
 493 
 494         /*
 495         ** did it work?
 496         */
 497         assertTrue(!skin.isHSBarVisible() & skin.isVSBarVisible());
 498     }
 499 
 500     /*
 501     ** check if ScrollBars appear if fitToWidth is true but width is < minWidth
 502     */
 503     @Test public void checkIfScrollbarsWhenFitToWidthAndWidthLessMin() {
 504         scrollPane.setHbarPolicy(ScrollPane.ScrollBarPolicy.AS_NEEDED);
 505         scrollPane.setVbarPolicy(ScrollPane.ScrollBarPolicy.AS_NEEDED);
 506 
 507         StackPane sp = new StackPane();
 508         sp.setPrefWidth(80);
 509         sp.setPrefHeight(80);
 510         sp.setMinWidth(40);
 511         sp.setMinHeight(40);
 512 
 513         // set width < content minWidth, should get horizontal scroll bar
 514         // set height > content minHeight, should not get vertical scroll bar
 515         // Note that the scrollPane's height has to be big enough to fit both the
 516         // horizontal ScrollBar and the re-sized content. If the ScrollBar's height
 517         // is 16, then the scrollPane's prefHeight needs to be 16 plus the content's
 518         // minHeight of 40 plus one pixel (since the content and the ScrollBar don't
 519         // overlap), all of which adds up to 57. Originally, this test had the height
 520         // set to 50 which caused the vertical ScrollBar to be visible.
 521         scrollPane.setPrefSize(30, 60);
 522         scrollPane.setContent(sp);
 523         scrollPane.setPannable(true);
 524         scrollPane.setFitToWidth(true);
 525         scrollPane.setFitToHeight(true);
 526 
 527         Scene scene = new Scene(new Group(), 400, 400);
 528         ((Group) scene.getRoot()).getChildren().clear();
 529         ((Group) scene.getRoot()).getChildren().add(scrollPane);
 530         Stage stage = new Stage();
 531         stage.setScene(scene);
 532         stage.show();
 533 
 534         /*
 535         ** did it work?
 536         */
 537         assertTrue(skin.isHSBarVisible() & !skin.isVSBarVisible());
 538     }
 539 
 540     /*
 541     ** check if ScrollBars appear if fitToHeight & fitToWidth are true but height is < minHeight & width is < minWidth
 542     */
 543     @Test public void checkIfScrollbarsWhenBothFitToAndBothLessMin() {
 544         scrollPane.setHbarPolicy(ScrollPane.ScrollBarPolicy.AS_NEEDED);
 545         scrollPane.setVbarPolicy(ScrollPane.ScrollBarPolicy.AS_NEEDED);
 546 
 547         StackPane sp = new StackPane();
 548         sp.setPrefWidth(80);
 549         sp.setPrefHeight(80);
 550         sp.setMinWidth(40);
 551         sp.setMinHeight(40);
 552 
 553         scrollPane.setPrefSize(60, 30);
 554         scrollPane.setContent(sp);
 555         scrollPane.setPannable(true);
 556         scrollPane.setFitToWidth(true);
 557         scrollPane.setFitToHeight(true);
 558 
 559         Scene scene = new Scene(new Group(), 400, 400);
 560         ((Group) scene.getRoot()).getChildren().clear();
 561         ((Group) scene.getRoot()).getChildren().add(scrollPane);
 562         Stage stage = new Stage();
 563         stage.setScene(scene);
 564         stage.show();
 565 
 566         /*
 567         ** did it work?
 568         */
 569         assertTrue(!skin.isHSBarVisible() & skin.isVSBarVisible());
 570     }
 571 
 572     /*
 573     ** check if ScrollBars appear if fitToHeight & fitToWidth are true but height is < minHeight & width is < minWidth
 574     */
 575     @Test public void checkWeHandleNullContent() {
 576 
 577 
 578         scrollPane.setFitToWidth(true);
 579 
 580         Scene scene = new Scene(scrollPane);
 581 
 582         Stage stage = new Stage();
 583         stage.setScene(scene);
 584 
 585         stage.setWidth(600);
 586         stage.setHeight(600);
 587 
 588         stage.show();
 589 
 590     }
 591 
 592 
 593     /*
 594     ** check if 'reduced-size' scrollbars leave a gap
 595     ** at the right edge
 596     */
 597     @Test public void checkForScrollBarGaps() {
 598 
 599         HBox hbox1 = new HBox(20);
 600         VBox vbox1a = new VBox(10);
 601         vbox1a.getChildren().addAll(new Label("one"), new Button("two"), new CheckBox("three"), new RadioButton("four"), new Label("five"));
 602         VBox vbox1b = new VBox(10);
 603         vbox1b.getChildren().addAll(new Label("one"), new Button("two"), new CheckBox("three"), new RadioButton("four"), new Label("five"));
 604         hbox1.getChildren().addAll(vbox1a, vbox1b);
 605         scrollPane.setContent(hbox1);
 606         scrollPane.setStyle("-fx-background-color: red;-fx-border-color:green;");
 607         scrollPane.setFocusTraversable(false);
 608         scrollPane.setPrefSize(50, 50);
 609 
 610 
 611         Scene scene = new Scene(new Group(), 400, 400);
 612         ((Group) scene.getRoot()).getChildren().clear();
 613         ((Group) scene.getRoot()).getChildren().add(scrollPane);
 614         Stage stage = new Stage();
 615         stage.setScene(scene);
 616         stage.show();
 617 
 618 
 619         /*
 620         ** did it work?
 621         ** check that the scrollbar is right at the border of the scrollpane, and
 622         ** not at the padding.
 623         */
 624         ScrollPaneSkinMock skin = (ScrollPaneSkinMock) scrollPane.getSkin();
 625 
 626         double skinWidth = scrollPane.getWidth();
 627         double right = scrollPane.getPadding().getRight();
 628         // 1 px of padding is on the outside - see RT-21251
 629         double vsbPosAndWidth = (right >= 1 ? 1 : 0) + skin.getVsbX()+skin.getVsbWidth()+(scrollPane.getInsets().getRight() - right);
 630         assertEquals(skinWidth,  vsbPosAndWidth, 0.1);
 631 
 632         double skinHeight = scrollPane.getHeight();
 633         // 1 px of padding is on the outside - see RT-21251
 634         double bottom = scrollPane.getPadding().getBottom();
 635         double hsbPosAndHeight = (bottom >= 1 ? 1 : 0) + skin.getHsbY()+skin.getHsbHeight()+(scrollPane.getInsets().getBottom() - bottom);
 636         assertEquals(skinHeight,  hsbPosAndHeight, 0.1);
 637 
 638     }
 639 
 640     /*
 641     ** check if scrollPane content Horizontal position compensates for content size change
 642     ** ignored, as we do swipe through ScrollEvents.
 643     */
 644     @Ignore
 645     @Test public void checkIfSwipeDownEventsChangeAnything() {
 646 
 647         scrolled = false;
 648 
 649         Rectangle rect = new Rectangle(200, 200, 200, 200);
 650 
 651         final ScrollPane scrollPaneInner = new ScrollPane();
 652         scrollPaneInner.setSkin(new com.sun.javafx.scene.control.skin.ScrollPaneSkin(scrollPaneInner));
 653         scrollPaneInner.setPrefWidth(100);
 654         scrollPaneInner.setPrefHeight(100);
 655         scrollPaneInner.setPannable(true);
 656         scrollPaneInner.setContent(rect);
 657         scrollPaneInner.setOnSwipeUp(event -> {
 658             scrolled = true;
 659         });
 660         scrollPaneInner.setOnSwipeDown(event -> {
 661             scrolled = true;
 662         });
 663         scrollPaneInner.setOnSwipeLeft(event -> {
 664             scrolled = true;
 665         });
 666         scrollPaneInner.setOnSwipeRight(event -> {
 667             scrolled = true;
 668         });
 669         Pane pOuter = new Pane();
 670         pOuter.setPrefWidth(600);
 671         pOuter.setPrefHeight(600);
 672 
 673         Scene scene = new Scene(new Group(), 700, 700);
 674         ((Group) scene.getRoot()).getChildren().clear();
 675         ((Group) scene.getRoot()).getChildren().add(scrollPaneInner);
 676 
 677         Stage stage = new Stage();
 678         stage.setScene(scene);
 679         stage.show();
 680 
 681         Event.fireEvent(rect,
 682          new SwipeEvent(SwipeEvent.SWIPE_DOWN,
 683             0.0, -50.0,
 684             0.0, -50.0,
 685             false,
 686             false,
 687             false,
 688             false,
 689             false,
 690             1,
 691             null
 692             ));
 693 
 694         /*
 695         ** did it work?
 696         */
 697         assertTrue(scrollPaneInner.getVvalue() > 0.0);
 698     }
 699 
 700     /*
 701     ** check if scrollPane content Horizontal position compensates for content size change
 702     ** ignored, as we do swipe through ScrollEvents.
 703     */
 704     @Ignore
 705     @Test public void checkIfSwipeRightEventsChangeAnything() {
 706 
 707         scrolled = false;
 708 
 709         Rectangle rect = new Rectangle(200, 200, 200, 200);
 710 
 711         final ScrollPane scrollPaneInner = new ScrollPane();
 712         scrollPaneInner.setSkin(new com.sun.javafx.scene.control.skin.ScrollPaneSkin(scrollPaneInner));
 713         scrollPaneInner.setPrefWidth(100);
 714         scrollPaneInner.setPrefHeight(100);
 715         scrollPaneInner.setPannable(true);
 716         scrollPaneInner.setContent(rect);
 717         scrollPaneInner.setOnSwipeUp(event -> {
 718             scrolled = true;
 719         });
 720         scrollPaneInner.setOnSwipeDown(event -> {
 721             scrolled = true;
 722         });
 723         scrollPaneInner.setOnSwipeLeft(event -> {
 724             scrolled = true;
 725         });
 726         scrollPaneInner.setOnSwipeRight(event -> {
 727             scrolled = true;
 728         });
 729         Pane pOuter = new Pane();
 730         pOuter.setPrefWidth(600);
 731         pOuter.setPrefHeight(600);
 732 
 733         Scene scene = new Scene(new Group(), 700, 700);
 734         ((Group) scene.getRoot()).getChildren().clear();
 735         ((Group) scene.getRoot()).getChildren().add(scrollPaneInner);
 736 
 737         Stage stage = new Stage();
 738         stage.setScene(scene);
 739         stage.show();
 740 
 741         Event.fireEvent(rect,
 742             new SwipeEvent(SwipeEvent.SWIPE_RIGHT,
 743             0.0, -50.0,
 744             0.0, -50.0,
 745             false,
 746             false,
 747             false,
 748             false,
 749             false,
 750             1,
 751             null
 752             ));
 753 
 754          /*
 755          ** did it work?
 756          */
 757         assertTrue(scrollPaneInner.getHvalue() > 0.0);
 758     }
 759 
 760 
 761 
 762     public static final class ScrollPaneSkinMock extends ScrollPaneSkin {
 763         boolean propertyChanged = false;
 764         int propertyChangeCount = 0;
 765         public ScrollPaneSkinMock(ScrollPane scrollPane) {
 766             super(scrollPane);
 767         }
 768 
 769         @Override protected void handleControlPropertyChanged(String p) {
 770             super.handleControlPropertyChanged(p);
 771             propertyChanged = true;
 772             propertyChangeCount++;
 773         }
 774 
 775         boolean isHSBarVisible() {
 776             return hsb.isVisible();
 777         }
 778 
 779         boolean isVSBarVisible() {
 780             return vsb.isVisible();
 781         }
 782         double getVsbX() {
 783             return vsb.getLayoutX();
 784         }
 785         double getVsbWidth() {
 786             return vsb.getWidth();
 787         }
 788         double getHsbY() {
 789             return hsb.getLayoutY();
 790         }
 791         double getHsbHeight() {
 792             return hsb.getHeight();
 793         }
 794     }
 795 
 796     private static class MouseEventGenerator {
 797         private boolean primaryButtonDown = false;
 798 
 799         public MouseEvent generateMouseEvent(EventType<MouseEvent> type,
 800                 double x, double y) {
 801 
 802             MouseButton button = MouseButton.NONE;
 803             if (type == MouseEvent.MOUSE_PRESSED ||
 804                     type == MouseEvent.MOUSE_RELEASED ||
 805                     type == MouseEvent.MOUSE_DRAGGED) {
 806                 button = MouseButton.PRIMARY;
 807             }
 808 
 809             if (type == MouseEvent.MOUSE_PRESSED ||
 810                     type == MouseEvent.MOUSE_DRAGGED) {
 811                 primaryButtonDown = true;
 812             }
 813 
 814             if (type == MouseEvent.MOUSE_RELEASED) {
 815                 primaryButtonDown = false;
 816             }
 817 
 818             MouseEvent event = new MouseEvent(type, x, y, x, y, button,
 819                     1, false, false, false, false, false, primaryButtonDown,
 820                     false, false, false, false, null);
 821 
 822             return event;
 823         }
 824     }
 825 }