1 /* 2 * Copyright (c) 2010, 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 javafx.scene.control; 27 28 import java.util.ArrayList; 29 import java.util.Collections; 30 import java.util.List; 31 32 import javafx.beans.DefaultProperty; 33 import javafx.beans.property.BooleanProperty; 34 import javafx.beans.property.DoubleProperty; 35 import javafx.beans.property.ObjectProperty; 36 import javafx.beans.property.SimpleDoubleProperty; 37 import javafx.beans.property.SimpleObjectProperty; 38 import javafx.beans.value.WritableValue; 39 import javafx.css.CssMetaData; 40 import javafx.css.PseudoClass; 41 import javafx.css.StyleableBooleanProperty; 42 import javafx.css.StyleableObjectProperty; 43 import javafx.css.StyleableProperty; 44 import javafx.geometry.BoundingBox; 45 import javafx.geometry.Bounds; 46 import javafx.scene.AccessibleAttribute; 47 import javafx.scene.AccessibleRole; 48 import javafx.scene.Node; 49 50 import com.sun.javafx.css.converters.BooleanConverter; 51 import com.sun.javafx.css.converters.EnumConverter; 52 import com.sun.javafx.scene.control.skin.ScrollPaneSkin; 53 54 import javafx.css.Styleable; 55 56 /** 57 * A Control that provides a scrolled, clipped viewport of its contents. It 58 * allows the user to scroll the content around either directly (panning) or 59 * by using scroll bars. The ScrollPane allows specification of the scroll 60 * bar policy, which determines when scroll bars are displayed: always, never, 61 * or only when they are needed. The scroll bar policy can be specified 62 * independently for the horizontal and vertical scroll bars. 63 * <p> 64 * The ScrollPane allows the application to set the current, minimum, and 65 * maximum values for positioning the contents in the horizontal and 66 * vertical directions. These values are mapped proportionally onto the 67 * {@link javafx.scene.Node#layoutBoundsProperty layoutBounds} of the contained node. 68 * <p> 69 * ScrollPane layout calculations are based on the layoutBounds rather than 70 * the boundsInParent (visual bounds) of the scroll node. 71 * If an application wants the scrolling to be based on the visual bounds 72 * of the node (for scaled content etc.), they need to wrap the scroll 73 * node in a Group. 74 * <p> 75 * ScrollPane sets focusTraversable to false. 76 * </p> 77 * 78 * <p> 79 * This example creates a ScrollPane, which contains a Rectangle : 80 * <pre><code> 81 * import javafx.scene.control.ScrollPane; 82 * import javafx.scene.shape.Rectangle; 83 * 84 * Rectangle rect = new Rectangle(200, 200, Color.RED); 85 * ScrollPane s1 = new ScrollPane(); 86 * s1.setPrefSize(120, 120); 87 * s1.setContent(rect); 88 * </code></pre> 89 * 90 * Implementation of ScrollPane According to JavaFX UI Control API Specification 91 * @since JavaFX 2.0 92 */ 93 @DefaultProperty("content") 94 public class ScrollPane extends Control { 95 96 /*************************************************************************** 97 * * 98 * Constructors * 99 * * 100 **************************************************************************/ 101 102 /** 103 * Creates a new ScrollPane. 104 */ 105 public ScrollPane() { 106 getStyleClass().setAll(DEFAULT_STYLE_CLASS); 107 setAccessibleRole(AccessibleRole.SCROLL_PANE); 108 // focusTraversable is styleable through css. Calling setFocusTraversable 109 // makes it look to css like the user set the value and css will not 110 // override. Initializing focusTraversable by calling applyStyle with 111 // null StyleOrigin ensures that css will be able to override the value. 112 ((StyleableProperty<Boolean>)(WritableValue<Boolean>)focusTraversableProperty()).applyStyle(null, Boolean.FALSE); 113 } 114 115 /** 116 * Creates a new ScrollPane. 117 * @param content the initial content for the ScrollPane 118 * @since JavaFX 8.0 119 */ 120 public ScrollPane(Node content) { 121 this(); 122 setContent(content); 123 } 124 125 /*************************************************************************** 126 * * 127 * Properties * 128 * * 129 **************************************************************************/ 130 /** 131 * Specifies the policy for showing the horizontal scroll bar. 132 */ 133 private ObjectProperty<ScrollBarPolicy> hbarPolicy; 134 public final void setHbarPolicy(ScrollBarPolicy value) { 135 hbarPolicyProperty().set(value); 136 } 137 138 public final ScrollBarPolicy getHbarPolicy() { 139 return hbarPolicy == null ? ScrollBarPolicy.AS_NEEDED : hbarPolicy.get(); 140 } 141 142 public final ObjectProperty<ScrollBarPolicy> hbarPolicyProperty() { 143 if (hbarPolicy == null) { 144 hbarPolicy = new StyleableObjectProperty<ScrollBarPolicy>(ScrollBarPolicy.AS_NEEDED) { 145 146 @Override 147 public CssMetaData<ScrollPane,ScrollBarPolicy> getCssMetaData() { 148 return StyleableProperties.HBAR_POLICY; 149 } 150 151 @Override 152 public Object getBean() { 153 return ScrollPane.this; 154 } 155 156 @Override 157 public String getName() { 158 return "hbarPolicy"; 159 } 160 }; 161 } 162 return hbarPolicy; 163 } 164 /** 165 * Specifies the policy for showing the vertical scroll bar. 166 */ 167 private ObjectProperty<ScrollBarPolicy> vbarPolicy; 168 public final void setVbarPolicy(ScrollBarPolicy value) { 169 vbarPolicyProperty().set(value); 170 } 171 172 public final ScrollBarPolicy getVbarPolicy() { 173 return vbarPolicy == null ? ScrollBarPolicy.AS_NEEDED : vbarPolicy.get(); 174 } 175 176 public final ObjectProperty<ScrollBarPolicy> vbarPolicyProperty() { 177 if (vbarPolicy == null) { 178 vbarPolicy = new StyleableObjectProperty<ScrollBarPolicy>(ScrollBarPolicy.AS_NEEDED) { 179 180 @Override 181 public CssMetaData<ScrollPane,ScrollBarPolicy> getCssMetaData() { 182 return StyleableProperties.VBAR_POLICY; 183 } 184 185 @Override 186 public Object getBean() { 187 return ScrollPane.this; 188 } 189 190 @Override 191 public String getName() { 192 return "vbarPolicy"; 193 } 194 }; 195 } 196 return vbarPolicy; 197 } 198 /** 199 * The node used as the content of this ScrollPane. 200 */ 201 private ObjectProperty<Node> content; 202 203 public final void setContent(Node value) { 204 contentProperty().set(value); 205 } 206 207 public final Node getContent() { 208 return content == null ? null : content.get(); 209 } 210 211 public final ObjectProperty<Node> contentProperty() { 212 if (content == null) { 213 content = new SimpleObjectProperty<Node>(this, "content"); 214 } 215 return content; 216 } 217 /** 218 * The current horizontal scroll position of the ScrollPane. This value 219 * may be set by the application to scroll the view programatically. 220 * The ScrollPane will update this value whenever the viewport is 221 * scrolled or panned by the user. This value must always be within 222 * the range of {@link #hminProperty hmin} to {@link #hmaxProperty hmax}. When {@link #hvalueProperty hvalue} 223 * equals {@link #hminProperty hmin}, the contained node is positioned so that 224 * its layoutBounds {@link javafx.geometry.Bounds#getMinX minX} is visible. When {@link #hvalueProperty hvalue} 225 * equals {@link #hmaxProperty hmax}, the contained node is positioned so that its 226 * layoutBounds {@link javafx.geometry.Bounds#getMaxX maxX} is visible. When {@link #hvalueProperty hvalue} is between 227 * {@link #hminProperty hmin} and {@link #hmaxProperty hmax}, the contained node is positioned 228 * proportionally between layoutBounds {@link javafx.geometry.Bounds#getMinX minX} and 229 * layoutBounds {@link javafx.geometry.Bounds#getMaxX maxX}. 230 */ 231 private DoubleProperty hvalue; 232 233 public final void setHvalue(double value) { 234 hvalueProperty().set(value); 235 } 236 237 public final double getHvalue() { 238 return hvalue == null ? 0.0 : hvalue.get(); 239 } 240 241 public final DoubleProperty hvalueProperty() { 242 if (hvalue == null) { 243 hvalue = new SimpleDoubleProperty(this, "hvalue"); 244 } 245 return hvalue; 246 } 247 /** 248 * The current vertical scroll position of the ScrollPane. This value 249 * may be set by the application to scroll the view programatically. 250 * The ScrollPane will update this value whenever the viewport is 251 * scrolled or panned by the user. This value must always be within 252 * the range of {@link #vminProperty vmin} to {@link #vmaxProperty vmax}. When {@link #vvalueProperty vvalue} 253 * equals {@link #vminProperty vmin}, the contained node is positioned so that 254 * its layoutBounds {@link javafx.geometry.Bounds#getMinY minY} is visible. When {@link #vvalueProperty vvalue} 255 * equals {@link #vmaxProperty vmax}, the contained node is positioned so that its 256 * layoutBounds {@link javafx.geometry.Bounds#getMaxY maxY} is visible. When {@link #vvalueProperty vvalue} is between 257 * {@link #vminProperty vmin} and {@link #vmaxProperty vmax}, the contained node is positioned 258 * proportionally between layoutBounds {@link javafx.geometry.Bounds#getMinY minY} and 259 * layoutBounds {@link javafx.geometry.Bounds#getMaxY maxY}. 260 */ 261 private DoubleProperty vvalue; 262 263 public final void setVvalue(double value) { 264 vvalueProperty().set(value); 265 } 266 267 public final double getVvalue() { 268 return vvalue == null ? 0.0 : vvalue.get(); 269 } 270 271 public final DoubleProperty vvalueProperty() { 272 if (vvalue == null) { 273 vvalue = new SimpleDoubleProperty(this, "vvalue"); 274 } 275 return vvalue; 276 } 277 /** 278 * The minimum allowable {@link #hvalueProperty hvalue} for this ScrollPane. 279 * Default value is 0. 280 */ 281 private DoubleProperty hmin; 282 283 public final void setHmin(double value) { 284 hminProperty().set(value); 285 } 286 287 public final double getHmin() { 288 return hmin == null ? 0.0F : hmin.get(); 289 } 290 291 public final DoubleProperty hminProperty() { 292 if (hmin == null) { 293 hmin = new SimpleDoubleProperty(this, "hmin", 0.0); 294 } 295 return hmin; 296 } 297 /** 298 * The minimum allowable {@link #hvalueProperty vvalue} for this ScrollPane. 299 * Default value is 0. 300 */ 301 private DoubleProperty vmin; 302 303 public final void setVmin(double value) { 304 vminProperty().set(value); 305 } 306 307 public final double getVmin() { 308 return vmin == null ? 0.0F : vmin.get(); 309 } 310 311 public final DoubleProperty vminProperty() { 312 if (vmin == null) { 313 vmin = new SimpleDoubleProperty(this, "vmin", 0.0); 314 } 315 return vmin; 316 } 317 /** 318 * The maximum allowable {@link #hvalueProperty hvalue} for this ScrollPane. 319 * Default value is 1. 320 */ 321 private DoubleProperty hmax; 322 323 public final void setHmax(double value) { 324 hmaxProperty().set(value); 325 } 326 327 public final double getHmax() { 328 return hmax == null ? 1.0F : hmax.get(); 329 } 330 331 public final DoubleProperty hmaxProperty() { 332 if (hmax == null) { 333 hmax = new SimpleDoubleProperty(this, "hmax", 1.0); 334 } 335 return hmax; 336 } 337 /** 338 * The maximum allowable {@link #hvalueProperty vvalue} for this ScrollPane. 339 * Default value is 1. 340 */ 341 private DoubleProperty vmax; 342 343 public final void setVmax(double value) { 344 vmaxProperty().set(value); 345 } 346 347 public final double getVmax() { 348 return vmax == null ? 1.0F : vmax.get(); 349 } 350 351 public final DoubleProperty vmaxProperty() { 352 if (vmax == null) { 353 vmax = new SimpleDoubleProperty(this, "vmax", 1.0); 354 } 355 return vmax; 356 } 357 /** 358 * If true and if the contained node is a Resizable, then the node will be 359 * kept resized to match the width of the ScrollPane's viewport. If the 360 * contained node is not a Resizable, this value is ignored. 361 */ 362 private BooleanProperty fitToWidth; 363 public final void setFitToWidth(boolean value) { 364 fitToWidthProperty().set(value); 365 } 366 public final boolean isFitToWidth() { 367 return fitToWidth == null ? false : fitToWidth.get(); 368 } 369 public final BooleanProperty fitToWidthProperty() { 370 if (fitToWidth == null) { 371 fitToWidth = new StyleableBooleanProperty(false) { 372 @Override public void invalidated() { 373 pseudoClassStateChanged(FIT_TO_WIDTH_PSEUDOCLASS_STATE, get()); 374 } 375 376 @Override 377 public CssMetaData<ScrollPane,Boolean> getCssMetaData() { 378 return StyleableProperties.FIT_TO_WIDTH; 379 } 380 381 @Override 382 public Object getBean() { 383 return ScrollPane.this; 384 } 385 386 @Override 387 public String getName() { 388 return "fitToWidth"; 389 } 390 }; 391 } 392 return fitToWidth; 393 } 394 /** 395 * If true and if the contained node is a Resizable, then the node will be 396 * kept resized to match the height of the ScrollPane's viewport. If the 397 * contained node is not a Resizable, this value is ignored. 398 */ 399 private BooleanProperty fitToHeight; 400 public final void setFitToHeight(boolean value) { 401 fitToHeightProperty().set(value); 402 } 403 public final boolean isFitToHeight() { 404 return fitToHeight == null ? false : fitToHeight.get(); 405 } 406 public final BooleanProperty fitToHeightProperty() { 407 if (fitToHeight == null) { 408 fitToHeight = new StyleableBooleanProperty(false) { 409 @Override public void invalidated() { 410 pseudoClassStateChanged(FIT_TO_HEIGHT_PSEUDOCLASS_STATE, get()); 411 } 412 413 @Override 414 public CssMetaData<ScrollPane,Boolean> getCssMetaData() { 415 return StyleableProperties.FIT_TO_HEIGHT; 416 } 417 418 @Override 419 public Object getBean() { 420 return ScrollPane.this; 421 } 422 423 @Override 424 public String getName() { 425 return "fitToHeight"; 426 } 427 }; 428 } 429 return fitToHeight; 430 } 431 /** 432 * Specifies whether the user should be able to pan the viewport by using 433 * the mouse. If mouse events reach the ScrollPane (that is, if mouse 434 * events are not blocked by the contained node or one of its children) 435 * then {@link #pannableProperty pannable} is consulted to determine if the events should be 436 * used for panning. 437 */ 438 private BooleanProperty pannable; 439 public final void setPannable(boolean value) { 440 pannableProperty().set(value); 441 } 442 public final boolean isPannable() { 443 return pannable == null ? false : pannable.get(); 444 } 445 public final BooleanProperty pannableProperty() { 446 if (pannable == null) { 447 pannable = new StyleableBooleanProperty(false) { 448 @Override public void invalidated() { 449 pseudoClassStateChanged(PANNABLE_PSEUDOCLASS_STATE, get()); 450 } 451 452 @Override 453 public CssMetaData<ScrollPane,Boolean> getCssMetaData() { 454 return StyleableProperties.PANNABLE; 455 } 456 457 @Override 458 public Object getBean() { 459 return ScrollPane.this; 460 } 461 462 @Override 463 public String getName() { 464 return "pannable"; 465 } 466 }; 467 } 468 return pannable; 469 } 470 471 472 /** 473 * Specify the perferred width of the ScrollPane Viewport. 474 * This is the width that will be available to the content node. 475 * The overall width of the ScrollPane is the ViewportWidth + padding 476 */ 477 private DoubleProperty prefViewportWidth; 478 479 public final void setPrefViewportWidth(double value) { 480 prefViewportWidthProperty().set(value); 481 } 482 483 public final double getPrefViewportWidth() { 484 return prefViewportWidth == null ? 0.0F : prefViewportWidth.get(); 485 } 486 487 public final DoubleProperty prefViewportWidthProperty() { 488 if (prefViewportWidth == null) { 489 prefViewportWidth = new SimpleDoubleProperty(this, "prefViewportWidth"); 490 } 491 return prefViewportWidth; 492 } 493 494 /** 495 * Specify the preferred height of the ScrollPane Viewport. 496 * This is the height that will be available to the content node. 497 * The overall height of the ScrollPane is the ViewportHeight + padding 498 */ 499 private DoubleProperty prefViewportHeight; 500 501 public final void setPrefViewportHeight(double value) { 502 prefViewportHeightProperty().set(value); 503 } 504 505 public final double getPrefViewportHeight() { 506 return prefViewportHeight == null ? 0.0F : prefViewportHeight.get(); 507 } 508 509 public final DoubleProperty prefViewportHeightProperty() { 510 if (prefViewportHeight == null) { 511 prefViewportHeight = new SimpleDoubleProperty(this, "prefViewportHeight"); 512 } 513 return prefViewportHeight; 514 } 515 516 517 /** 518 * Specify the minimum width of the ScrollPane Viewport. 519 * This is the width that will be available to the content node. 520 * 521 * @since JavaFX 8u40 522 * @see #prefViewportWidthProperty() 523 */ 524 private DoubleProperty minViewportWidth; 525 526 public final void setMinViewportWidth(double value) { 527 minViewportWidthProperty().set(value); 528 } 529 530 public final double getMinViewportWidth() { 531 return minViewportWidth == null ? 0.0F : minViewportWidth.get(); 532 } 533 534 public final DoubleProperty minViewportWidthProperty() { 535 if (minViewportWidth == null) { 536 minViewportWidth = new SimpleDoubleProperty(this, "minViewportWidth"); 537 } 538 return minViewportWidth; 539 } 540 541 /** 542 * Specify the minimum height of the ScrollPane Viewport. 543 * This is the height that will be available to the content node. 544 * 545 * @since JavaFX 8u40 546 * @see #prefViewportHeightProperty() 547 */ 548 private DoubleProperty minViewportHeight; 549 550 public final void setMinViewportHeight(double value) { 551 minViewportHeightProperty().set(value); 552 } 553 554 public final double getMinViewportHeight() { 555 return minViewportHeight == null ? 0.0F : minViewportHeight.get(); 556 } 557 558 public final DoubleProperty minViewportHeightProperty() { 559 if (minViewportHeight == null) { 560 minViewportHeight = new SimpleDoubleProperty(this, "minViewportHeight"); 561 } 562 return minViewportHeight; 563 } 564 565 /** 566 * The actual Bounds of the ScrollPane Viewport. 567 * This is the Bounds of the content node. 568 */ 569 private ObjectProperty<Bounds> viewportBounds; 570 571 public final void setViewportBounds(Bounds value) { 572 viewportBoundsProperty().set(value); 573 } 574 575 public final Bounds getViewportBounds() { 576 return viewportBounds == null ? new BoundingBox(0,0,0,0) : viewportBounds.get(); 577 } 578 579 public final ObjectProperty<Bounds> viewportBoundsProperty() { 580 if (viewportBounds == null) { 581 viewportBounds = new SimpleObjectProperty<Bounds>(this, "viewportBounds", new BoundingBox(0,0,0,0)); 582 } 583 return viewportBounds; 584 } 585 586 587 /*************************************************************************** 588 * * 589 * Methods * 590 * * 591 **************************************************************************/ 592 593 /* 594 * TODO The unit increment and block increment variables have been 595 * removed from the public API. These are intended to be mapped to 596 * the corresponding variables of the scrollbars. However, the problem 597 * is that they are specified in terms of the logical corrdinate space 598 * of the ScrollPane (that is, [hmin..hmax] by [vmin..vmax]. This is 599 * incorrect. Scrolling is a user action and should properly be based 600 * on how much of the content is visible, not on some abstract 601 * coordinate space. At some later date we may add a finer-grained 602 * API to allow applications to control this. Meanwhile, the skin should 603 * set unit and block increments for the scroll bars to do something 604 * reasonable based on the viewport size, e.g. the block increment 605 * should scroll 90% of the pixel size of the viewport, and the unit 606 * increment should scroll 10% of the pixel size of the viewport. 607 */ 608 609 /** 610 * Defines the horizontal unit increment amount. Typically this is used when clicking on the 611 * increment or decrement arrow buttons of the horizontal scroll bar. 612 */ 613 // public var hunitIncrement:Number = 20.0; 614 615 /** 616 * Defines the vertical unit increment amount. Typically this is used when clicking on the 617 * increment or decrement arrow buttons of the vertical scroll bar. 618 */ 619 // public var vunitIncrement:Number = 20.0; 620 621 /** 622 * Defines the horizontal block increment amount. Typically this is used when clicking on the 623 * track of the scroll bar. 624 */ 625 // public var hblockIncrement:Number = -1; 626 627 /** 628 * Defines the vertical block increment amount. Typically this is used when clicking on the 629 * track of the scroll bar. 630 */ 631 // public var vblockIncrement:Number = -1; 632 633 /** {@inheritDoc} */ 634 @Override protected Skin<?> createDefaultSkin() { 635 return new ScrollPaneSkin(this); 636 } 637 638 /*************************************************************************** 639 * * 640 * Stylesheet Handling * 641 * * 642 **************************************************************************/ 643 644 /** 645 * Initialize the style class to 'scroll-view'. 646 * 647 * This is the selector class from which CSS can be used to style 648 * this control. 649 */ 650 private static final String DEFAULT_STYLE_CLASS = "scroll-pane"; 651 652 /** 653 * @treatAsPrivate 654 */ 655 private static class StyleableProperties { 656 private static final CssMetaData<ScrollPane,ScrollBarPolicy> HBAR_POLICY = 657 new CssMetaData<ScrollPane,ScrollBarPolicy>("-fx-hbar-policy", 658 new EnumConverter<ScrollBarPolicy>(ScrollBarPolicy.class), 659 ScrollBarPolicy.AS_NEEDED){ 660 661 @Override 662 public boolean isSettable(ScrollPane n) { 663 return n.hbarPolicy == null || !n.hbarPolicy.isBound(); 664 } 665 666 @Override 667 public StyleableProperty<ScrollBarPolicy> getStyleableProperty(ScrollPane n) { 668 return (StyleableProperty<ScrollBarPolicy>)(WritableValue<ScrollBarPolicy>)n.hbarPolicyProperty(); 669 } 670 }; 671 672 private static final CssMetaData<ScrollPane,ScrollBarPolicy> VBAR_POLICY = 673 new CssMetaData<ScrollPane,ScrollBarPolicy>("-fx-vbar-policy", 674 new EnumConverter<ScrollBarPolicy>(ScrollBarPolicy.class), 675 ScrollBarPolicy.AS_NEEDED){ 676 677 @Override 678 public boolean isSettable(ScrollPane n) { 679 return n.vbarPolicy == null || !n.vbarPolicy.isBound(); 680 } 681 682 @Override 683 public StyleableProperty<ScrollBarPolicy> getStyleableProperty(ScrollPane n) { 684 return (StyleableProperty<ScrollBarPolicy>)(WritableValue<ScrollBarPolicy>)n.vbarPolicyProperty(); 685 } 686 }; 687 688 private static final CssMetaData<ScrollPane,Boolean> FIT_TO_WIDTH = 689 new CssMetaData<ScrollPane, Boolean>("-fx-fit-to-width", 690 BooleanConverter.getInstance(), Boolean.FALSE){ 691 692 @Override 693 public boolean isSettable(ScrollPane n) { 694 return n.fitToWidth == null || !n.fitToWidth.isBound(); 695 } 696 697 @Override 698 public StyleableProperty<Boolean> getStyleableProperty(ScrollPane n) { 699 return (StyleableProperty<Boolean>)(WritableValue<Boolean>)n.fitToWidthProperty(); 700 } 701 }; 702 703 private static final CssMetaData<ScrollPane,Boolean> FIT_TO_HEIGHT = 704 new CssMetaData<ScrollPane, Boolean>("-fx-fit-to-height", 705 BooleanConverter.getInstance(), Boolean.FALSE){ 706 707 @Override 708 public boolean isSettable(ScrollPane n) { 709 return n.fitToHeight == null || !n.fitToHeight.isBound(); 710 } 711 712 @Override 713 public StyleableProperty<Boolean> getStyleableProperty(ScrollPane n) { 714 return (StyleableProperty<Boolean>)(WritableValue<Boolean>)n.fitToHeightProperty(); 715 } 716 }; 717 718 private static final CssMetaData<ScrollPane,Boolean> PANNABLE = 719 new CssMetaData<ScrollPane, Boolean>("-fx-pannable", 720 BooleanConverter.getInstance(), Boolean.FALSE){ 721 722 @Override 723 public boolean isSettable(ScrollPane n) { 724 return n.pannable == null || !n.pannable.isBound(); 725 } 726 727 @Override 728 public StyleableProperty<Boolean> getStyleableProperty(ScrollPane n) { 729 return (StyleableProperty<Boolean>)(WritableValue<Boolean>)n.pannableProperty(); 730 } 731 }; 732 733 private static final List<CssMetaData<? extends Styleable, ?>> STYLEABLES; 734 static { 735 final List<CssMetaData<? extends Styleable, ?>> styleables = 736 new ArrayList<CssMetaData<? extends Styleable, ?>>(Control.getClassCssMetaData()); 737 styleables.add(HBAR_POLICY); 738 styleables.add(VBAR_POLICY); 739 styleables.add(FIT_TO_WIDTH); 740 styleables.add(FIT_TO_HEIGHT); 741 styleables.add(PANNABLE); 742 STYLEABLES = Collections.unmodifiableList(styleables); 743 } 744 } 745 746 /** 747 * @return The CssMetaData associated with this class, which may include the 748 * CssMetaData of its super classes. 749 * @since JavaFX 8.0 750 */ 751 public static List<CssMetaData<? extends Styleable, ?>> getClassCssMetaData() { 752 return StyleableProperties.STYLEABLES; 753 } 754 755 /** 756 * {@inheritDoc} 757 * @since JavaFX 8.0 758 */ 759 @Override 760 public List<CssMetaData<? extends Styleable, ?>> getControlCssMetaData() { 761 return getClassCssMetaData(); 762 } 763 764 private static final PseudoClass PANNABLE_PSEUDOCLASS_STATE = 765 PseudoClass.getPseudoClass("pannable"); 766 private static final PseudoClass FIT_TO_WIDTH_PSEUDOCLASS_STATE = 767 PseudoClass.getPseudoClass("fitToWidth"); 768 private static final PseudoClass FIT_TO_HEIGHT_PSEUDOCLASS_STATE = 769 PseudoClass.getPseudoClass("fitToHeight"); 770 771 /** 772 * Most Controls return true for focusTraversable, so Control overrides 773 * this method to return true, but ScrollPane returns false for 774 * focusTraversable's initial value; hence the override of the override. 775 * This method is called from CSS code to get the correct initial value. 776 * @treatAsPrivate implementation detail 777 */ 778 @Deprecated @Override 779 protected /*do not make final*/ Boolean impl_cssGetFocusTraversableInitialValue() { 780 return Boolean.FALSE; 781 } 782 783 784 /*************************************************************************** 785 * * 786 * Accessibility handling * 787 * * 788 **************************************************************************/ 789 790 @Override 791 public Object queryAccessibleAttribute(AccessibleAttribute attribute, Object... parameters) { 792 switch (attribute) { 793 case CONTENTS: return getContent(); 794 default: return super.queryAccessibleAttribute(attribute, parameters); 795 } 796 } 797 798 799 /*************************************************************************** 800 * * 801 * Support classes * 802 * * 803 **************************************************************************/ 804 805 /** 806 * An enumeration denoting the policy to be used by a scrollable 807 * Control in deciding whether to show a scroll bar. 808 * @since JavaFX 2.0 809 */ 810 public static enum ScrollBarPolicy { 811 /** 812 * Indicates that a scroll bar should never be shown. 813 */ 814 NEVER, 815 /** 816 * Indicates that a scroll bar should always be shown. 817 */ 818 ALWAYS, 819 /** 820 * Indicates that a scroll bar should be shown when required. 821 */ 822 AS_NEEDED 823 } 824 825 826 827 }