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.scene;
  27 
  28 import com.sun.javafx.FXUnit;
  29 import javafx.beans.value.ChangeListener;
  30 import javafx.beans.value.ObservableValue;
  31 import javafx.scene.layout.StackPane;
  32 import javafx.scene.layout.TilePane;
  33 import javafx.scene.layout.VBox;
  34 import javafx.scene.shape.Rectangle;
  35 import javafx.scene.transform.Scale;
  36 import javafx.stage.Stage;
  37 import com.sun.javafx.pgstub.StubScene;
  38 import com.sun.javafx.pgstub.StubToolkit;
  39 import com.sun.javafx.sg.prism.NGCamera;
  40 import com.sun.javafx.test.MouseEventGenerator;
  41 import com.sun.javafx.tk.Toolkit;
  42 import javafx.application.Platform;
  43 import javafx.beans.InvalidationListener;
  44 import javafx.beans.Observable;
  45 import javafx.scene.input.MouseEvent;
  46 import org.junit.After;
  47 import org.junit.Before;
  48 import org.junit.Rule;
  49 import org.junit.Test;
  50 import static org.junit.Assert.assertEquals;
  51 import static org.junit.Assert.assertFalse;
  52 import static org.junit.Assert.assertNull;
  53 import static org.junit.Assert.assertSame;
  54 import static org.junit.Assert.assertTrue;
  55 import static org.junit.Assert.fail;
  56 
  57 /**
  58  * Tests various aspects of Scene.
  59  *
  60  */
  61 public class SceneTest {
  62 
  63     @Rule
  64     public FXUnit fx = new FXUnit();
  65 
  66     private Stage stage;
  67     private boolean handler1Called = false;
  68     private boolean handler2Called = false;
  69 
  70 
  71     @Before
  72     public void setUp() {
  73         stage = new Stage();
  74         stage.show();
  75         stage.requestFocus();
  76     }
  77 
  78     @After
  79     public void tearDown() {
  80         stage.hide();
  81     }
  82 
  83     /***************************************************************************
  84      *                                                                         *
  85      *                           Lookup related tests                          *
  86      *                                                                         *
  87      **************************************************************************/
  88     @Test
  89     public void testLookupCorrectId() {
  90         Node n;
  91         Group root = new Group();
  92         Scene scene = new Scene(root);
  93         Rectangle a = new Rectangle(); a.setId("a");
  94         Rectangle b = new Rectangle(); a.setId("b");
  95         Rectangle c = new Rectangle(); a.setId("c");
  96         Group g = new Group();
  97         g.setId("d");
  98 
  99         Rectangle r1 = new Rectangle(); a.setId("1");
 100         Rectangle r2 = new Rectangle(); a.setId("2");
 101         Rectangle r3 = new Rectangle(); a.setId("3");
 102         n = new Rectangle(); n.setId("4");
 103         Rectangle r5 = new Rectangle(); a.setId("5");
 104         Rectangle r6 = new Rectangle(); a.setId("6");
 105 
 106         Rectangle e = new Rectangle(); a.setId("e");
 107         Rectangle f = new Rectangle(); a.setId("f");
 108 
 109         g.getChildren().addAll(r1,r2,r3,n,r5,r6);
 110 
 111         root.getChildren().addAll(a,b,c,g,e,f);
 112 
 113         assertEquals(n, scene.lookup("#4"));
 114     }
 115 
 116     @Test
 117     public void testLookupBadId() {
 118         Node n;
 119         Group root = new Group();
 120         Scene scene = new Scene(root);
 121         Rectangle a = new Rectangle(); a.setId("a");
 122         Rectangle b = new Rectangle(); a.setId("b");
 123         Rectangle c = new Rectangle(); a.setId("c");
 124         Group g = new Group();
 125         g.setId("d");
 126 
 127         Rectangle r1 = new Rectangle(); a.setId("1");
 128         Rectangle r2 = new Rectangle(); a.setId("2");
 129         Rectangle r3 = new Rectangle(); a.setId("3");
 130         n = new Rectangle(); n.setId("4");
 131         Rectangle r5 = new Rectangle(); a.setId("5");
 132         Rectangle r6 = new Rectangle(); a.setId("6");
 133 
 134         Rectangle e = new Rectangle(); a.setId("e");
 135         Rectangle f = new Rectangle(); a.setId("f");
 136 
 137         g.getChildren().addAll(r1,r2,r3,n,r5,r6);
 138 
 139         root.getChildren().addAll(a,b,c,g,e,f);
 140 
 141         assertNull(scene.lookup("#4444"));
 142     }
 143 
 144     /***************************************************************************
 145      *                                                                         *
 146      *                          Scene Content Tests                            *
 147      *                                                                         *
 148      **************************************************************************/
 149     @Test
 150     public void isOnFxAppThread() {
 151         assertTrue(Platform.isFxApplicationThread());
 152     }
 153 
 154     @Test(expected=NullPointerException.class)
 155     public void testNullRoot() {
 156         Scene scene = new Scene(null);
 157     }
 158 
 159     @Test(expected=NullPointerException.class)
 160     public void testSetNullRoot() {
 161         Scene scene = new Scene(new Group());
 162         scene.setRoot(null);
 163     }
 164 
 165     @Test
 166     public void testRootInitializedInConstructor() {
 167         Group g = new Group();
 168         Scene scene = new Scene(g);
 169 
 170         assertEquals(g, scene.getRoot());
 171         assertEquals(scene, g.getScene());
 172     }
 173 
 174     @Test
 175     public void testDepthBufferInitializedInConstructor() {
 176         Group g = new Group();
 177         Scene scene = new Scene(g, 100, 100, true);
 178 
 179         assertTrue(scene.isDepthBuffer());
 180     }
 181 
 182     @Test
 183     public void testRootUpdatedWhenAddedToScene() {
 184         Scene scene = new Scene(new Group());
 185 
 186         Group g = new Group();
 187         scene.setRoot(g);
 188 
 189         assertEquals(g, scene.getRoot());
 190         assertEquals(scene, g.getScene());
 191     }
 192 
 193     @Test
 194     public void testRootUpdatedWhenChangedInScene() {
 195         Group g = new Group();
 196         Scene scene = new Scene(g);
 197 
 198         Group g2 = new Group();
 199         scene.setRoot(g2);
 200 
 201         assertNull(g.getScene());
 202         assertEquals(g2, scene.getRoot());
 203         assertEquals(scene, g2.getScene());
 204     }
 205 
 206     @Test
 207     public void testNodeUpdatedWhenAddedToScene() {
 208         Group root = new Group();
 209         Scene scene = new Scene(root);
 210         Rectangle rect = new Rectangle();
 211 
 212         assertNull(rect.getScene());
 213 
 214         root.getChildren().add(rect);
 215 
 216         assertEquals(scene, rect.getScene());
 217     }
 218 
 219     @Test
 220     public void testNodeUpdatedWhenRemovedFromScene() {
 221         Rectangle rect;
 222         Group root = new Group();
 223         Scene scene = new Scene(root);
 224         root.getChildren().add(rect = new Rectangle());
 225 
 226         assertEquals(scene, rect.getScene());
 227 
 228         root.getChildren().remove(rect);
 229 
 230         assertNull(rect.getScene());
 231     }
 232 
 233     @Test
 234     public void testNodeTreeUpdatedWhenAddedToScene() {
 235         Rectangle rect;
 236         Group root = new Group();
 237         Scene scene = new Scene(root);
 238         Group g = new Group();
 239 
 240         g.getChildren().add(rect = new Rectangle());
 241 
 242         assertNull(rect.getScene());
 243         assertNull(g.getScene());
 244 
 245         root.getChildren().add(g);
 246 
 247         assertEquals(scene, g.getScene());
 248         assertEquals(scene, rect.getScene());
 249     }
 250 
 251     @Test
 252     public void testNodeTreeUpdatedWhenRemovedFromScene() {
 253         Rectangle rect;
 254         Group g;
 255         Group root = new Group();
 256         Scene scene = new Scene(root);
 257         root.getChildren().add(g = new Group());
 258 
 259         g.getChildren().add(rect = new Rectangle());
 260 
 261         assertEquals(scene, g.getScene());
 262         assertEquals(scene, rect.getScene());
 263 
 264         root.getChildren().remove(g);
 265 
 266         assertNull(rect.getScene());
 267         assertNull(g.getScene());
 268     }
 269 
 270     @Test
 271     public void testNodeTreeUpdatedWhenAddedToChildOfScene() {
 272         Group parentGroup;
 273         Group root = new Group();
 274         Scene scene = new Scene(root);
 275         root.getChildren().add(parentGroup = new Group());
 276 
 277         Rectangle rect;
 278         Group childGroup = new Group();
 279         childGroup.getChildren().add(rect = new Rectangle());
 280 
 281         assertNull(rect.getScene());
 282         assertNull(childGroup.getScene());
 283         assertEquals(scene, parentGroup.getScene());
 284 
 285         parentGroup.getChildren().add(childGroup);
 286 
 287         assertEquals(scene, rect.getScene());
 288         assertEquals(scene, childGroup.getScene());
 289         assertEquals(scene, parentGroup.getScene());
 290     }
 291 
 292     @Test
 293     public void testNodeTreeUpdatedWhenRemovedFromChildOfScene() {
 294         Group parentGroup;
 295         Group root = new Group();
 296         Scene scene = new Scene(root);
 297         root.getChildren().add(parentGroup = new Group());
 298 
 299         Rectangle rect;
 300         Group childGroup = new Group();
 301         parentGroup.getChildren().add(childGroup);
 302         childGroup.getChildren().add(rect = new Rectangle());
 303 
 304         assertEquals(scene, rect.getScene());
 305         assertEquals(scene, childGroup.getScene());
 306         assertEquals(scene, parentGroup.getScene());
 307 
 308         parentGroup.getChildren().remove(childGroup);
 309 
 310         assertNull(rect.getScene());
 311         assertNull(childGroup.getScene());
 312         assertEquals(scene, parentGroup.getScene());
 313     }
 314 
 315     @Test
 316     public void testSceneSizeSetWhenNotInitialized() {
 317         Group g = new Group();
 318 
 319         Rectangle r = new Rectangle();
 320         r.setX(-20);
 321         r.setY(-20);
 322         r.setWidth(200);
 323         r.setHeight(200);
 324         g.getChildren().add(r);
 325 
 326         Scene scene = new Scene(g);
 327         stage.setScene(scene);
 328 
 329         assertEquals(180, (int) scene.getWidth());
 330         assertEquals(180, (int) scene.getHeight());
 331     }
 332 
 333     @Test
 334     public void testSceneSizeSetWithEffectOnRoot() {
 335         Group g = new Group();
 336 
 337         g.setEffect(new javafx.scene.effect.DropShadow());
 338 
 339         Rectangle r = new Rectangle();
 340         r.setX(-20);
 341         r.setY(-20);
 342         g.getChildren().add(r);
 343         r.setWidth(200);
 344         r.setHeight(200);
 345 
 346         Scene scene = new Scene(g);
 347         stage.setScene(scene);
 348 
 349         assertEquals(189, (int) scene.getWidth());
 350         assertEquals(189, (int) scene.getHeight());
 351     }
 352 
 353     @Test
 354     public void testSceneSizeSetWithClipOnRoot() {
 355         Group g = new Group();
 356 
 357         Rectangle clip = new Rectangle();
 358         clip.setX(20); clip.setY(20); clip.setWidth(150); clip.setHeight(150);
 359 
 360         g.setClip(clip);
 361 
 362         Rectangle r = new Rectangle();
 363 
 364         r.setX(20);
 365         r.setY(20);
 366         g.getChildren().add(r);
 367         r.setWidth(200);
 368         r.setHeight(200);
 369 
 370         Scene scene = new Scene(g);
 371         stage.setScene(scene);
 372 
 373         assertEquals(170,(int) scene.getWidth());
 374         assertEquals(170, (int) scene.getHeight());
 375 
 376     }
 377 
 378     @Test
 379     public void testSceneSizeSetWithTransformOnRoot() {
 380         Group g = new Group();
 381 
 382         Scale s = new Scale(); s.setX(2.0f); s.setY(2.0f);
 383         Rectangle r = new Rectangle();
 384         r.setX(-20);
 385         r.setY(-20);
 386         g.getChildren().add(r);
 387         r.setWidth(200);
 388         r.setHeight(200);
 389 
 390         g.getTransforms().add(s);
 391         Scene scene = new Scene(g);
 392         stage.setScene(scene);
 393 
 394         assertEquals(360,(int) scene.getWidth());
 395         assertEquals(360, (int) scene.getHeight());
 396     }
 397 
 398     @Test
 399     public void testSceneSizeSetWithScaleOnRoot() {
 400         Group g = new Group();
 401 
 402         g.setScaleX(2);
 403         g.setScaleY(2);
 404         Rectangle r = new Rectangle();
 405         r.setX(-20);
 406         r.setY(-20);
 407         r.setWidth(200);
 408         r.setHeight(200);
 409         g.getChildren().add(r);
 410 
 411         Scene scene = new Scene(g);
 412         stage.setScene(scene);
 413 
 414         assertEquals(280,(int) scene.getWidth());
 415         assertEquals(280, (int) scene.getHeight());
 416     }
 417 
 418     @Test
 419     public void testSceneSizeSetWithRotationOnRoot() {
 420         Group g = new Group();
 421         g.setRotate(45);
 422         Rectangle r = new Rectangle();
 423         r.setX(-20);
 424         r.setY(-20);
 425         r.setWidth(200);
 426         r.setHeight(200);
 427         g.getChildren().add(r);
 428 
 429         Scene scene = new Scene(g);
 430         stage.setScene(scene);
 431 
 432         assertTrue(scene.getWidth() > 220.0f && scene.getWidth() < 222.0f);
 433         assertTrue(scene.getHeight() > 220.0f && scene.getHeight() < 222.0f);
 434     }
 435 
 436     @Test
 437     public void testSceneSizeSetWithTranslateOnRoot() {
 438         Group g = new Group();
 439 
 440         g.setTranslateX(10);
 441         g.setTranslateY(10);
 442         Rectangle r = new Rectangle();
 443         r.setX(-20);
 444         r.setY(-20);
 445         r.setWidth(200);
 446         r.setHeight(200);
 447         g.getChildren().add(r);
 448         Scene scene = new Scene(g);
 449         stage.setScene(scene);
 450 
 451         assertEquals(190, (int)scene.getWidth());
 452         assertEquals(190, (int)scene.getHeight());
 453     }
 454 
 455     @Test
 456     public void testSceneSizeSetWithResizableAsRoot() {
 457         StackPane st = new StackPane();
 458 
 459         Rectangle r = new Rectangle();
 460         r.setX(-20);
 461         r.setY(-20);
 462         r.setWidth(200);
 463         r.setHeight(200);
 464         st.getChildren().add(r);
 465 
 466         Scene scene = new Scene(st);
 467         stage.setScene(scene);
 468 
 469         assertEquals(200,(int) scene.getWidth());
 470         assertEquals(200, (int) scene.getHeight());
 471     }
 472 
 473     @Test
 474     public void testSceneSizeWhenWidthInitialized() {
 475         Group g = new Group();
 476 
 477         Rectangle r = new Rectangle();
 478         r.setX(-20);
 479         r.setY(-20);
 480         r.setWidth(100);
 481         r.setHeight(100);
 482         g.getChildren().add(r);
 483 
 484         Scene scene = new Scene(g, 200, -1);
 485         stage.setScene(scene);
 486 
 487         assertEquals(200,(int) scene.getWidth());
 488         assertEquals(80, (int) scene.getHeight());
 489     }
 490 
 491     @Test
 492     public void testSceneSizeWhenHeightInitialized() {
 493         Group g = new Group();
 494 
 495         Rectangle r = new Rectangle();
 496         r.setX(-20);
 497         r.setY(-20);
 498         r.setWidth(100);
 499         r.setHeight(100);
 500         g.getChildren().add(r);
 501 
 502         Scene scene = new Scene(g, -1, 300);
 503         stage.setScene(scene);
 504 
 505         assertEquals(80,(int) scene.getWidth());
 506         assertEquals(300,(int) scene.getHeight());
 507     }
 508 
 509     @Test
 510     public void testSceneSizeWhenWidthAndHeightInitialized() {
 511         Group g = new Group();
 512 
 513         Rectangle r = new Rectangle();
 514         r.setX(-20);
 515         r.setY(-20);
 516         r.setWidth(100);
 517         r.setHeight(100);
 518         g.getChildren().add(r);
 519 
 520         Scene scene = new Scene(g, 400, 400);
 521         stage.setScene(scene);
 522 
 523         assertEquals(400,(int) scene.getWidth());
 524         assertEquals(400, (int) scene.getHeight());
 525     }
 526 
 527     @Test
 528     public void testSceneSizeOverridesResizableRootPrefSize() {
 529         StackPane s = new StackPane();
 530 
 531         Rectangle r = new Rectangle();
 532         r.setX(-20);
 533         r.setY(-20);
 534         r.setWidth(100);
 535         r.setHeight(100);
 536         s.getChildren().add(r);
 537 
 538         Scene scene = new Scene(s, 600, 600);
 539         stage.setScene(scene);
 540 
 541         assertEquals(600, (int) scene.getWidth());
 542         assertEquals(600, (int) scene.getHeight());
 543     }
 544 
 545     @Test
 546     public void testSceneSizeWithContentBiasOnRoot() {
 547         Rectangle r1 = new Rectangle(20, 20);
 548         Rectangle r2 = new Rectangle(20, 20);
 549         Rectangle r3 = new Rectangle(100, 20);
 550 
 551         TilePane tilePane = new TilePane();
 552         tilePane.getChildren().addAll(r1, r2);
 553 
 554         final VBox root = new VBox();
 555         root.getChildren().addAll(tilePane, r3);
 556         Scene scene = new Scene(root);
 557         stage.setScene(scene);
 558 
 559         assertEquals(100, (int) scene.getWidth());
 560         assertEquals(40, (int) scene.getHeight());
 561     }
 562 
 563     @Test
 564     public void focusChangeShouldBeAtomic() {
 565         final Group root = new Group();
 566 
 567         final Rectangle r1 = new Rectangle();
 568         final Rectangle r2 = new Rectangle();
 569 
 570         root.getChildren().addAll(r1, r2);
 571         final Scene scene = new Scene(root, 600, 600);
 572         stage.setScene(scene);
 573 
 574         r1.requestFocus();
 575 
 576         assertTrue(r1.isFocused());
 577         assertFalse(r2.isFocused());
 578 
 579         handler1Called = false;
 580         handler2Called = true;
 581 
 582         r1.focusedProperty().addListener(new ChangeListener<Boolean>() {
 583             @Override
 584             public void changed(ObservableValue<? extends Boolean> arg0, Boolean arg1, Boolean focused) {
 585                 assertFalse(focused); // r1 is being defocused
 586                 assertTrue(r2.isFocused()); // r2 is already focused
 587                 handler1Called = true;
 588 
 589                 root.getChildren().remove(r2); // be evil: remove r2
 590             }
 591         });
 592 
 593         r2.focusedProperty().addListener(new ChangeListener<Boolean>() {
 594             @Override
 595             public void changed(ObservableValue<? extends Boolean> arg0, Boolean arg1, Boolean focused) {
 596                 assertTrue(focused); // r2 is being focused
 597                 assertFalse(r1.isFocused()); // r1 is already defocused
 598                 assertTrue(handler1Called); // r1 listener was called first
 599                 handler2Called = true;
 600                 // remove the listener otherwise thi final defocus calls it again
 601                 r2.focusedProperty().removeListener(this);
 602             }
 603         });
 604 
 605         r2.requestFocus();
 606         assertTrue(handler2Called); // both listeners were called
 607     }
 608 
 609     @Test
 610     public void testSetCamera() {
 611         Camera camera = new PerspectiveCamera();
 612         Scene scene = new Scene(new Group(camera));
 613         scene.setCamera(camera);
 614         assertEquals(scene.getCamera(), camera);
 615         scene.setCamera(camera);
 616     }
 617 
 618     @Test
 619     public void testGetDefaultCamera() {
 620         Scene scene = new Scene(new Group());
 621         assertNull(scene.getCamera());
 622     }
 623 
 624     @Test
 625     public void testSetNullCamera() {
 626         Scene scene = new Scene(new Group());
 627         scene.setCamera(null);
 628         assertNull(scene.getCamera());
 629     }
 630 
 631     @Test(expected = IllegalArgumentException.class)
 632     public void testSetIllegalCameraFromOtherScene() {
 633         Camera camera = new PerspectiveCamera();
 634 
 635         Scene scene1 = new Scene(new Group(camera));
 636         Scene scene2 = new Scene(new Group());
 637 
 638         scene1.setCamera(camera);
 639         scene2.setCamera(camera);
 640     }
 641 
 642     @Test(expected = IllegalArgumentException.class)
 643     public void testSetIllegalCameraFromItsSubScene() {
 644         Camera camera = new PerspectiveCamera();
 645 
 646         SubScene subScene = new SubScene(new Group(camera), 150, 150);
 647         Scene scene = new Scene(new Group(subScene));
 648 
 649         subScene.setCamera(camera);
 650         scene.setCamera(camera);
 651     }
 652 
 653     @Test(expected = IllegalArgumentException.class)
 654     public void testSetIllegalCameraFromOtherSubScene() {
 655         Camera camera = new PerspectiveCamera();
 656 
 657         Scene scene = new Scene(new Group());
 658 
 659         SubScene subScene = new SubScene(new Group(camera), 150, 150);
 660         Scene otherScene = new Scene(new Group(subScene));
 661 
 662         subScene.setCamera(camera);
 663         scene.setCamera(camera);
 664     }
 665 
 666     @Test(expected = IllegalArgumentException.class)
 667     public void testSetIllegalCameraFromSubScene() {
 668         Camera camera = new PerspectiveCamera();
 669 
 670         SubScene subScene = new SubScene(new Group(camera), 150, 150);
 671         Scene scene = new Scene(new Group());
 672 
 673         subScene.setCamera(camera);
 674         scene.setCamera(camera);
 675     }
 676 
 677     @Test(expected = IllegalArgumentException.class)
 678     public void testSetIllegalCameraFromNestedSubScene() {
 679         Camera camera = new PerspectiveCamera();
 680 
 681         SubScene nestedSubScene = new SubScene(new Group(camera), 100, 100);
 682         SubScene subScene = new SubScene(new Group(nestedSubScene), 150, 150);
 683         Scene scene = new Scene(new Group(subScene));
 684 
 685         nestedSubScene.setCamera(camera);
 686         scene.setCamera(camera);
 687     }
 688 
 689     @Test
 690     public void testCameraUpdatesPG() {
 691         Scene scene = new Scene(new Group(), 300, 200);
 692         Camera cam = new ParallelCamera();
 693         stage.setScene(scene);
 694 
 695         scene.setCamera(cam);
 696         Toolkit.getToolkit().firePulse();
 697 
 698         // verify it has correct owner
 699         cam.setNearClip(20);
 700         Toolkit.getToolkit().firePulse();
 701         NGCamera ngCamera = ((StubScene)scene.impl_getPeer()).getCamera();
 702         assertEquals(20, ngCamera.getNearClip(), 0.00001);
 703 
 704         scene.setCamera(null);
 705         Toolkit.getToolkit().firePulse();
 706         // verify owner was removed
 707         cam.setNearClip(30);
 708         Toolkit.getToolkit().firePulse();
 709         assertEquals(20, ngCamera.getNearClip(), 0.00001);
 710 
 711         scene.setCamera(cam);
 712         Toolkit.getToolkit().firePulse();
 713         // verify it has correct owner
 714         cam.setNearClip(40);
 715         Toolkit.getToolkit().firePulse();
 716         assertEquals(40, ngCamera.getNearClip(), 0.00001);
 717 
 718         NGCamera oldCam = ngCamera;
 719         scene.setCamera(new ParallelCamera());
 720         Toolkit.getToolkit().firePulse();
 721         // verify owner was removed
 722         cam.setNearClip(50);
 723         Toolkit.getToolkit().firePulse();
 724         ngCamera = scene.getCamera().impl_getPeer();
 725         assertEquals(40, oldCam.getNearClip(), 0.00001);
 726         assertEquals(0.1, ngCamera.getNearClip(), 0.00001);
 727     }
 728 
 729     @Test
 730     public void testDefaultCameraUpdatesPG() {
 731         Scene scene = new Scene(new Group(), 300, 200);
 732         stage.setScene(scene);
 733         Toolkit.getToolkit().firePulse();
 734         Camera cam = scene.getEffectiveCamera();
 735 
 736         cam.setNearClip(20);
 737         Toolkit.getToolkit().firePulse();
 738         NGCamera camera = ((StubScene)scene.impl_getPeer()).getCamera();
 739         assertEquals(20, camera.getNearClip(), 0.00001);
 740     }
 741 
 742     @Test(expected=IllegalArgumentException.class)
 743     public void scenesCannotShareCamera() {
 744         Scene scene = new Scene(new Group(), 300, 200);
 745         Scene scene2 = new Scene(new Group(), 300, 200);
 746         Camera cam = new ParallelCamera();
 747         scene.setCamera(cam);
 748         scene2.setCamera(cam);
 749     }
 750 
 751     @Test(expected=IllegalArgumentException.class)
 752     public void subSceneAndSceneCannotShareCamera() {
 753         SubScene sub = new SubScene(new Group(), 100, 100);
 754         Scene scene = new Scene(new Group(sub), 300, 200);
 755         Camera cam = new ParallelCamera();
 756         sub.setCamera(cam);
 757         scene.setCamera(cam);
 758     }
 759 
 760     @Test
 761     public void shouldBeAbleToSetCameraTwiceToScene() {
 762         Scene scene = new Scene(new Group(), 300, 200);
 763         Camera cam = new ParallelCamera();
 764         try {
 765             scene.setCamera(cam);
 766             scene.setCamera(cam);
 767         } catch (IllegalArgumentException e) {
 768             fail("It didn't allow to 'share' camera with myslef");
 769         }
 770     }
 771 
 772     @Test
 773     public void scenePropertyListenerShouldBeCalledForInitializedScene() {
 774         final Group root = new Group();
 775         final Rectangle rect = new Rectangle();
 776         root.getChildren().add(rect);
 777 
 778         root.sceneProperty().addListener(new InvalidationListener() {
 779             @Override public void invalidated(Observable o) {
 780                 root.getChildren().remove(rect);
 781             }
 782         });
 783 
 784         Scene scene = new Scene(root, 600, 450);
 785         // if there is no exception, the test passed
 786     }
 787 
 788     @Test
 789     public void testSceneCursorChangePropagatesToScenePeer() {
 790         final StubToolkit toolkit = (StubToolkit) Toolkit.getToolkit();
 791         final MouseEventGenerator generator = new MouseEventGenerator();
 792 
 793         final Scene scene = new Scene(new Group(), 300, 200);
 794         stage.setScene(scene);
 795         scene.impl_processMouseEvent(
 796                 generator.generateMouseEvent(MouseEvent.MOUSE_ENTERED,
 797                                              100, 100));
 798         toolkit.firePulse();
 799 
 800         scene.setCursor(Cursor.TEXT);
 801         assertTrue(toolkit.isPulseRequested());
 802         toolkit.firePulse();
 803 
 804         assertSame(Cursor.TEXT.getCurrentFrame(),
 805                    ((StubScene) scene.impl_getPeer()).getCursor());
 806     }
 807 
 808     @Test
 809     public void testNodeCursorChangePropagatesToScenePeer() {
 810         final StubToolkit toolkit = (StubToolkit) Toolkit.getToolkit();
 811         final MouseEventGenerator generator = new MouseEventGenerator();
 812 
 813         final Parent root = new Group(new Rectangle(300, 200));
 814         final Scene scene = new Scene(root, 300, 200);
 815         stage.setScene(scene);
 816         scene.impl_processMouseEvent(
 817                 generator.generateMouseEvent(MouseEvent.MOUSE_ENTERED,
 818                                              100, 100));
 819         toolkit.firePulse();
 820 
 821         root.setCursor(Cursor.TEXT);
 822         assertTrue(toolkit.isPulseRequested());
 823         toolkit.firePulse();
 824 
 825         assertSame(Cursor.TEXT.getCurrentFrame(),
 826                    ((StubScene) scene.impl_getPeer()).getCursor());
 827     }
 828 }