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