Spec-Zone .ru
спецификации, руководства, описания, API
|
001/* 002 * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. 003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 004 * 005 * This code is free software; you can redistribute it and/or modify it 006 * under the terms of the GNU General Public License version 2 only, as 007 * published by the Free Software Foundation. Oracle designates this 008 * particular file as subject to the "Classpath" exception as provided 009 * by Oracle in the LICENSE file that accompanied this code. 010 * 011 * This code is distributed in the hope that it will be useful, but WITHOUT 012 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 013 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 014 * version 2 for more details (a copy is included in the LICENSE file that 015 * accompanied this code). 016 * 017 * You should have received a copy of the GNU General Public License version 018 * 2 along with this work; if not, write to the Free Software Foundation, 019 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 020 * 021 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 022 * or visit www.oracle.com if you need additional information or have any 023 * questions. 024 */ 025 026package javafx.scene.control; 027 028import java.util.ArrayList; 029import java.util.Collections; 030import java.util.List; 031import javafx.beans.property.DoubleProperty; 032import javafx.beans.property.ObjectProperty; 033import javafx.beans.property.SimpleDoubleProperty; 034import javafx.geometry.Orientation; 035 036import com.sun.javafx.Utils; 037import javafx.css.CssMetaData; 038import javafx.css.PseudoClass; 039import javafx.css.StyleableDoubleProperty; 040import javafx.css.StyleableObjectProperty; 041import com.sun.javafx.css.converters.EnumConverter; 042import com.sun.javafx.css.converters.SizeConverter; 043import com.sun.javafx.scene.control.skin.ScrollBarSkin; 044import javafx.css.Styleable; 045import javafx.css.StyleableProperty; 046 047 048/** 049 * Either a horizontal or vertical bar with increment and decrement buttons and 050 * a "thumb" with which the user can interact. Typically not used alone but used 051 * for building up more complicated controls such as the ScrollPane and ListView. 052 * <p> 053 * ScrollBar sets focusTraversable to false. 054 * </p> 055 * 056 * <p> 057 * This example creates a vertical ScrollBar : 058 * <pre><code> 059 * import javafx.scene.control.ScrollBar; 060 * 061 * ScrollBar s1 = new ScrollBar(); 062 * s1.setOrientation(Orientation.VERTICAL); 063 * </code></pre> 064 * 065 * Implementation of ScrollBar According to JavaFX UI Control API Specification 066 */ 067 068public class ScrollBar extends Control { 069 070 /*************************************************************************** 071 * * 072 * Constructors * 073 * * 074 **************************************************************************/ 075 076 /** 077 * Creates a new horizontal (i.e. <code>getOrientation() == Orientation.HORIZONTAL</code>) 078 * ScrollBar. 079 */ 080 public ScrollBar() { 081 // TODO : we need to ensure we have a width and height 082 setWidth(ScrollBarSkin.DEFAULT_WIDTH); 083 setHeight(ScrollBarSkin.DEFAULT_LENGTH); 084 getStyleClass().setAll(DEFAULT_STYLE_CLASS); 085 // focusTraversable is styleable through css. Calling setFocusTraversable 086 // makes it look to css like the user set the value and css will not 087 // override. Initializing focusTraversable by calling applyStyle with null 088 // for StyleOrigin ensures that css will be able to override the value. 089 ((StyleableProperty)focusTraversableProperty()).applyStyle(null,Boolean.FALSE); 090 091 // set pseudo-class state to horizontal 092 pseudoClassStateChanged(HORIZONTAL_PSEUDOCLASS_STATE, true); 093 094 } 095 /*************************************************************************** 096 * * 097 * Properties * 098 * * 099 **************************************************************************/ 100 /** 101 * The minimum value represented by this {@code ScrollBar}. This should be a 102 * value less than or equal to {@link #maxProperty max}. 103 */ 104 private DoubleProperty min; 105 public final void setMin(double value) { 106 minProperty().set(value); 107 } 108 109 public final double getMin() { 110 return min == null ? 0 : min.get(); 111 } 112 113 public final DoubleProperty minProperty() { 114 if (min == null) { 115 min = new SimpleDoubleProperty(this, "min"); 116 } 117 return min; 118 } 119 /** 120 * The maximum value represented by this {@code ScrollBar}. This should be a 121 * value greater than or equal to {@link #minProperty min}. 122 */ 123 private DoubleProperty max; 124 public final void setMax(double value) { 125 maxProperty().set(value); 126 } 127 128 public final double getMax() { 129 return max == null ? 100 : max.get(); 130 } 131 132 public final DoubleProperty maxProperty() { 133 if (max == null) { 134 max = new SimpleDoubleProperty(this, "max", 100); 135 } 136 return max; 137 } 138 /** 139 * The current value represented by this {@code ScrollBar}. This value should 140 * be between {@link #minProperty min} and {@link #maxProperty max}, inclusive. 141 */ 142 private DoubleProperty value; 143 public final void setValue(double value) { 144 valueProperty().set(value); 145 } 146 147 public final double getValue() { 148 return value == null ? 0 : value.get(); 149 } 150 151 public final DoubleProperty valueProperty() { 152 if (value == null) { 153 value = new SimpleDoubleProperty(this, "value"); 154 } 155 return value; 156 } 157 /** 158 * The orientation of the {@code ScrollBar} can either be {@link javafx.geometry.Orientation#HORIZONTAL HORIZONTAL} 159 * or {@link javafx.geometry.Orientation#VERTICAL VERTICAL}. 160 */ 161 private ObjectProperty<Orientation> orientation; 162 public final void setOrientation(Orientation value) { 163 orientationProperty().set(value); 164 } 165 166 public final Orientation getOrientation() { 167 return orientation == null ? Orientation.HORIZONTAL : orientation.get(); 168 } 169 170 public final ObjectProperty<Orientation> orientationProperty() { 171 if (orientation == null) { 172 orientation = new StyleableObjectProperty<Orientation>(Orientation.HORIZONTAL) { 173 @Override protected void invalidated() { 174 final boolean vertical = (get() == Orientation.VERTICAL); 175 pseudoClassStateChanged(VERTICAL_PSEUDOCLASS_STATE, vertical); 176 pseudoClassStateChanged(HORIZONTAL_PSEUDOCLASS_STATE, !vertical); 177 } 178 179 @Override 180 public CssMetaData<ScrollBar,Orientation> getCssMetaData() { 181 return StyleableProperties.ORIENTATION; 182 } 183 184 @Override 185 public Object getBean() { 186 return ScrollBar.this; 187 } 188 189 @Override 190 public String getName() { 191 return "orientation"; 192 } 193 }; 194 } 195 return orientation; 196 } 197 198 /** 199 * The amount by which to adjust the ScrollBar when the {@link #increment() increment} or 200 * {@link #decrement() decrement} methods are called. 201 */ 202 private DoubleProperty unitIncrement; 203 public final void setUnitIncrement(double value) { 204 unitIncrementProperty().set(value); 205 } 206 207 public final double getUnitIncrement() { 208 return unitIncrement == null ? 1 : unitIncrement.get(); 209 } 210 211 public final DoubleProperty unitIncrementProperty() { 212 if (unitIncrement == null) { 213 unitIncrement = new StyleableDoubleProperty(1) { 214 215 @Override 216 public CssMetaData<ScrollBar,Number> getCssMetaData() { 217 return StyleableProperties.UNIT_INCREMENT; 218 } 219 220 @Override 221 public Object getBean() { 222 return ScrollBar.this; 223 } 224 225 @Override 226 public String getName() { 227 return "unitIncrement"; 228 } 229 }; 230 } 231 return unitIncrement; 232 } 233 /** 234 * The amount by which to adjust the scrollbar if the track of the bar is 235 * clicked. 236 */ 237 private DoubleProperty blockIncrement; 238 public final void setBlockIncrement(double value) { 239 blockIncrementProperty().set(value); 240 } 241 242 public final double getBlockIncrement() { 243 return blockIncrement == null ? 10 : blockIncrement.get(); 244 } 245 246 public final DoubleProperty blockIncrementProperty() { 247 if (blockIncrement == null) { 248 blockIncrement = new StyleableDoubleProperty(10) { 249 250 @Override 251 public CssMetaData<ScrollBar,Number> getCssMetaData() { 252 return StyleableProperties.BLOCK_INCREMENT; 253 } 254 255 @Override 256 public Object getBean() { 257 return ScrollBar.this; 258 } 259 260 @Override 261 public String getName() { 262 return "blockIncrement"; 263 } 264 }; 265 } 266 return blockIncrement; 267 } 268 /** 269 * Visible amount of the scrollbar's range, typically represented by 270 * the size of the scroll bar's thumb. 271 * 272 * @since JavaFX 1.3 273 */ 274 private DoubleProperty visibleAmount; 275 276 public final void setVisibleAmount(double value) { 277 visibleAmountProperty().set(value); 278 } 279 280 public final double getVisibleAmount() { 281 return visibleAmount == null ? 15 : visibleAmount.get(); 282 } 283 284 public final DoubleProperty visibleAmountProperty() { 285 if (visibleAmount == null) { 286 visibleAmount = new SimpleDoubleProperty(this, "visibleAmount"); 287 } 288 return visibleAmount; 289 } 290 291 /*************************************************************************** 292 * * 293 * Methods * 294 * * 295 **************************************************************************/ 296 297 /** 298 * Adjusts the {@link #valueProperty() value} property by 299 * {@link #blockIncrementProperty() blockIncrement}. The {@code position} is the fractional amount 300 * between the {@link #minProperty min} and {@link #maxProperty max}. For 301 * example, it might be 50%. If {@code #minProperty min} were 0 and {@code #maxProperty max} 302 * were 100 and {@link #valueProperty() value} were 25, then a position of .5 would indicate 303 * that we should increment {@link #valueProperty() value} by 304 * {@code blockIncrement}. If {@link #valueProperty() value} were 75, then a 305 * position of .5 would indicate that we 306 * should decrement {@link #valueProperty() value} by {@link #blockIncrementProperty blockIncrement}. 307 * 308 * @expert This function is intended to be used by experts, primarily 309 * by those implementing new Skins or Behaviors. It is not common 310 * for developers or designers to access this function directly. 311 */ 312 public void adjustValue(double position) { 313 // figure out the "value" associated with the specified position 314 double posValue = ((getMax() - getMin()) * Utils.clamp(0, position, 1))+getMin(); 315 double newValue; 316 if (Double.compare(posValue, getValue()) != 0) { 317 if (posValue > getValue()) { 318 newValue = getValue() + getBlockIncrement(); 319 } 320 else { 321 newValue = getValue() - getBlockIncrement(); 322 } 323 324 boolean incrementing = position > ((getValue() - getMin())/(getMax() - getMin())); 325 if (incrementing && newValue > posValue) newValue = posValue; 326 if (! incrementing && newValue < posValue) newValue = posValue; 327 setValue(Utils.clamp(getMin(), newValue, getMax())); 328 } 329 } 330 331 /** 332 * Increments the value of the {@code ScrollBar} by the 333 * {@link #unitIncrementProperty unitIncrement} 334 */ 335 public void increment() { 336 setValue(Utils.clamp(getMin(), getValue() + getUnitIncrement(), getMax())); 337 } 338 339 /** 340 * Decrements the value of the {@code ScrollBar} by the 341 * {@link #unitIncrementProperty unitIncrement} 342 */ 343 public void decrement() { 344 setValue(Utils.clamp(getMin(), getValue() - getUnitIncrement(), getMax())); 345 } 346 347 /** {@inheritDoc} */ 348 @Override protected Skin<?> createDefaultSkin() { 349 return new ScrollBarSkin(this); 350 } 351 352 /*************************************************************************** 353 * * 354 * Stylesheet Handling * 355 * * 356 **************************************************************************/ 357 358 /** 359 * Initialize the style class to 'scroll-bar'. 360 * 361 * This is the selector class from which CSS can be used to style 362 * this control. 363 */ 364 private static final String DEFAULT_STYLE_CLASS = "scroll-bar"; 365 366 private static class StyleableProperties { 367 private static final CssMetaData<ScrollBar,Orientation> ORIENTATION = 368 new CssMetaData<ScrollBar,Orientation>("-fx-orientation", 369 new EnumConverter<Orientation>(Orientation.class), 370 Orientation.HORIZONTAL) { 371 372 @Override 373 public Orientation getInitialValue(ScrollBar node) { 374 // A vertical ScrollBar should remain vertical 375 return node.getOrientation(); 376 } 377 378 @Override 379 public boolean isSettable(ScrollBar n) { 380 return n.orientation == null || !n.orientation.isBound(); 381 } 382 383 @Override 384 public StyleableProperty<Orientation> getStyleableProperty(ScrollBar n) { 385 return (StyleableProperty<Orientation>)n.orientationProperty(); 386 } 387 }; 388 389 private static final CssMetaData<ScrollBar,Number> UNIT_INCREMENT = 390 new CssMetaData<ScrollBar,Number>("-fx-unit-increment", 391 SizeConverter.getInstance(), 1.0) { 392 393 @Override 394 public boolean isSettable(ScrollBar n) { 395 return n.unitIncrement == null || !n.unitIncrement.isBound(); 396 } 397 398 @Override 399 public StyleableProperty<Number> getStyleableProperty(ScrollBar n) { 400 return (StyleableProperty<Number>)n.unitIncrementProperty(); 401 } 402 403 }; 404 405 private static final CssMetaData<ScrollBar,Number> BLOCK_INCREMENT = 406 new CssMetaData<ScrollBar,Number>("-fx-block-increment", 407 SizeConverter.getInstance(), 10.0) { 408 409 @Override 410 public boolean isSettable(ScrollBar n) { 411 return n.blockIncrement == null || !n.blockIncrement.isBound(); 412 } 413 414 @Override 415 public StyleableProperty<Number> getStyleableProperty(ScrollBar n) { 416 return (StyleableProperty<Number>)n.blockIncrementProperty(); 417 } 418 419 }; 420 421 private static final List<CssMetaData<? extends Styleable, ?>> STYLEABLES; 422 static { 423 final List<CssMetaData<? extends Styleable, ?>> styleables = 424 new ArrayList<CssMetaData<? extends Styleable, ?>>(Control.getClassCssMetaData()); 425 styleables.add(ORIENTATION); 426 styleables.add(UNIT_INCREMENT); 427 styleables.add(BLOCK_INCREMENT); 428 STYLEABLES = Collections.unmodifiableList(styleables); 429 } 430 } 431 432 /** 433 * @return The CssMetaData associated with this class, which may include the 434 * CssMetaData of its super classes. 435 */ 436 public static List<CssMetaData<? extends Styleable, ?>> getClassCssMetaData() { 437 return StyleableProperties.STYLEABLES; 438 } 439 440 /** 441 * {@inheritDoc} 442 */ 443 @Override 444 public List<CssMetaData<? extends Styleable, ?>> getControlCssMetaData() { 445 return getClassCssMetaData(); 446 } 447 448 /** 449 * Pseud-class indicating this is a vertical ScrollBar. 450 */ 451 private static final PseudoClass VERTICAL_PSEUDOCLASS_STATE = 452 PseudoClass.getPseudoClass("vertical"); 453 454 /** 455 * Pseudo-class indicating this is a horizontal ScrollBar. 456 */ 457 private static final PseudoClass HORIZONTAL_PSEUDOCLASS_STATE = 458 PseudoClass.getPseudoClass("horizontal"); 459 460 /** 461 * Most Controls return true for focusTraversable, so Control overrides 462 * this method to return true, but ScrollBar returns false for 463 * focusTraversable's initial value; hence the override of the override. 464 * This method is called from CSS code to get the correct initial value. 465 * @treatAsPrivate implementation detail 466 */ 467 @Deprecated @Override 468 protected /*do not make final*/ Boolean impl_cssGetFocusTraversableInitialValue() { 469 return Boolean.FALSE; 470 } 471 472}