1 /* 2 * Copyright (c) 2011, 2013, 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.animation; 27 28 import java.io.IOException; 29 import java.io.OutputStream; 30 import java.io.PrintStream; 31 32 import com.sun.javafx.tk.Toolkit; 33 import javafx.animation.Animation.Status; 34 import javafx.event.ActionEvent; 35 import javafx.event.EventHandler; 36 import javafx.util.Duration; 37 import com.sun.scenario.animation.AbstractMasterTimerMock; 38 import com.sun.scenario.animation.shared.ClipEnvelopeMock; 39 import org.junit.After; 40 import org.junit.Before; 41 import org.junit.Test; 42 43 import static org.junit.Assert.*; 44 45 public class AnimationTest { 46 47 private static final Duration ONE_SEC = Duration.millis(1000); 48 private static final Duration TWO_SECS = Duration.millis(2000); 49 private static final Duration THREE_SECS = Duration.millis(3000); 50 private static final Duration FOUR_SECS = Duration.millis(4000); 51 52 private static final double DEFAULT_RATE = 1.0; 53 private static final int DEFAULT_REPEAT_COUNT = 1; 54 private static final boolean DEFAULT_AUTO_REVERSE = false; 55 56 private static final double EPSILON = 1e-12; 57 58 private AbstractMasterTimerMock timer; 59 private Animation animation; 60 private ClipEnvelopeMock clipEnvelope; 61 62 @Before 63 public void setUp() { 64 timer = new AbstractMasterTimerMock(); 65 clipEnvelope = new ClipEnvelopeMock(); 66 animation = new AnimationImpl(timer, clipEnvelope, 1); 67 animation.setCycleDuration(ONE_SEC); 68 clipEnvelope.setAnimation(animation); 69 } 70 71 @After 72 public void tearDown() { 73 animation.stop(); 74 } 75 76 @Test 77 public void testConstructors() { 78 final Animation animation0 = new AnimationImpl(); 79 assertEquals(DEFAULT_RATE, animation0.getRate(), EPSILON); 80 assertEquals(0.0, animation0.getCurrentRate(), EPSILON); 81 assertEquals(Duration.ZERO, animation0.getCycleDuration()); 82 assertEquals(Duration.ZERO, animation0.getTotalDuration()); 83 assertEquals(Duration.ZERO, animation0.getCurrentTime()); 84 assertEquals(DEFAULT_REPEAT_COUNT, animation0.getCycleCount()); 85 assertEquals(DEFAULT_AUTO_REVERSE, animation0.isAutoReverse()); 86 assertEquals(Status.STOPPED, animation0.getStatus()); 87 assertEquals(6000.0 / Toolkit.getToolkit().getMasterTimer().getDefaultResolution(), animation0.getTargetFramerate(), EPSILON); 88 assertEquals(null, animation0.getOnFinished()); 89 assertEquals(0, animation0.getCuePoints().size()); 90 91 final Animation animation1 = new AnimationImpl(timer, clipEnvelope, 600); 92 assertEquals(10.0, animation1.getTargetFramerate(), EPSILON); 93 } 94 95 @Test 96 public void testReadOnlyProperties() { 97 // currentRate 98 assertEquals("currentRate", animation.currentRateProperty().getName()); 99 assertEquals(animation, animation.currentRateProperty().getBean()); 100 101 // cycleDuration 102 assertEquals("cycleDuration", animation.cycleDurationProperty().getName()); 103 assertEquals(animation, animation.cycleDurationProperty().getBean()); 104 105 // totalDuration 106 assertEquals("totalDuration", animation.totalDurationProperty().getName()); 107 assertEquals(animation, animation.totalDurationProperty().getBean()); 108 109 // currentTime 110 assertEquals("currentTime", animation.currentTimeProperty().getName()); 111 assertEquals(animation, animation.currentTimeProperty().getBean()); 112 113 // status 114 assertEquals("status", animation.statusProperty().getName()); 115 assertEquals(animation, animation.statusProperty().getBean()); 116 117 } 118 119 @Test 120 public void testCalculationOfTotalDuration() { 121 // 1000ms 122 assertEquals(ONE_SEC, animation.getTotalDuration()); 123 animation.setCycleCount(0); 124 assertEquals(ONE_SEC, animation.getTotalDuration()); 125 animation.setCycleCount(7); 126 assertEquals(ONE_SEC.multiply(7), animation.getTotalDuration()); 127 animation.setCycleCount(Animation.INDEFINITE); 128 assertEquals(Duration.INDEFINITE, animation.getTotalDuration()); 129 animation.setCycleCount(1); 130 131 // Duration.ZERO 132 animation.setCycleDuration(Duration.ZERO); 133 assertEquals(Duration.ZERO, animation.getTotalDuration()); 134 animation.setCycleCount(0); 135 assertEquals(Duration.ZERO, animation.getTotalDuration()); 136 animation.setCycleCount(7); 137 assertEquals(Duration.ZERO, animation.getTotalDuration()); 138 animation.setCycleCount(Animation.INDEFINITE); 139 assertEquals(Duration.ZERO, animation.getTotalDuration()); 140 animation.setCycleCount(1); 141 142 // Duration.INDEFINITE 143 animation.setCycleDuration(Duration.INDEFINITE); 144 assertEquals(Duration.INDEFINITE, animation.getTotalDuration()); 145 animation.setCycleCount(0); 146 assertEquals(Duration.INDEFINITE, animation.getTotalDuration()); 147 animation.setCycleCount(7); 148 assertEquals(Duration.INDEFINITE, animation.getTotalDuration()); 149 animation.setCycleCount(Animation.INDEFINITE); 150 assertEquals(Duration.INDEFINITE, animation.getTotalDuration()); 151 animation.setCycleCount(1); 152 } 153 154 @Test 155 public void testDecreaseTotalDuration() { 156 animation.jumpTo(ONE_SEC); 157 animation.setCycleDuration(ONE_SEC.divide(2)); 158 assertEquals(ONE_SEC.divide(2), animation.getCurrentTime()); 159 animation.setCycleDuration(Duration.ZERO); 160 assertEquals(Duration.ZERO, animation.getCurrentTime()); 161 } 162 163 @Test 164 public void testJumpTo() { 165 animation.setCycleDuration(TWO_SECS); 166 167 // cycleCount = 1 168 animation.jumpTo(ONE_SEC); 169 assertEquals(ONE_SEC, animation.getCurrentTime()); 170 assertEquals(6000, clipEnvelope.getLastJumpTo()); 171 animation.jumpTo(TWO_SECS); 172 assertEquals(TWO_SECS, animation.getCurrentTime()); 173 assertEquals(12000, clipEnvelope.getLastJumpTo()); 174 animation.jumpTo(Duration.ZERO); 175 assertEquals(Duration.ZERO, animation.getCurrentTime()); 176 assertEquals(0, clipEnvelope.getLastJumpTo()); 177 animation.jumpTo(TWO_SECS.add(Duration.ONE)); 178 assertEquals(TWO_SECS, animation.getCurrentTime()); 179 assertEquals(12000, clipEnvelope.getLastJumpTo()); 180 animation.jumpTo(Duration.ONE.negate()); 181 assertEquals(Duration.ZERO, animation.getCurrentTime()); 182 assertEquals(0, clipEnvelope.getLastJumpTo()); 183 184 // cycleCount = 2 185 animation.setCycleCount(2); 186 animation.jumpTo(ONE_SEC); 187 assertEquals(ONE_SEC, animation.getCurrentTime()); 188 assertEquals(6000, clipEnvelope.getLastJumpTo()); 189 animation.jumpTo(TWO_SECS); 190 assertEquals(TWO_SECS, animation.getCurrentTime()); 191 assertEquals(12000, clipEnvelope.getLastJumpTo()); 192 animation.jumpTo(THREE_SECS); 193 assertEquals(ONE_SEC, animation.getCurrentTime()); 194 assertEquals(18000, clipEnvelope.getLastJumpTo()); 195 animation.jumpTo(FOUR_SECS); 196 assertEquals(TWO_SECS, animation.getCurrentTime()); 197 assertEquals(24000, clipEnvelope.getLastJumpTo()); 198 animation.jumpTo(Duration.ZERO); 199 assertEquals(Duration.ZERO, animation.getCurrentTime()); 200 assertEquals(0, clipEnvelope.getLastJumpTo()); 201 animation.jumpTo(FOUR_SECS.add(Duration.ONE)); 202 assertEquals(TWO_SECS, animation.getCurrentTime()); 203 assertEquals(24000, clipEnvelope.getLastJumpTo()); 204 animation.jumpTo(Duration.ONE.negate()); 205 assertEquals(Duration.ZERO, animation.getCurrentTime()); 206 assertEquals(0, clipEnvelope.getLastJumpTo()); 207 } 208 209 @Test 210 public void testJumpTo_ZeroLengthAnimation() { 211 animation.setCycleDuration(Duration.ZERO); 212 213 // cycleCount = 1 214 animation.jumpTo(Duration.ZERO); 215 assertEquals(Duration.ZERO, animation.getCurrentTime()); 216 assertEquals(0, clipEnvelope.getLastJumpTo()); 217 animation.jumpTo(ONE_SEC); 218 assertEquals(Duration.ZERO, animation.getCurrentTime()); 219 assertEquals(0, clipEnvelope.getLastJumpTo()); 220 221 // cycleCount = 2 222 animation.setCycleCount(2); 223 animation.jumpTo(Duration.ZERO); 224 assertEquals(Duration.ZERO, animation.getCurrentTime()); 225 assertEquals(0, clipEnvelope.getLastJumpTo()); 226 animation.jumpTo(ONE_SEC); 227 assertEquals(Duration.ZERO, animation.getCurrentTime()); 228 assertEquals(0, clipEnvelope.getLastJumpTo()); 229 } 230 231 @Test 232 public void testDurationRoundingError() { 233 final Duration duration = Duration.millis(0.01); 234 animation.setCycleDuration(duration); 235 assertTrue(animation.getCycleDuration().greaterThan(Duration.ZERO)); 236 237 // should not be startable 238 assertFalse(animation.impl_startable(true)); 239 240 // jump 241 animation.jumpTo(Duration.ZERO); 242 assertEquals(Duration.ZERO, animation.getCurrentTime()); 243 assertEquals(0, clipEnvelope.getLastJumpTo()); 244 } 245 246 @Test(expected=NullPointerException.class) 247 public void testJumpTo_Null() { 248 animation.jumpTo((Duration)null); 249 } 250 251 @Test(expected=IllegalArgumentException.class) 252 public void testJumpTo_UNKNOWN() { 253 animation.jumpTo(Duration.UNKNOWN); 254 } 255 256 @Test 257 public void testJumpToCuePoint_Default() { 258 animation.getCuePoints().put("ONE_SEC", ONE_SEC); 259 animation.getCuePoints().put("THREE_SECS", THREE_SECS); 260 animation.setCycleDuration(TWO_SECS); 261 262 // normal jumps 263 animation.jumpTo("end"); 264 assertEquals(TWO_SECS, animation.getCurrentTime()); 265 animation.jumpTo("start"); 266 assertEquals(Duration.ZERO, animation.getCurrentTime()); 267 animation.jumpTo("ONE_SEC"); 268 assertEquals(ONE_SEC, animation.getCurrentTime()); 269 270 // jump to non-existing cue-point 271 animation.jumpTo("undefined"); 272 assertEquals(ONE_SEC, animation.getCurrentTime()); 273 274 // jump to cue-point behind end of animation 275 animation.jumpTo("THREE_SECS"); 276 assertEquals(TWO_SECS, animation.getCurrentTime()); 277 } 278 279 @Test 280 public void testJumpToCuePoint_ZeroLengthAnimation() { 281 animation.getCuePoints().put("ONE_SEC", ONE_SEC); 282 animation.setCycleDuration(Duration.ZERO); 283 284 animation.jumpTo("start"); 285 assertEquals(Duration.ZERO, animation.getCurrentTime()); 286 animation.jumpTo("end"); 287 assertEquals(Duration.ZERO, animation.getCurrentTime()); 288 animation.jumpTo("ONE_SEC"); 289 assertEquals(Duration.ZERO, animation.getCurrentTime()); 290 } 291 292 @Test(expected=NullPointerException.class) 293 public void testJumpToCuePoint_Null() { 294 animation.jumpTo((String)null); 295 } 296 297 @Test 298 public void testPlay() { 299 final OnFinishedListener listener = new OnFinishedListener(); 300 animation.setOnFinished(listener); 301 302 // stopped timeline 303 listener.wasCalled = false; 304 animation.play(); 305 assertEquals(Status.RUNNING, animation.getStatus()); 306 assertFalse(listener.wasCalled); 307 assertTrue(timer.containsPulseReceiver(animation.pulseReceiver)); 308 309 // calling play on playing timeline 310 animation.play(); 311 assertEquals(Status.RUNNING, animation.getStatus()); 312 assertFalse(listener.wasCalled); 313 assertTrue(timer.containsPulseReceiver(animation.pulseReceiver)); 314 animation.stop(); 315 316 // stopped timeline, rate = 0 317 listener.wasCalled = false; 318 animation.setRate(0.0); 319 animation.play(); 320 assertEquals(Status.RUNNING, animation.getStatus()); 321 assertFalse(listener.wasCalled); 322 assertFalse(timer.containsPulseReceiver(animation.pulseReceiver)); 323 animation.stop(); 324 animation.setRate(1.0); 325 326 // stopped timeline, cycleDuration = 0 327 listener.wasCalled = false; 328 animation.setCycleDuration(Duration.ZERO); 329 animation.play(); 330 assertEquals(Status.STOPPED, animation.getStatus()); 331 assertTrue(listener.wasCalled); 332 assertFalse(timer.containsPulseReceiver(animation.pulseReceiver)); 333 animation.stop(); 334 animation.setCycleDuration(ONE_SEC); 335 336 // paused timeline 337 animation.play(); 338 animation.pause(); 339 animation.play(); 340 assertEquals(Status.RUNNING, animation.getStatus()); 341 assertTrue(timer.containsPulseReceiver(animation.pulseReceiver)); 342 animation.stop(); 343 344 // paused timeline, rate = 0 345 animation.play(); 346 animation.pause(); 347 animation.setRate(0.0); 348 animation.play(); 349 assertEquals(Status.RUNNING, animation.getStatus()); 350 assertFalse(timer.containsPulseReceiver(animation.pulseReceiver)); 351 } 352 353 @Test 354 public void testStop() { 355 // stopped timeline 356 animation.jumpTo(ONE_SEC); 357 animation.stop(); 358 assertEquals(Status.STOPPED, animation.getStatus()); 359 assertEquals(0.0, animation.getCurrentRate(), EPSILON); 360 assertEquals(ONE_SEC, animation.getCurrentTime()); 361 assertFalse(timer.containsPulseReceiver(animation.pulseReceiver)); 362 363 // playing timeline 364 animation.jumpTo(ONE_SEC); 365 animation.play(); 366 animation.stop(); 367 assertEquals(Status.STOPPED, animation.getStatus()); 368 assertEquals(0.0, animation.getCurrentRate(), EPSILON); 369 assertEquals(Duration.ZERO, animation.getCurrentTime()); 370 assertFalse(timer.containsPulseReceiver(animation.pulseReceiver)); 371 372 // paused timeline 373 animation.jumpTo(ONE_SEC); 374 animation.play(); 375 animation.pause(); 376 animation.stop(); 377 assertEquals(Status.STOPPED, animation.getStatus()); 378 assertEquals(0.0, animation.getCurrentRate(), EPSILON); 379 assertEquals(Duration.ZERO, animation.getCurrentTime()); 380 assertFalse(timer.containsPulseReceiver(animation.pulseReceiver)); 381 } 382 383 @Test 384 public void testPause() { 385 // stopped timeline 386 animation.jumpTo(ONE_SEC); 387 animation.pause(); 388 assertEquals(Status.STOPPED, animation.getStatus()); 389 assertEquals(0.0, animation.getCurrentRate(), EPSILON); 390 assertFalse(timer.containsPulseReceiver(animation.pulseReceiver)); 391 392 // playing timeline 393 animation.jumpTo(ONE_SEC); 394 animation.play(); 395 animation.pause(); 396 assertEquals(Status.PAUSED, animation.getStatus()); 397 assertEquals(0.0, animation.getCurrentRate(), EPSILON); 398 assertFalse(timer.containsPulseReceiver(animation.pulseReceiver)); 399 400 // paused timeline 401 animation.jumpTo(ONE_SEC); 402 animation.play(); 403 animation.pause(); 404 animation.pause(); 405 assertEquals(Status.PAUSED, animation.getStatus()); 406 assertEquals(0.0, animation.getCurrentRate(), EPSILON); 407 assertFalse(timer.containsPulseReceiver(animation.pulseReceiver)); 408 } 409 410 @Test 411 public void testStart() { 412 // cycleDuration = 1000ms 413 assertTrue(animation.impl_startable(true)); 414 animation.impl_start(true); 415 assertEquals(Status.RUNNING, animation.getStatus()); 416 assertEquals(1.0, animation.getCurrentRate(), EPSILON); 417 assertEquals(6000, clipEnvelope.getTimelineTicks()); 418 assertEquals(1.0, clipEnvelope.getRate(), EPSILON); 419 assertEquals(false, clipEnvelope.getAutoReverse()); 420 assertEquals(1, clipEnvelope.getCycleCount()); 421 animation.impl_finished(); 422 423 // change all values and try again 424 animation.setCycleDuration(TWO_SECS); 425 animation.setRate(-2.0); 426 animation.setAutoReverse(true); 427 animation.setCycleCount(Animation.INDEFINITE); 428 assertTrue(animation.impl_startable(true)); 429 animation.impl_start(true); 430 assertEquals(Status.RUNNING, animation.getStatus()); 431 assertEquals(-2.0, animation.getCurrentRate(), EPSILON); 432 assertEquals(12000, clipEnvelope.getTimelineTicks()); 433 assertEquals(-2.0, clipEnvelope.getRate(), EPSILON); 434 assertEquals(true, clipEnvelope.getAutoReverse()); 435 assertEquals(Animation.INDEFINITE, clipEnvelope.getCycleCount()); 436 animation.impl_finished(); 437 438 // cycleDuration = 0 439 animation.setCycleDuration(Duration.ZERO); 440 assertFalse(animation.impl_startable(true)); 441 } 442 443 @Test 444 public void testChangeCycleDurationAfterFinish_RT32657() { 445 animation.setCycleDuration(TWO_SECS); 446 animation.play(); 447 assertEquals(Status.RUNNING, animation.getStatus()); 448 assertEquals(Duration.ZERO, animation.getCurrentTime()); 449 animation.impl_setCurrentTicks(12000); 450 assertEquals(TWO_SECS, animation.getCurrentTime()); 451 animation.impl_finished(); 452 453 animation.setCycleDuration(ONE_SEC); 454 animation.play(); 455 assertEquals(Status.RUNNING, animation.getStatus()); 456 assertEquals(Duration.ZERO, animation.getCurrentTime()); 457 } 458 459 @Test 460 public void testFinished() { 461 final OnFinishedListener listener = new OnFinishedListener(); 462 animation.setOnFinished(listener); 463 464 // stopped timeline 465 animation.impl_finished(); 466 assertEquals(Status.STOPPED, animation.getStatus()); 467 assertEquals(0.0, animation.getCurrentRate(), EPSILON); 468 assertTrue(listener.wasCalled); 469 470 // playing timeline 471 animation.play(); 472 animation.impl_finished(); 473 assertEquals(Status.STOPPED, animation.getStatus()); 474 assertEquals(0.0, animation.getCurrentRate(), EPSILON); 475 assertTrue(listener.wasCalled); 476 477 // paused timeline 478 animation.play(); 479 animation.pause(); 480 animation.impl_finished(); 481 assertEquals(Status.STOPPED, animation.getStatus()); 482 assertEquals(0.0, animation.getCurrentRate(), EPSILON); 483 assertTrue(listener.wasCalled); 484 } 485 486 @Test 487 public void testFinished_ThrowsException() { 488 final OnFinishedExceptionListener listener = new OnFinishedExceptionListener(); 489 final PrintStream defaultErrorStream = System.err; 490 final PrintStream nirvana = new PrintStream(new OutputStream() { 491 @Override 492 public void write(int i) throws IOException { 493 } 494 }); 495 animation.setOnFinished(listener); 496 497 // stopped timeline 498 try { 499 System.setErr(nirvana); 500 } catch (SecurityException ex) { 501 // ignore 502 } 503 animation.impl_finished(); 504 try { 505 System.setErr(defaultErrorStream); 506 } catch (SecurityException ex) { 507 // ignore 508 } 509 assertEquals(Status.STOPPED, animation.getStatus()); 510 assertEquals(0.0, animation.getCurrentRate(), EPSILON); 511 assertTrue(listener.wasCalled); 512 513 // playing timeline 514 animation.play(); 515 try { 516 System.setErr(nirvana); 517 } catch (SecurityException ex) { 518 // ignore 519 } 520 animation.impl_finished(); 521 try { 522 System.setErr(defaultErrorStream); 523 } catch (SecurityException ex) { 524 // ignore 525 } 526 assertEquals(Status.STOPPED, animation.getStatus()); 527 assertEquals(0.0, animation.getCurrentRate(), EPSILON); 528 assertTrue(listener.wasCalled); 529 530 // paused timeline 531 animation.play(); 532 animation.pause(); 533 try { 534 System.setErr(nirvana); 535 } catch (SecurityException ex) { 536 // ignore 537 } 538 animation.impl_finished(); 539 try { 540 System.setErr(defaultErrorStream); 541 } catch (SecurityException ex) { 542 // ignore 543 } 544 assertEquals(Status.STOPPED, animation.getStatus()); 545 assertEquals(0.0, animation.getCurrentRate(), EPSILON); 546 assertTrue(listener.wasCalled); 547 } 548 549 @Test 550 public void testFullSpeedResolution() { 551 final int resolution = Toolkit.getToolkit().getMasterTimer().getDefaultResolution(); 552 553 // send pulse 554 animation.impl_timePulse(4 * resolution); 555 assertEquals(4 * resolution, clipEnvelope.getLastTimePulse()); 556 557 // send half pulse 558 animation.impl_timePulse(Math.round(4.5 * resolution)); 559 assertEquals(Math.round(4.5 * resolution), clipEnvelope.getLastTimePulse()); 560 561 // send full pulse 562 animation.impl_timePulse(Math.round(5.5 * resolution)); 563 assertEquals(Math.round(5.5 * resolution), clipEnvelope.getLastTimePulse()); 564 565 // send half pulse 566 animation.impl_timePulse(6 * resolution); 567 assertEquals(6 * resolution, clipEnvelope.getLastTimePulse()); 568 569 } 570 571 @Test 572 public void testCustomResolution() { 573 final int resolution = 100; 574 animation = new AnimationImpl(timer, clipEnvelope, resolution); 575 576 // send pulse 577 animation.impl_timePulse(4 * resolution); 578 assertEquals(4 * resolution, clipEnvelope.getLastTimePulse()); 579 580 // send half pulse 581 animation.impl_timePulse(Math.round(4.5 * resolution)); 582 assertEquals(0, clipEnvelope.getLastTimePulse()); 583 584 // send full pulse 585 animation.impl_timePulse(Math.round(5.5 * resolution)); 586 assertEquals(Math.round(5.5 * resolution), clipEnvelope.getLastTimePulse()); 587 588 // send half pulse, this time it should trigger a pulse 589 animation.impl_timePulse(6 * resolution); 590 assertEquals(6 * resolution, clipEnvelope.getLastTimePulse()); 591 592 } 593 594 private static class OnFinishedListener implements EventHandler<ActionEvent> { 595 596 private boolean wasCalled = false; 597 598 @Override 599 public void handle(ActionEvent event) { 600 wasCalled = true; 601 } 602 603 } 604 605 private static class OnFinishedExceptionListener implements EventHandler<ActionEvent> { 606 607 private boolean wasCalled = false; 608 609 @Override 610 public void handle(ActionEvent event) { 611 wasCalled = true; 612 throw new RuntimeException("Test Exception"); 613 } 614 615 } 616 617 }