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.animation; 027 028import java.util.Collection; 029import java.util.Collections; 030import java.util.Set; 031import java.util.concurrent.CopyOnWriteArraySet; 032 033import javafx.event.ActionEvent; 034import javafx.event.EventHandler; 035import javafx.util.Duration; 036 037/** 038 * Defines target values at a specified point in time for a set of variables 039 * that are interpolated along a {@link Timeline}. 040 * <p> 041 * The developer controls the interpolation of a set of variables for the 042 * interval between successive key frames by providing a target value and an 043 * {@link Interpolator} associated with each variable. The variables are 044 * interpolated such that they will reach their target value at the specified 045 * time. An {@link #onFinished} function is invoked on each {@code KeyFrame} if one 046 * is provided. A {@code KeyFrame} can optionally have a {@link #name}, which 047 * will result in a cuepoint that is automatically added to the {@code Timeline}. 048 * 049 * @see Timeline 050 * @see KeyValue 051 * @see Interpolator 052 * 053 */ 054public final class KeyFrame { 055 056 private static final EventHandler<ActionEvent> DEFAULT_ON_FINISHED = null; 057 private static final String DEFAULT_NAME = null; 058 059 /** 060 * Returns the time offset of this {@code KeyFrame}. 061 * 062 * The returned {@link javafx.util.Duration} defines the time offset within 063 * a single cycle of a {@link Timeline} at which the {@link KeyValue 064 * KeyValues} will be set and at which the {@link #onFinished} function 065 * variable will be called. 066 * <p> 067 * The {@code time} of a {@code KeyFrame} has to be greater than or equal to 068 * {@link javafx.util.Duration#ZERO} and it cannot be 069 * {@link javafx.util.Duration#UNKNOWN}. 070 * 071 * Note: While the unit of {@code time} is a millisecond, the granularity 072 * depends on the underlying operating system and will in general be larger. 073 * For example animations on desktop systems usually run with a maximum of 074 * 60fps which gives a granularity of ~17 ms. 075 */ 076 public Duration getTime() { 077 return time; 078 } 079 private final Duration time; 080 081 /** 082 * Returns an immutable {@code Set} of {@link KeyValue} instances. 083 * 084 * A {@code KeyValue} defines a target and the desired value that should be 085 * interpolated at the specified time of this {@code KeyFrame}. 086 */ 087 public Set<KeyValue> getValues() { 088 return values; 089 } 090 private final Set<KeyValue> values; 091 092 /** 093 * Returns the {@code onFinished} event handler of this {@code KeyFrame}. 094 * 095 * The {@code onFinished} event handler is a function that is called when 096 * the elapsed time on a cycle passes the specified time of this 097 * {@code KeyFrame}. The {@code onFinished} function variable will be called 098 * if the elapsed time passes the indicated value, even if it never equaled 099 * the time value exactly. 100 */ 101 public EventHandler<ActionEvent> getOnFinished() { 102 return onFinished; 103 } 104 private final EventHandler<ActionEvent> onFinished; 105 106 /** 107 * Returns the {@code name} of this {@code KeyFrame}. 108 * 109 * If a named {@code KeyFrame} is added to a {@link Timeline}, a cuepoint 110 * with the {@code name} and the {@link #time} of the {@code KeyFrame} will 111 * be added automatically. If the {@code KeyFrame} is removed, the cuepoint 112 * will also be removed. 113 */ 114 public String getName() { 115 return name; 116 } 117 private final String name; 118 119 /** 120 * Constructor of {@code KeyFrame} 121 * <p> 122 * If a passed in {@code KeyValue} is {@code null} or a duplicate, it will 123 * be ignored. 124 * 125 * @param time 126 * the {@link #time} 127 * @param name 128 * the {@link #name} 129 * @param onFinished 130 * the {@link #onFinished onFinished-handler} 131 * @param values 132 * a {@link javafx.collections.ObservableList} of 133 * {@link KeyValue} instances 134 * @throws NullPointerException 135 * if {@code time} is null 136 * @throws IllegalArgumentException 137 * if {@code time} is invalid (see {@link #time}) 138 */ 139 public KeyFrame(Duration time, String name, 140 EventHandler<ActionEvent> onFinished, Collection<KeyValue> values) { 141 if (time == null) { 142 throw new NullPointerException("The time has to be specified"); 143 } 144 if (time.lessThan(Duration.ZERO) || time.equals(Duration.UNKNOWN)) { 145 throw new IllegalArgumentException("The time is invalid."); 146 } 147 this.time = time; 148 this.name = name; 149 if (values != null) { 150 final Set<KeyValue> set = new CopyOnWriteArraySet<KeyValue>(values); 151 set.remove(null); 152 this.values = (set.size() == 0) ? Collections.<KeyValue> emptySet() 153 : (set.size() == 1) ? Collections.<KeyValue> singleton(set 154 .iterator().next()) : Collections 155 .unmodifiableSet(set); 156 } else { 157 this.values = Collections.<KeyValue> emptySet(); 158 } 159 this.onFinished = onFinished; 160 } 161 162 /** 163 * Constructor of {@code KeyFrame} 164 * <p> 165 * If a passed in {@code KeyValue} is {@code null} or a duplicate, it will 166 * be ignored. 167 * 168 * @param time 169 * the {@link #time} 170 * @param name 171 * the {@link #name} 172 * @param onFinished 173 * the {@link #onFinished onFinished-handler} 174 * @param values 175 * the {@link KeyValue} instances 176 * @throws NullPointerException 177 * if {@code time} is null 178 * @throws IllegalArgumentException 179 * if {@code time} is invalid (see {@link #time}) 180 */ 181 public KeyFrame(Duration time, String name, 182 EventHandler<ActionEvent> onFinished, KeyValue... values) { 183 if (time == null) { 184 throw new NullPointerException("The time has to be specified"); 185 } 186 if (time.lessThan(Duration.ZERO) || time.equals(Duration.UNKNOWN)) { 187 throw new IllegalArgumentException("The time is invalid."); 188 } 189 this.time = time; 190 this.name = name; 191 if (values != null) { 192 final Set<KeyValue> set = new CopyOnWriteArraySet<KeyValue>(); 193 for (final KeyValue keyValue : values) { 194 if (keyValue != null) { 195 set.add(keyValue); 196 } 197 } 198 this.values = (set.size() == 0) ? Collections.<KeyValue> emptySet() 199 : (set.size() == 1) ? Collections.<KeyValue> singleton(set 200 .iterator().next()) : Collections 201 .unmodifiableSet(set); 202 } else { 203 this.values = Collections.emptySet(); 204 } 205 this.onFinished = onFinished; 206 } 207 208 /** 209 * Constructor of {@code KeyFrame} 210 * 211 * @param time 212 * the {@link #time} 213 * @param onFinished 214 * the {@link #onFinished onFinished-handler} 215 * @param values 216 * the {@link KeyValue} instances 217 * @throws NullPointerException 218 * if {@code time} is null 219 * @throws IllegalArgumentException 220 * if {@code time} is invalid (see {@link #time}) 221 */ 222 public KeyFrame(Duration time, EventHandler<ActionEvent> onFinished, 223 KeyValue... values) { 224 this(time, DEFAULT_NAME, onFinished, values); 225 } 226 227 /** 228 * Constructor of {@code KeyFrame} 229 * 230 * @param time 231 * the {@link #time} 232 * @param name 233 * the {@link #name} 234 * @param values 235 * the {@link KeyValue} instances 236 * @throws NullPointerException 237 * if {@code time} is null 238 * @throws IllegalArgumentException 239 * if {@code time} is invalid (see {@link #time}) 240 */ 241 public KeyFrame(Duration time, String name, KeyValue... values) { 242 this(time, name, DEFAULT_ON_FINISHED, values); 243 } 244 245 /** 246 * Constructor of {@code KeyFrame} 247 * 248 * @param time 249 * the {@link #time} 250 * @param values 251 * the {@link KeyValue} instances 252 * @throws NullPointerException 253 * if {@code time} is null 254 * @throws IllegalArgumentException 255 * if {@code time} is invalid (see {@link #time}) 256 */ 257 public KeyFrame(Duration time, KeyValue... values) { 258 this(time, DEFAULT_NAME, DEFAULT_ON_FINISHED, values); 259 } 260 261 /** 262 * Returns a string representation of this {@code KeyFrame} object. 263 * @return a string representation of this {@code KeyFrame} object. 264 */ 265 @Override 266 public String toString() { 267 return "KeyFrame [time=" + time + ", values=" + values 268 + ", onFinished=" + onFinished + ", name=" + name + "]"; 269 } 270 271 /** 272 * Returns a hash code for this {@code KeyFrame} object. 273 * @return a hash code for this {@code KeyFrame} object. 274 */ 275 @Override 276 public int hashCode() { 277 assert (time != null) && (values != null); 278 final int prime = 31; 279 int result = 1; 280 result = prime * result + time.hashCode(); 281 result = prime * result + ((name == null) ? 0 : name.hashCode()); 282 result = prime * result 283 + ((onFinished == null) ? 0 : onFinished.hashCode()); 284 result = prime * result + values.hashCode(); 285 return result; 286 } 287 288 /** 289 * Indicates whether some other object is "equal to" this one. 290 * Two {@code KeyFrames} are considered equal, if their {@link #getTime() 291 * time}, {@link #onFinished onFinished}, and {@link #getValues() values} 292 * are equal. 293 */ 294 @Override 295 public boolean equals(Object obj) { 296 if (this == obj) { 297 return true; 298 } 299 if (obj instanceof KeyFrame) { 300 final KeyFrame kf = (KeyFrame) obj; 301 assert (time != null) && (values != null) && (kf.time != null) 302 && (kf.values != null); 303 return time.equals(kf.time) 304 && ((name == null) ? kf.name == null : name.equals(kf.name)) 305 && ((onFinished == null) ? kf.onFinished == null 306 : onFinished.equals(kf.onFinished)) 307 && values.equals(kf.values); 308 } 309 return false; 310 } 311 312}