Spec-Zone .ru
спецификации, руководства, описания, API
|
001/* 002 * Copyright (c) 2011, 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.animation; 027 028import javafx.beans.property.ObjectProperty; 029import javafx.beans.property.ObjectPropertyBase; 030import javafx.beans.property.SimpleObjectProperty; 031import javafx.scene.Node; 032import javafx.scene.paint.Color; 033import javafx.scene.shape.Shape; 034import javafx.util.Duration; 035 036/** 037 * This {@code Transition} creates an animation, that changes the filling of a 038 * shape over a {@code duration}. This is done by updating the {@code fill} 039 * variable of the {@code shape} at regular intervals. 040 * <p> 041 * It starts from the {@code fromValue} if provided else uses the {@code shape} 042 * 's {@code fill} value. (The {@code stroke} value has to be a 043 * {@link javafx.scene.paint.Color} in this case). 044 * <p> 045 * It stops at the {@code toValue} value. 046 * 047 * <p> 048 * Code Segment Example: 049 * </p> 050 * 051 * <pre> 052 * <code> 053 * import javafx.scene.shape.*; 054 * import javafx.animation.transition.*; 055 * 056 * ... 057 * 058 * Rectangle rect = new Rectangle (100, 40, 100, 100); 059 * rect.setArcHeight(50); 060 * rect.setArcWidth(50); 061 * 062 * FillTransition ft = new FillTransition(Duration.millis(3000), rect, Color.RED, Color.BLUE); 063 * ft.setCycleCount(4); 064 * ft.setAutoReverse(true); 065 * 066 * ft.play(); 067 * 068 * ... 069 * 070 * </code> 071 * </pre> 072 * 073 * @see Transition 074 * @see Animation 075 * 076 */ 077public final class FillTransition extends Transition { 078 079 private Color start; 080 private Color end; 081 082 /** 083 * The target shape of this {@code FillTransition}. 084 * <p> 085 * It is not possible to change the target {@code shape} of a running 086 * {@code FillTransition}. If the value of {@code shape} is changed for a 087 * running {@code FillTransition}, the animation has to be stopped and 088 * started again to pick up the new value. 089 */ 090 private ObjectProperty<Shape> shape; 091 private static final Shape DEFAULT_SHAPE = null; 092 093 public final void setShape(Shape value) { 094 if ((shape != null) || (value != null /* DEFAULT_SHAPE */)) { 095 shapeProperty().set(value); 096 } 097 } 098 099 public final Shape getShape() { 100 return (shape == null)? DEFAULT_SHAPE : shape.get(); 101 } 102 103 public final ObjectProperty<Shape> shapeProperty() { 104 if (shape == null) { 105 shape = new SimpleObjectProperty<Shape>(this, "shape", DEFAULT_SHAPE); 106 } 107 return shape; 108 } 109 110 private Shape cachedShape; 111 112 /** 113 * The duration of this {@code FillTransition}. 114 * <p> 115 * It is not possible to change the {@code duration} of a running 116 * {@code FillTransition}. If the value of {@code duration} is changed for a 117 * running {@code FillTransition}, the animation has to be stopped and 118 * started again to pick up the new value. 119 * <p> 120 * Note: While the unit of {@code duration} is a millisecond, the 121 * granularity depends on the underlying operating system and will in 122 * general be larger. For example animations on desktop systems usually run 123 * with a maximum of 60fps which gives a granularity of ~17 ms. 124 * 125 * Setting duration to value lower than {@link Duration#ZERO} will result 126 * in {@link IllegalArgumentException}. 127 * 128 * @defaultValue 400ms 129 */ 130 private ObjectProperty<Duration> duration; 131 private static final Duration DEFAULT_DURATION = Duration.millis(400); 132 133 public final void setDuration(Duration value) { 134 if ((duration != null) || (!DEFAULT_DURATION.equals(value))) { 135 durationProperty().set(value); 136 } 137 } 138 139 public final Duration getDuration() { 140 return (duration == null)? DEFAULT_DURATION : duration.get(); 141 } 142 143 public final ObjectProperty<Duration> durationProperty() { 144 if (duration == null) { 145 duration = new ObjectPropertyBase<Duration>(DEFAULT_DURATION) { 146 147 @Override 148 public void invalidated() { 149 try { 150 setCycleDuration(getDuration()); 151 } catch (IllegalArgumentException e) { 152 if (isBound()) { 153 unbind(); 154 } 155 set(getCycleDuration()); 156 throw e; 157 } 158 } 159 160 @Override 161 public Object getBean() { 162 return FillTransition.this; 163 } 164 165 @Override 166 public String getName() { 167 return "duration"; 168 } 169 }; 170 } 171 return duration; 172 } 173 174 /** 175 * Specifies the start color value for this {@code FillTransition}. 176 * <p> 177 * It is not possible to change {@code fromValue} of a running 178 * {@code FillTransition}. If the value of {@code fromValue} is changed for 179 * a running {@code FillTransition}, the animation has to be stopped and 180 * started again to pick up the new value. 181 * 182 * @defaultValue {@code null} 183 */ 184 private ObjectProperty<Color> fromValue; 185 private static final Color DEFAULT_FROM_VALUE = null; 186 187 public final void setFromValue(Color value) { 188 if ((fromValue != null) || (value != null /* DEFAULT_FROM_VALUE */)) { 189 fromValueProperty().set(value); 190 } 191 } 192 193 public final Color getFromValue() { 194 return (fromValue == null)? DEFAULT_FROM_VALUE : fromValue.get(); 195 } 196 197 public final ObjectProperty<Color> fromValueProperty() { 198 if (fromValue == null) { 199 fromValue = new SimpleObjectProperty<Color>(this, "fromValue", DEFAULT_FROM_VALUE); 200 } 201 return fromValue; 202 } 203 204 /** 205 * Specifies the stop color value for this {@code FillTransition}. 206 * <p> 207 * It is not possible to change {@code toValue} of a running 208 * {@code FillTransition}. If the value of {@code toValue} is changed for a 209 * running {@code FillTransition}, the animation has to be stopped and 210 * started again to pick up the new value. 211 * 212 * @defaultValue {@code null} 213 */ 214 private ObjectProperty<Color> toValue; 215 private static final Color DEFAULT_TO_VALUE = null; 216 217 public final void setToValue(Color value) { 218 if ((toValue != null) || (value != null /* DEFAULT_TO_VALUE */)) { 219 toValueProperty().set(value); 220 } 221 } 222 223 public final Color getToValue() { 224 return (toValue == null)? DEFAULT_TO_VALUE : toValue.get(); 225 } 226 227 public final ObjectProperty<Color> toValueProperty() { 228 if (toValue == null) { 229 toValue = new SimpleObjectProperty<Color>(this, "toValue", DEFAULT_TO_VALUE); 230 } 231 return toValue; 232 } 233 234/** 235 * The constructor of {@code FillTransition} 236 * @param duration The duration of the {@code FillTransition} 237 * @param shape The {@code shape} which filling will be animated 238 * @param fromValue The start value of the color-animation 239 * @param toValue The end value of the color-animation 240 */ 241 public FillTransition(Duration duration, Shape shape, Color fromValue, 242 Color toValue) { 243 setDuration(duration); 244 setShape(shape); 245 setFromValue(fromValue); 246 setToValue(toValue); 247 setCycleDuration(duration); 248 } 249 250/** 251 * The constructor of {@code FillTransition} 252 * @param duration The duration of the {@code FillTransition} 253 * @param fromValue The start value of the color-animation 254 * @param toValue The end value of the color-animation 255 */ 256 public FillTransition(Duration duration, Color fromValue, Color toValue) { 257 this(duration, null, fromValue, toValue); 258 } 259 260 /** 261 * The constructor of {@code FillTransition} 262 * 263 * @param duration 264 * The duration of the {@code FillTransition} 265 * @param shape 266 * The {@code shape} which filling will be animated 267 */ 268 public FillTransition(Duration duration, Shape shape) { 269 this(duration, shape, null, null); 270 } 271 272 /** 273 * The constructor of {@code FillTransition} 274 * 275 * @param duration 276 * The duration of the {@code FadeTransition} 277 */ 278 public FillTransition(Duration duration) { 279 this(duration, null, null, null); 280 } 281 282 /** 283 * The constructor of {@code FillTransition} 284 */ 285 public FillTransition() { 286 this(DEFAULT_DURATION, null); 287 } 288 289 /** 290 * {@inheritDoc} 291 */ 292 @Override 293 protected void interpolate(double frac) { 294 final Color newColor = start.interpolate(end, frac); 295 cachedShape.setFill(newColor); 296 } 297 298 private Shape getTargetShape() { 299 Shape shape = getShape(); 300 if (shape == null) { 301 final Node node = getParentTargetNode(); 302 if (node instanceof Shape) { 303 shape = (Shape) node; 304 } 305 } 306 return shape; 307 } 308 309 @Override 310 boolean impl_startable(boolean forceSync) { 311 if (!super.impl_startable(forceSync)) { 312 return false; 313 } 314 // check if synchronization is not forced and cached values are valid 315 if (!forceSync && (cachedShape != null)) { 316 return true; 317 } 318 319 // we have to synchronize 320 final Shape shape = getTargetShape(); 321 return ((shape != null) // shape is defined? 322 && ((getFromValue() != null) || (shape.getFill() instanceof Color)) // fromValue 323 // defined 324 // or 325 // current 326 // fill 327 // is 328 // Color? 329 && (getToValue() != null)); // toValue defined? 330 } 331 332 @Override 333 void impl_sync(boolean forceSync) { 334 super.impl_sync(forceSync); 335 if (forceSync || (cachedShape == null)) { 336 cachedShape = getTargetShape(); 337 final Color _fromValue = getFromValue(); 338 start = (_fromValue != null) ? _fromValue : (Color) cachedShape 339 .getFill(); 340 end = getToValue(); 341 } 342 } 343}