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