1 /* 2 * Copyright (c) 2010, 2016, 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.property.BooleanProperty; 33 import javafx.beans.property.DoubleProperty; 34 import javafx.beans.property.DoublePropertyBase; 35 import javafx.beans.property.IntegerProperty; 36 import javafx.beans.property.ObjectProperty; 37 import javafx.beans.property.SimpleBooleanProperty; 38 import javafx.beans.property.SimpleObjectProperty; 39 import javafx.beans.value.WritableValue; 40 import javafx.geometry.Orientation; 41 import javafx.scene.AccessibleAction; 42 import javafx.scene.AccessibleAttribute; 43 import javafx.scene.AccessibleRole; 44 import javafx.util.StringConverter; 45 46 import com.sun.javafx.util.Utils; 47 48 import javafx.css.CssMetaData; 49 import javafx.css.PseudoClass; 50 import javafx.css.StyleableBooleanProperty; 51 import javafx.css.StyleableDoubleProperty; 52 import javafx.css.StyleableIntegerProperty; 53 import javafx.css.StyleableObjectProperty; 54 55 import javafx.css.converter.BooleanConverter; 56 import javafx.css.converter.EnumConverter; 57 import javafx.css.converter.SizeConverter; 58 import javafx.scene.control.skin.SliderSkin; 59 60 import javafx.css.Styleable; 61 import javafx.css.StyleableProperty; 62 63 /** 64 * The Slider Control is used to display a continuous or discrete range of 65 * valid numeric choices and allows the user to interact with the control. It is 66 * typically represented visually as having a "track" and a "knob" or "thumb" 67 * which is dragged within the track. The Slider can optionally show tick marks 68 * and labels indicating the different slider position values. 69 * <p> 70 * The three fundamental variables of the slider are <code>min</code>, 71 * <code>max</code>, and <code>value</code>. The <code>value</code> should always 72 * be a number within the range defined by <code>min</code> and 73 * <code>max</code>. <code>min</code> should always be less than or equal to 74 * <code>max</code> (although a slider who's <code>min</code> and 75 * <code>max</code> are equal is a degenerate case that makes no sense). 76 * <code>min</code> defaults to 0, whereas <code>max</code> defaults to 100. 77 * <p> 78 * This first example creates a slider who's range, or span, goes from 0 to 1, 79 * and who's value defaults to .5: 80 * 81 * <pre> 82 * import javafx.scene.control.Slider; 83 * 84 * Slider slider = new Slider(0, 1, 0.5); 85 * </pre> 86 * 87 * <p> 88 * This next example shows a slider with customized tick marks and tick mark 89 * labels, which also spans from 0 to 1: 90 * 91 * <pre> 92 * import javafx.scene.control.Slider; 93 * 94 * Slider slider = new Slider(0, 1, 0.5); 95 * slider.setShowTickMarks(true); 96 * slider.setShowTickLabels(true); 97 * slider.setMajorTickUnit(0.25f); 98 * slider.setBlockIncrement(0.1f); 99 * </pre> 100 * @since JavaFX 2.0 101 */ 102 public class Slider extends Control { 103 104 /** 105 * Creates a default Slider instance. 106 */ 107 public Slider() { 108 initialize(); 109 } 110 111 /** 112 * Constructs a Slider control with the specified slider min, max and current value values. 113 * @param min Slider minimum value 114 * @param max Slider maximum value 115 * @param value Slider current value 116 */ 117 public Slider(double min, double max, double value) { 118 setMax(max); 119 setMin(min); 120 setValue(value); 121 adjustValues(); 122 initialize(); 123 } 124 125 private void initialize() { 126 //Initialize the style class to be 'slider'. 127 getStyleClass().setAll(DEFAULT_STYLE_CLASS); 128 setAccessibleRole(AccessibleRole.SLIDER); 129 } 130 /** 131 * The maximum value represented by this Slider. This must be a 132 * value greater than {@link #minProperty() min}. 133 */ 134 private DoubleProperty max; 135 public final void setMax(double value) { 136 maxProperty().set(value); 137 } 138 139 public final double getMax() { 140 return max == null ? 100 : max.get(); 141 } 142 143 public final DoubleProperty maxProperty() { 144 if (max == null) { 145 max = new DoublePropertyBase(100) { 146 @Override protected void invalidated() { 147 if (get() < getMin()) { 148 setMin(get()); 149 } 150 adjustValues(); 151 notifyAccessibleAttributeChanged(AccessibleAttribute.MAX_VALUE); 152 } 153 154 @Override 155 public Object getBean() { 156 return Slider.this; 157 } 158 159 @Override 160 public String getName() { 161 return "max"; 162 } 163 }; 164 } 165 return max; 166 } 167 /** 168 * The minimum value represented by this Slider. This must be a 169 * value less than {@link #maxProperty() max}. 170 */ 171 private DoubleProperty min; 172 public final void setMin(double value) { 173 minProperty().set(value); 174 } 175 176 public final double getMin() { 177 return min == null ? 0 : min.get(); 178 } 179 180 public final DoubleProperty minProperty() { 181 if (min == null) { 182 min = new DoublePropertyBase(0) { 183 @Override protected void invalidated() { 184 if (get() > getMax()) { 185 setMax(get()); 186 } 187 adjustValues(); 188 notifyAccessibleAttributeChanged(AccessibleAttribute.MIN_VALUE); 189 } 190 191 @Override 192 public Object getBean() { 193 return Slider.this; 194 } 195 196 @Override 197 public String getName() { 198 return "min"; 199 } 200 }; 201 } 202 return min; 203 } 204 /** 205 * The current value represented by this Slider. This value must 206 * always be between {@link #minProperty() min} and {@link #maxProperty() max}, 207 * inclusive. If it is ever out of bounds either due to {@code min} or 208 * {@code max} changing or due to itself being changed, then it will 209 * be clamped to always remain valid. 210 */ 211 private DoubleProperty value; 212 public final void setValue(double value) { 213 if (!valueProperty().isBound()) valueProperty().set(value); 214 } 215 216 public final double getValue() { 217 return value == null ? 0 : value.get(); 218 } 219 220 public final DoubleProperty valueProperty() { 221 if (value == null) { 222 value = new DoublePropertyBase(0) { 223 @Override protected void invalidated() { 224 adjustValues(); 225 notifyAccessibleAttributeChanged(AccessibleAttribute.VALUE); 226 } 227 228 @Override 229 public Object getBean() { 230 return Slider.this; 231 } 232 233 @Override 234 public String getName() { 235 return "value"; 236 } 237 }; 238 } 239 return value; 240 } 241 /** 242 * When true, indicates the current value of this Slider is changing. 243 * It provides notification that the value is changing. Once the value is 244 * computed, it is reset back to false. 245 */ 246 private BooleanProperty valueChanging; 247 248 public final void setValueChanging(boolean value) { 249 valueChangingProperty().set(value); 250 } 251 252 public final boolean isValueChanging() { 253 return valueChanging == null ? false : valueChanging.get(); 254 } 255 256 public final BooleanProperty valueChangingProperty() { 257 if (valueChanging == null) { 258 valueChanging = new SimpleBooleanProperty(this, "valueChanging", false); 259 } 260 return valueChanging; 261 } 262 // /** 263 // * The {@code span} is the distance, or quantity, between min and max value. 264 // * This will be strictly non-negative, since both {@code min} and 265 // * {@code max} are forced to maintain a proper relationship. 266 // */ 267 // // public def span = bind max - min; 268 269 /** 270 * The orientation of the {@code Slider} can either be horizontal 271 * or vertical. 272 */ 273 private ObjectProperty<Orientation> orientation; 274 public final void setOrientation(Orientation value) { 275 orientationProperty().set(value); 276 } 277 278 public final Orientation getOrientation() { 279 return orientation == null ? Orientation.HORIZONTAL : orientation.get(); 280 } 281 282 public final ObjectProperty<Orientation> orientationProperty() { 283 if (orientation == null) { 284 orientation = new StyleableObjectProperty<Orientation>(Orientation.HORIZONTAL) { 285 @Override protected void invalidated() { 286 final boolean vertical = (get() == Orientation.VERTICAL); 287 pseudoClassStateChanged(VERTICAL_PSEUDOCLASS_STATE, vertical); 288 pseudoClassStateChanged(HORIZONTAL_PSEUDOCLASS_STATE, !vertical); 289 } 290 291 @Override 292 public CssMetaData<Slider,Orientation> getCssMetaData() { 293 return StyleableProperties.ORIENTATION; 294 } 295 296 @Override 297 public Object getBean() { 298 return Slider.this; 299 } 300 301 @Override 302 public String getName() { 303 return "orientation"; 304 } 305 }; 306 } 307 return orientation; 308 } 309 310 311 /** 312 * Indicates that the labels for tick marks should be shown. Typically a 313 * {@link Skin} implementation will only show labels if 314 * {@link #showTickMarksProperty() showTickMarks} is also true. 315 */ 316 private BooleanProperty showTickLabels; 317 public final void setShowTickLabels(boolean value) { 318 showTickLabelsProperty().set(value); 319 } 320 321 public final boolean isShowTickLabels() { 322 return showTickLabels == null ? false : showTickLabels.get(); 323 } 324 325 public final BooleanProperty showTickLabelsProperty() { 326 if (showTickLabels == null) { 327 showTickLabels = new StyleableBooleanProperty(false) { 328 329 330 @Override 331 public CssMetaData<Slider,Boolean> getCssMetaData() { 332 return StyleableProperties.SHOW_TICK_LABELS; 333 } 334 335 @Override 336 public Object getBean() { 337 return Slider.this; 338 } 339 340 @Override 341 public String getName() { 342 return "showTickLabels"; 343 } 344 }; 345 } 346 return showTickLabels; 347 } 348 /** 349 * Specifies whether the {@link Skin} implementation should show tick marks. 350 */ 351 private BooleanProperty showTickMarks; 352 public final void setShowTickMarks(boolean value) { 353 showTickMarksProperty().set(value); 354 } 355 356 public final boolean isShowTickMarks() { 357 return showTickMarks == null ? false : showTickMarks.get(); 358 } 359 360 public final BooleanProperty showTickMarksProperty() { 361 if (showTickMarks == null) { 362 showTickMarks = new StyleableBooleanProperty(false) { 363 364 365 @Override 366 public CssMetaData<Slider,Boolean> getCssMetaData() { 367 return StyleableProperties.SHOW_TICK_MARKS; 368 } 369 370 @Override 371 public Object getBean() { 372 return Slider.this; 373 } 374 375 @Override 376 public String getName() { 377 return "showTickMarks"; 378 } 379 }; 380 } 381 return showTickMarks; 382 } 383 /** 384 * The unit distance between major tick marks. For example, if 385 * the {@link #minProperty() min} is 0 and the {@link #maxProperty() max} is 100 and the 386 * {@link #majorTickUnitProperty() majorTickUnit} is 25, then there would be 5 tick marks: one at 387 * position 0, one at position 25, one at position 50, one at position 388 * 75, and a final one at position 100. 389 * <p> 390 * This value should be positive and should be a value less than the 391 * span. Out of range values are essentially the same as disabling 392 * tick marks. 393 */ 394 private DoubleProperty majorTickUnit; 395 public final void setMajorTickUnit(double value) { 396 if (value <= 0) { 397 throw new IllegalArgumentException("MajorTickUnit cannot be less than or equal to 0."); 398 } 399 majorTickUnitProperty().set(value); 400 } 401 402 public final double getMajorTickUnit() { 403 return majorTickUnit == null ? 25 : majorTickUnit.get(); 404 } 405 406 public final DoubleProperty majorTickUnitProperty() { 407 if (majorTickUnit == null) { 408 majorTickUnit = new StyleableDoubleProperty(25) { 409 @Override 410 public void invalidated() { 411 if (get() <= 0) { 412 throw new IllegalArgumentException("MajorTickUnit cannot be less than or equal to 0."); 413 } 414 } 415 416 @Override 417 public CssMetaData<Slider,Number> getCssMetaData() { 418 return StyleableProperties.MAJOR_TICK_UNIT; 419 } 420 421 @Override 422 public Object getBean() { 423 return Slider.this; 424 } 425 426 @Override 427 public String getName() { 428 return "majorTickUnit"; 429 } 430 }; 431 } 432 return majorTickUnit; 433 } 434 /** 435 * The number of minor ticks to place between any two major ticks. This 436 * number should be positive or zero. Out of range values will disable 437 * disable minor ticks, as will a value of zero. 438 */ 439 private IntegerProperty minorTickCount; 440 public final void setMinorTickCount(int value) { 441 minorTickCountProperty().set(value); 442 } 443 444 public final int getMinorTickCount() { 445 return minorTickCount == null ? 3 : minorTickCount.get(); 446 } 447 448 public final IntegerProperty minorTickCountProperty() { 449 if (minorTickCount == null) { 450 minorTickCount = new StyleableIntegerProperty(3) { 451 452 453 @Override 454 public CssMetaData<Slider,Number> getCssMetaData() { 455 return StyleableProperties.MINOR_TICK_COUNT; 456 } 457 458 @Override 459 public Object getBean() { 460 return Slider.this; 461 } 462 463 @Override 464 public String getName() { 465 return "minorTickCount"; 466 } 467 }; 468 } 469 return minorTickCount; 470 } 471 /** 472 * Indicates whether the {@link #valueProperty() value} of the {@code Slider} should always 473 * be aligned with the tick marks. This is honored even if the tick marks 474 * are not shown. 475 */ 476 private BooleanProperty snapToTicks; 477 public final void setSnapToTicks(boolean value) { 478 snapToTicksProperty().set(value); 479 } 480 481 public final boolean isSnapToTicks() { 482 return snapToTicks == null ? false : snapToTicks.get(); 483 } 484 485 public final BooleanProperty snapToTicksProperty() { 486 if (snapToTicks == null) { 487 snapToTicks = new StyleableBooleanProperty(false) { 488 489 @Override 490 public CssMetaData<Slider,Boolean> getCssMetaData() { 491 return StyleableProperties.SNAP_TO_TICKS; 492 } 493 494 @Override 495 public Object getBean() { 496 return Slider.this; 497 } 498 499 @Override 500 public String getName() { 501 return "snapToTicks"; 502 } 503 }; 504 } 505 return snapToTicks; 506 } 507 /** 508 * A function for formatting the label for a major tick. The number 509 * representing the major tick will be passed to the function. If this 510 * function is not specified, then a default function will be used by 511 * the {@link Skin} implementation. 512 */ 513 private ObjectProperty<StringConverter<Double>> labelFormatter; 514 515 public final void setLabelFormatter(StringConverter<Double> value) { 516 labelFormatterProperty().set(value); 517 } 518 519 public final StringConverter<Double> getLabelFormatter() { 520 return labelFormatter == null ? null : labelFormatter.get(); 521 } 522 523 public final ObjectProperty<StringConverter<Double>> labelFormatterProperty() { 524 if (labelFormatter == null) { 525 labelFormatter = new SimpleObjectProperty<StringConverter<Double>>(this, "labelFormatter"); 526 } 527 return labelFormatter; 528 } 529 /** 530 * The amount by which to adjust the slider if the track of the slider is 531 * clicked. This is used when manipulating the slider position using keys. If 532 * {@link #snapToTicksProperty() snapToTicks} is true then the nearest tick mark to the adjusted 533 * value will be used. 534 */ 535 private DoubleProperty blockIncrement; 536 public final void setBlockIncrement(double value) { 537 blockIncrementProperty().set(value); 538 } 539 540 public final double getBlockIncrement() { 541 return blockIncrement == null ? 10 : blockIncrement.get(); 542 } 543 544 public final DoubleProperty blockIncrementProperty() { 545 if (blockIncrement == null) { 546 blockIncrement = new StyleableDoubleProperty(10) { 547 548 @Override 549 public CssMetaData<Slider,Number> getCssMetaData() { 550 return StyleableProperties.BLOCK_INCREMENT; 551 } 552 553 @Override 554 public Object getBean() { 555 return Slider.this; 556 } 557 558 @Override 559 public String getName() { 560 return "blockIncrement"; 561 } 562 }; 563 } 564 return blockIncrement; 565 } 566 567 /** 568 * Adjusts {@link #valueProperty() value} to match <code>newValue</code>. The 569 * <code>value</code>is the actual amount between the 570 * {@link #minProperty() min} and {@link #maxProperty() max}. This function 571 * also takes into account {@link #snapToTicksProperty() snapToTicks}, which 572 * is the main difference between adjustValue and setValue. It also ensures 573 * that the value is some valid number between min and max. 574 * 575 * @expert This function is intended to be used by experts, primarily 576 * by those implementing new Skins or Behaviors. It is not common 577 * for developers or designers to access this function directly. 578 */ 579 public void adjustValue(double newValue) { 580 // figure out the "value" associated with the specified position 581 final double _min = getMin(); 582 final double _max = getMax(); 583 if (_max <= _min) return; 584 newValue = newValue < _min ? _min : newValue; 585 newValue = newValue > _max ? _max : newValue; 586 587 setValue(snapValueToTicks(newValue)); 588 } 589 590 /** 591 * Increments the value by {@link #blockIncrementProperty() blockIncrement}, bounded by max. If the 592 * max is less than or equal to the min, then this method does nothing. 593 */ 594 public void increment() { 595 adjustValue(getValue() + getBlockIncrement()); 596 } 597 598 /** 599 * Decrements the value by {@link #blockIncrementProperty() blockIncrement}, bounded by max. If the 600 * max is less than or equal to the min, then this method does nothing. 601 */ 602 public void decrement() { 603 adjustValue(getValue() - getBlockIncrement()); 604 } 605 606 /** 607 * Ensures that min is always < max, that value is always 608 * somewhere between the two, and that if snapToTicks is set then the 609 * value will always be set to align with a tick mark. 610 */ 611 private void adjustValues() { 612 if ((getValue() < getMin() || getValue() > getMax()) /* && !isReadOnly(value)*/) 613 setValue(Utils.clamp(getMin(), getValue(), getMax())); 614 } 615 616 /** 617 * Utility function which, given the specified value, will position it 618 * either aligned with a tick, or simply clamp between min & max value, 619 * depending on whether snapToTicks is set. 620 * 621 * @expert This function is intended to be used by experts, primarily 622 * by those implementing new Skins or Behaviors. It is not common 623 * for developers or designers to access this function directly. 624 */ 625 private double snapValueToTicks(double val) { 626 double v = val; 627 if (isSnapToTicks()) { 628 double tickSpacing = 0; 629 // compute the nearest tick to this value 630 if (getMinorTickCount() != 0) { 631 tickSpacing = getMajorTickUnit() / (Math.max(getMinorTickCount(),0)+1); 632 } else { 633 tickSpacing = getMajorTickUnit(); 634 } 635 int prevTick = (int)((v - getMin())/ tickSpacing); 636 double prevTickValue = (prevTick) * tickSpacing + getMin(); 637 double nextTickValue = (prevTick + 1) * tickSpacing + getMin(); 638 v = Utils.nearest(prevTickValue, v, nextTickValue); 639 } 640 return Utils.clamp(getMin(), v, getMax()); 641 } 642 643 /** {@inheritDoc} */ 644 @Override protected Skin<?> createDefaultSkin() { 645 return new SliderSkin(this); 646 } 647 648 /*************************************************************************** 649 * * 650 * Stylesheet Handling * 651 * * 652 **************************************************************************/ 653 654 private static final String DEFAULT_STYLE_CLASS = "slider"; 655 656 private static class StyleableProperties { 657 private static final CssMetaData<Slider,Number> BLOCK_INCREMENT = 658 new CssMetaData<Slider,Number>("-fx-block-increment", 659 SizeConverter.getInstance(), 10.0) { 660 661 @Override 662 public boolean isSettable(Slider n) { 663 return n.blockIncrement == null || !n.blockIncrement.isBound(); 664 } 665 666 @Override 667 public StyleableProperty<Number> getStyleableProperty(Slider n) { 668 return (StyleableProperty<Number>)(WritableValue<Number>)n.blockIncrementProperty(); 669 } 670 }; 671 672 private static final CssMetaData<Slider,Boolean> SHOW_TICK_LABELS = 673 new CssMetaData<Slider,Boolean>("-fx-show-tick-labels", 674 BooleanConverter.getInstance(), Boolean.FALSE) { 675 676 @Override 677 public boolean isSettable(Slider n) { 678 return n.showTickLabels == null || !n.showTickLabels.isBound(); 679 } 680 681 @Override 682 public StyleableProperty<Boolean> getStyleableProperty(Slider n) { 683 return (StyleableProperty<Boolean>)(WritableValue<Boolean>)n.showTickLabelsProperty(); 684 } 685 }; 686 687 private static final CssMetaData<Slider,Boolean> SHOW_TICK_MARKS = 688 new CssMetaData<Slider,Boolean>("-fx-show-tick-marks", 689 BooleanConverter.getInstance(), Boolean.FALSE) { 690 691 @Override 692 public boolean isSettable(Slider n) { 693 return n.showTickMarks == null || !n.showTickMarks.isBound(); 694 } 695 696 @Override 697 public StyleableProperty<Boolean> getStyleableProperty(Slider n) { 698 return (StyleableProperty<Boolean>)(WritableValue<Boolean>)n.showTickMarksProperty(); 699 } 700 }; 701 702 private static final CssMetaData<Slider,Boolean> SNAP_TO_TICKS = 703 new CssMetaData<Slider,Boolean>("-fx-snap-to-ticks", 704 BooleanConverter.getInstance(), Boolean.FALSE) { 705 706 @Override 707 public boolean isSettable(Slider n) { 708 return n.snapToTicks == null || !n.snapToTicks.isBound(); 709 } 710 711 @Override 712 public StyleableProperty<Boolean> getStyleableProperty(Slider n) { 713 return (StyleableProperty<Boolean>)(WritableValue<Boolean>)n.snapToTicksProperty(); 714 } 715 }; 716 717 private static final CssMetaData<Slider,Number> MAJOR_TICK_UNIT = 718 new CssMetaData<Slider,Number>("-fx-major-tick-unit", 719 SizeConverter.getInstance(), 25.0) { 720 721 @Override 722 public boolean isSettable(Slider n) { 723 return n.majorTickUnit == null || !n.majorTickUnit.isBound(); 724 } 725 726 @Override 727 public StyleableProperty<Number> getStyleableProperty(Slider n) { 728 return (StyleableProperty<Number>)(WritableValue<Number>)n.majorTickUnitProperty(); 729 } 730 }; 731 732 private static final CssMetaData<Slider,Number> MINOR_TICK_COUNT = 733 new CssMetaData<Slider,Number>("-fx-minor-tick-count", 734 SizeConverter.getInstance(), 3.0) { 735 736 @Override 737 public boolean isSettable(Slider n) { 738 return n.minorTickCount == null || !n.minorTickCount.isBound(); 739 } 740 741 @Override 742 public StyleableProperty<Number> getStyleableProperty(Slider n) { 743 return (StyleableProperty<Number>)(WritableValue<Number>)n.minorTickCountProperty(); 744 } 745 }; 746 747 private static final CssMetaData<Slider,Orientation> ORIENTATION = 748 new CssMetaData<Slider,Orientation>("-fx-orientation", 749 new EnumConverter<Orientation>(Orientation.class), 750 Orientation.HORIZONTAL) { 751 752 @Override 753 public Orientation getInitialValue(Slider node) { 754 // A vertical Slider should remain vertical 755 return node.getOrientation(); 756 } 757 758 @Override 759 public boolean isSettable(Slider n) { 760 return n.orientation == null || !n.orientation.isBound(); 761 } 762 763 @Override 764 public StyleableProperty<Orientation> getStyleableProperty(Slider n) { 765 return (StyleableProperty<Orientation>)(WritableValue<Orientation>)n.orientationProperty(); 766 } 767 }; 768 769 private static final List<CssMetaData<? extends Styleable, ?>> STYLEABLES; 770 static { 771 final List<CssMetaData<? extends Styleable, ?>> styleables = 772 new ArrayList<CssMetaData<? extends Styleable, ?>>(Control.getClassCssMetaData()); 773 styleables.add(BLOCK_INCREMENT); 774 styleables.add(SHOW_TICK_LABELS); 775 styleables.add(SHOW_TICK_MARKS); 776 styleables.add(SNAP_TO_TICKS); 777 styleables.add(MAJOR_TICK_UNIT); 778 styleables.add(MINOR_TICK_COUNT); 779 styleables.add(ORIENTATION); 780 781 STYLEABLES = Collections.unmodifiableList(styleables); 782 } 783 } 784 785 /** 786 * @return The CssMetaData associated with this class, which may include the 787 * CssMetaData of its super classes. 788 * @since JavaFX 8.0 789 */ 790 public static List<CssMetaData<? extends Styleable, ?>> getClassCssMetaData() { 791 return StyleableProperties.STYLEABLES; 792 } 793 794 /** 795 * {@inheritDoc} 796 * @since JavaFX 8.0 797 */ 798 @Override protected List<CssMetaData<? extends Styleable, ?>> getControlCssMetaData() { 799 return getClassCssMetaData(); 800 } 801 802 private static final PseudoClass VERTICAL_PSEUDOCLASS_STATE = 803 PseudoClass.getPseudoClass("vertical"); 804 private static final PseudoClass HORIZONTAL_PSEUDOCLASS_STATE = 805 PseudoClass.getPseudoClass("horizontal"); 806 807 808 809 /*************************************************************************** 810 * * 811 * Accessibility handling * 812 * * 813 **************************************************************************/ 814 815 @Override 816 public Object queryAccessibleAttribute(AccessibleAttribute attribute, Object... parameters) { 817 switch (attribute) { 818 case VALUE: return getValue(); 819 case MAX_VALUE: return getMax(); 820 case MIN_VALUE: return getMin(); 821 case ORIENTATION: return getOrientation(); 822 default: return super.queryAccessibleAttribute(attribute, parameters); 823 } 824 } 825 826 @Override 827 public void executeAccessibleAction(AccessibleAction action, Object... parameters) { 828 switch (action) { 829 case INCREMENT: increment(); break; 830 case DECREMENT: decrement(); break; 831 case SET_VALUE: { 832 Double value = (Double) parameters[0]; 833 if (value != null) setValue(value); 834 break; 835 } 836 default: super.executeAccessibleAction(action, parameters); 837 } 838 } 839 }