< prev index next >

modules/javafx.graphics/src/main/java/javafx/scene/Scene.java

Print this page
rev 10859 : 8195788: Remove obsolete javafx.jmx module
Reviewed-by:


  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.glass.ui.Application;
  29 import com.sun.glass.ui.Accessible;
  30 import com.sun.javafx.util.Logging;
  31 import com.sun.javafx.util.Utils;
  32 import com.sun.javafx.application.PlatformImpl;
  33 import com.sun.javafx.collections.TrackableObservableList;
  34 import com.sun.javafx.css.StyleManager;
  35 import com.sun.javafx.cursor.CursorFrame;
  36 import com.sun.javafx.event.EventQueue;
  37 import com.sun.javafx.geom.PickRay;
  38 import com.sun.javafx.geom.Vec3d;
  39 import com.sun.javafx.geom.transform.BaseTransform;
  40 import com.sun.javafx.perf.PerformanceTracker;
  41 import com.sun.javafx.runtime.SystemProperties;
  42 import com.sun.javafx.scene.CssFlags;
  43 import com.sun.javafx.scene.LayoutFlags;
  44 import com.sun.javafx.scene.SceneEventDispatcher;
  45 import com.sun.javafx.scene.SceneHelper;
  46 import com.sun.javafx.scene.input.DragboardHelper;
  47 import com.sun.javafx.scene.input.ExtendedInputMethodRequests;
  48 import com.sun.javafx.scene.input.InputEventUtils;
  49 import com.sun.javafx.scene.input.PickResultChooser;
  50 import com.sun.javafx.scene.traversal.Direction;
  51 import com.sun.javafx.scene.traversal.SceneTraversalEngine;
  52 import com.sun.javafx.scene.traversal.TopMostTraversalEngine;
  53 import com.sun.javafx.sg.prism.NGCamera;
  54 import com.sun.javafx.sg.prism.NGLightBase;
  55 import com.sun.javafx.tk.*;
  56 import com.sun.prism.impl.PrismSettings;
  57 
  58 import javafx.animation.KeyFrame;
  59 import javafx.animation.Timeline;
  60 import javafx.application.ConditionalFeature;
  61 import javafx.application.Platform;


 393                         public void preferredSize(Scene scene) {
 394                             scene.preferredSize();
 395                         }
 396 
 397                         @Override
 398                         public void disposePeer(Scene scene) {
 399                             scene.disposePeer();
 400                         }
 401 
 402                         @Override
 403                         public void initPeer(Scene scene) {
 404                             scene.initPeer();
 405                         }
 406 
 407                         @Override
 408                         public void setWindow(Scene scene, Window window) {
 409                             scene.setWindow(window);
 410                         }
 411 
 412                         @Override
 413                         public TKPulseListener getScenePulseListener(Scene scene) {
 414                             return scene.getScenePulseListener();
 415                         }
 416 
 417                         @Override
 418                         public TKScene getPeer(Scene scene) {
 419                             return scene.getPeer();
 420                         }
 421 
 422                         @Override
 423                         public void setAllowPGAccess(boolean flag) {
 424                             Scene.setAllowPGAccess(flag);
 425                         }
 426 
 427                         @Override
 428                         public void setPaused(boolean paused) {
 429                             Scene.paused = paused;
 430                         }
 431 
 432                         @Override
 433                         public void parentEffectiveOrientationInvalidated(
 434                                 final Scene scene) {
 435                             scene.parentEffectiveOrientationInvalidated();
 436                         }
 437 
 438                         @Override
 439                         public Camera getEffectiveCamera(Scene scene) {
 440                             return scene.getEffectiveCamera();
 441                         }
 442 
 443                         @Override
 444                         public Scene createPopupScene(Parent root) {
 445                             return new Scene(root) {
 446                                        @Override
 447                                        void doLayoutPass() {
 448                                            resizeRootToPreferredSize(getRoot());
 449                                            super.doLayoutPass();
 450                                        }
 451 
 452                                        @Override


 464                                 scene.transientFocusContainer = node;
 465                             }
 466                         }
 467 
 468                         @Override
 469                         public Accessible getAccessible(Scene scene) {
 470                             return scene.getAccessible();
 471                         }
 472                     });
 473         }
 474 
 475         // Reserve space for 30 nodes in the dirtyNodes set.
 476         private static final int MIN_DIRTY_CAPACITY = 30;
 477 
 478         // For debugging
 479         private static boolean inSynchronizer = false;
 480         private static boolean inMousePick = false;
 481         private static boolean allowPGAccess = false;
 482         private static int pgAccessCount = 0;
 483 
 484         // Flag set by the Toolkit when we are paused for JMX debugging
 485         private static boolean paused = false;
 486 
 487         /**
 488          * Used for debugging purposes. Returns true if we are in either the
 489          * mouse event code (picking) or the synchronizer, or if the scene is
 490          * not yet initialized,
 491          *
 492          */
 493         static boolean isPGAccessAllowed() {
 494             return inSynchronizer || inMousePick || allowPGAccess;
 495         }
 496 
 497         static void setAllowPGAccess(boolean flag) {
 498             if (Utils.assertionEnabled()) {
 499                 if (flag) {
 500                     pgAccessCount++;
 501                     allowPGAccess = true;
 502                 }
 503                 else {
 504                     if (pgAccessCount <= 0) {
 505                         throw new java.lang.AssertionError("*** pgAccessCount underflow");
 506                     }


 591         }
 592     }
 593 
 594     /**
 595      * The peer of this scene
 596      */
 597     private TKScene peer;
 598 
 599     /*
 600      * Get Scene's peer
 601      */
 602     TKScene getPeer() {
 603         return peer;
 604     }
 605 
 606     /**
 607      * The scene pulse listener that gets called on toolkit pulses
 608      */
 609     ScenePulseListener scenePulseListener = new ScenePulseListener();
 610 
 611     TKPulseListener getScenePulseListener() {
 612         if (SystemProperties.isDebug()) {
 613             return scenePulseListener;
 614         }
 615         return null;
 616     }
 617 
 618     private List<Runnable> preLayoutPulseListeners;
 619     private List<Runnable> postLayoutPulseListeners;
 620 
 621     /**
 622      * Adds a new scene pre layout pulse listener to this scene. Every time a pulse occurs,
 623      * this listener will be called on the JavaFX Application Thread directly
 624      * <strong>before</strong> the CSS and layout passes, and also before
 625      * any rendering is done for
 626      * this frame. This scene pulse listener is suitable for knowing when a
 627      * scenegraph pulse is happening and also for modifying the scenegraph
 628      * (as it is called before CSS and layout, so any changes made will be properly
 629      * styled and positioned).
 630      *
 631      * This method must be called on the JavaFX Application thread.
 632      *
 633      * @param r The Runnable to be called when the pulse occurs.
 634      *
 635      * @throws IllegalStateException if this method is called on a thread
 636      * other than the JavaFX Application Thread.
 637      *


1266     void setNeedsRepaint() {
1267         if (this.peer != null) {
1268             peer.entireSceneNeedsRepaint();
1269         }
1270     }
1271 
1272     // Process CSS and layout and sync the scene prior to the snapshot
1273     // operation of the given node for this scene (currently the node
1274     // is unused but could possibly be used in the future to optimize this)
1275     void doCSSLayoutSyncForSnapshot(Node node) {
1276         if (!sizeInitialized) {
1277             preferredSize();
1278         } else {
1279             doCSSPass();
1280         }
1281 
1282         // we do not need pulse in the snapshot code
1283         // because this scene can be stage-less
1284         doLayoutPass();
1285 
1286         if (!paused) {
1287             getRoot().updateBounds();
1288             if (peer != null) {
1289                 peer.waitForRenderingToComplete();
1290                 peer.waitForSynchronization();
1291                 try {
1292                     // Run the synchronizer while holding the render lock
1293                     scenePulseListener.synchronizeSceneNodes();
1294                 } finally {
1295                     peer.releaseSynchronization(false);
1296                 }
1297             } else {
1298                 scenePulseListener.synchronizeSceneNodes();
1299             }
1300         }
1301 
1302     }
1303 
1304     // Shared method for Scene.snapshot and Node.snapshot. It is static because
1305     // we might be doing a Node snapshot with a null scene
1306     static WritableImage doSnapshot(Scene scene,
1307             double x, double y, double w, double h,
1308             Node root, BaseTransform transform, boolean depthBuffer,
1309             Paint fill, Camera camera, WritableImage wimg) {
1310 
1311         Toolkit tk = Toolkit.getToolkit();
1312         Toolkit.ImageRenderingContext context = new Toolkit.ImageRenderingContext();
1313 
1314         int xMin = (int)Math.floor(x);
1315         int yMin = (int)Math.floor(y);
1316         int xMax = (int)Math.ceil(x + w);
1317         int yMax = (int)Math.ceil(y + h);
1318         int width = Math.max(xMax - xMin, 1);
1319         int height = Math.max(yMax - yMin, 1);
1320         if (wimg == null) {


1463      * explicitly by the application or implicitly (such as chart animation),
1464      * the snapshot will be rendered based on the state of the scene graph at
1465      * the moment the snapshot is taken and will not reflect any subsequent
1466      * animation changes.
1467      * </p>
1468      *
1469      * @param image the writable image that will be used to hold the rendered scene.
1470      * It may be null in which case a new WritableImage will be constructed.
1471      * If the image is non-null, the scene will be rendered into the
1472      * existing image.
1473      * In this case, the width and height of the image determine the area
1474      * that is rendered instead of the width and height of the scene.
1475      *
1476      * @throws IllegalStateException if this method is called on a thread
1477      *     other than the JavaFX Application Thread.
1478      *
1479      * @return the rendered image
1480      * @since JavaFX 2.2
1481      */
1482     public WritableImage snapshot(WritableImage image) {
1483         if (!paused) {
1484             Toolkit.getToolkit().checkFxUserThread();
1485         }
1486 
1487         return doSnapshot(image);
1488     }
1489 
1490     /**
1491      * Takes a snapshot of this scene at the next frame and calls the
1492      * specified callback method when the image is ready.
1493      * CSS and layout processing will be done for the scene prior to
1494      * rendering it.
1495      * The entire destination image is cleared using the fill {@code Paint}
1496      * of this scene. The nodes in the scene are then rendered to the image.
1497      * The point (0,0) in scene coordinates is mapped to (0,0) in the image.
1498      * If the image is smaller than the size of the scene, then the rendering
1499      * will be clipped by the image.
1500      *
1501      * <p>
1502      * This is an asynchronous call, which means that other
1503      * events or animation might be processed before the scene is rendered.
1504      * If any such events modify a node in the scene that modification will
1505      * be reflected in the rendered image (as it will also be reflected in




  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.glass.ui.Application;
  29 import com.sun.glass.ui.Accessible;
  30 import com.sun.javafx.util.Logging;
  31 import com.sun.javafx.util.Utils;
  32 import com.sun.javafx.application.PlatformImpl;
  33 import com.sun.javafx.collections.TrackableObservableList;
  34 import com.sun.javafx.css.StyleManager;
  35 import com.sun.javafx.cursor.CursorFrame;
  36 import com.sun.javafx.event.EventQueue;
  37 import com.sun.javafx.geom.PickRay;
  38 import com.sun.javafx.geom.Vec3d;
  39 import com.sun.javafx.geom.transform.BaseTransform;
  40 import com.sun.javafx.perf.PerformanceTracker;

  41 import com.sun.javafx.scene.CssFlags;
  42 import com.sun.javafx.scene.LayoutFlags;
  43 import com.sun.javafx.scene.SceneEventDispatcher;
  44 import com.sun.javafx.scene.SceneHelper;
  45 import com.sun.javafx.scene.input.DragboardHelper;
  46 import com.sun.javafx.scene.input.ExtendedInputMethodRequests;
  47 import com.sun.javafx.scene.input.InputEventUtils;
  48 import com.sun.javafx.scene.input.PickResultChooser;
  49 import com.sun.javafx.scene.traversal.Direction;
  50 import com.sun.javafx.scene.traversal.SceneTraversalEngine;
  51 import com.sun.javafx.scene.traversal.TopMostTraversalEngine;
  52 import com.sun.javafx.sg.prism.NGCamera;
  53 import com.sun.javafx.sg.prism.NGLightBase;
  54 import com.sun.javafx.tk.*;
  55 import com.sun.prism.impl.PrismSettings;
  56 
  57 import javafx.animation.KeyFrame;
  58 import javafx.animation.Timeline;
  59 import javafx.application.ConditionalFeature;
  60 import javafx.application.Platform;


 392                         public void preferredSize(Scene scene) {
 393                             scene.preferredSize();
 394                         }
 395 
 396                         @Override
 397                         public void disposePeer(Scene scene) {
 398                             scene.disposePeer();
 399                         }
 400 
 401                         @Override
 402                         public void initPeer(Scene scene) {
 403                             scene.initPeer();
 404                         }
 405 
 406                         @Override
 407                         public void setWindow(Scene scene, Window window) {
 408                             scene.setWindow(window);
 409                         }
 410 
 411                         @Override





 412                         public TKScene getPeer(Scene scene) {
 413                             return scene.getPeer();
 414                         }
 415 
 416                         @Override
 417                         public void setAllowPGAccess(boolean flag) {
 418                             Scene.setAllowPGAccess(flag);
 419                         }
 420 
 421                         @Override





 422                         public void parentEffectiveOrientationInvalidated(
 423                                 final Scene scene) {
 424                             scene.parentEffectiveOrientationInvalidated();
 425                         }
 426 
 427                         @Override
 428                         public Camera getEffectiveCamera(Scene scene) {
 429                             return scene.getEffectiveCamera();
 430                         }
 431 
 432                         @Override
 433                         public Scene createPopupScene(Parent root) {
 434                             return new Scene(root) {
 435                                        @Override
 436                                        void doLayoutPass() {
 437                                            resizeRootToPreferredSize(getRoot());
 438                                            super.doLayoutPass();
 439                                        }
 440 
 441                                        @Override


 453                                 scene.transientFocusContainer = node;
 454                             }
 455                         }
 456 
 457                         @Override
 458                         public Accessible getAccessible(Scene scene) {
 459                             return scene.getAccessible();
 460                         }
 461                     });
 462         }
 463 
 464         // Reserve space for 30 nodes in the dirtyNodes set.
 465         private static final int MIN_DIRTY_CAPACITY = 30;
 466 
 467         // For debugging
 468         private static boolean inSynchronizer = false;
 469         private static boolean inMousePick = false;
 470         private static boolean allowPGAccess = false;
 471         private static int pgAccessCount = 0;
 472 



 473         /**
 474          * Used for debugging purposes. Returns true if we are in either the
 475          * mouse event code (picking) or the synchronizer, or if the scene is
 476          * not yet initialized,
 477          *
 478          */
 479         static boolean isPGAccessAllowed() {
 480             return inSynchronizer || inMousePick || allowPGAccess;
 481         }
 482 
 483         static void setAllowPGAccess(boolean flag) {
 484             if (Utils.assertionEnabled()) {
 485                 if (flag) {
 486                     pgAccessCount++;
 487                     allowPGAccess = true;
 488                 }
 489                 else {
 490                     if (pgAccessCount <= 0) {
 491                         throw new java.lang.AssertionError("*** pgAccessCount underflow");
 492                     }


 577         }
 578     }
 579 
 580     /**
 581      * The peer of this scene
 582      */
 583     private TKScene peer;
 584 
 585     /*
 586      * Get Scene's peer
 587      */
 588     TKScene getPeer() {
 589         return peer;
 590     }
 591 
 592     /**
 593      * The scene pulse listener that gets called on toolkit pulses
 594      */
 595     ScenePulseListener scenePulseListener = new ScenePulseListener();
 596 







 597     private List<Runnable> preLayoutPulseListeners;
 598     private List<Runnable> postLayoutPulseListeners;
 599 
 600     /**
 601      * Adds a new scene pre layout pulse listener to this scene. Every time a pulse occurs,
 602      * this listener will be called on the JavaFX Application Thread directly
 603      * <strong>before</strong> the CSS and layout passes, and also before
 604      * any rendering is done for
 605      * this frame. This scene pulse listener is suitable for knowing when a
 606      * scenegraph pulse is happening and also for modifying the scenegraph
 607      * (as it is called before CSS and layout, so any changes made will be properly
 608      * styled and positioned).
 609      *
 610      * This method must be called on the JavaFX Application thread.
 611      *
 612      * @param r The Runnable to be called when the pulse occurs.
 613      *
 614      * @throws IllegalStateException if this method is called on a thread
 615      * other than the JavaFX Application Thread.
 616      *


1245     void setNeedsRepaint() {
1246         if (this.peer != null) {
1247             peer.entireSceneNeedsRepaint();
1248         }
1249     }
1250 
1251     // Process CSS and layout and sync the scene prior to the snapshot
1252     // operation of the given node for this scene (currently the node
1253     // is unused but could possibly be used in the future to optimize this)
1254     void doCSSLayoutSyncForSnapshot(Node node) {
1255         if (!sizeInitialized) {
1256             preferredSize();
1257         } else {
1258             doCSSPass();
1259         }
1260 
1261         // we do not need pulse in the snapshot code
1262         // because this scene can be stage-less
1263         doLayoutPass();
1264 

1265         getRoot().updateBounds();
1266         if (peer != null) {
1267             peer.waitForRenderingToComplete();
1268             peer.waitForSynchronization();
1269             try {
1270                 // Run the synchronizer while holding the render lock
1271                 scenePulseListener.synchronizeSceneNodes();
1272             } finally {
1273                 peer.releaseSynchronization(false);
1274             }
1275         } else {
1276             scenePulseListener.synchronizeSceneNodes();
1277         }

1278 
1279     }
1280 
1281     // Shared method for Scene.snapshot and Node.snapshot. It is static because
1282     // we might be doing a Node snapshot with a null scene
1283     static WritableImage doSnapshot(Scene scene,
1284             double x, double y, double w, double h,
1285             Node root, BaseTransform transform, boolean depthBuffer,
1286             Paint fill, Camera camera, WritableImage wimg) {
1287 
1288         Toolkit tk = Toolkit.getToolkit();
1289         Toolkit.ImageRenderingContext context = new Toolkit.ImageRenderingContext();
1290 
1291         int xMin = (int)Math.floor(x);
1292         int yMin = (int)Math.floor(y);
1293         int xMax = (int)Math.ceil(x + w);
1294         int yMax = (int)Math.ceil(y + h);
1295         int width = Math.max(xMax - xMin, 1);
1296         int height = Math.max(yMax - yMin, 1);
1297         if (wimg == null) {


1440      * explicitly by the application or implicitly (such as chart animation),
1441      * the snapshot will be rendered based on the state of the scene graph at
1442      * the moment the snapshot is taken and will not reflect any subsequent
1443      * animation changes.
1444      * </p>
1445      *
1446      * @param image the writable image that will be used to hold the rendered scene.
1447      * It may be null in which case a new WritableImage will be constructed.
1448      * If the image is non-null, the scene will be rendered into the
1449      * existing image.
1450      * In this case, the width and height of the image determine the area
1451      * that is rendered instead of the width and height of the scene.
1452      *
1453      * @throws IllegalStateException if this method is called on a thread
1454      *     other than the JavaFX Application Thread.
1455      *
1456      * @return the rendered image
1457      * @since JavaFX 2.2
1458      */
1459     public WritableImage snapshot(WritableImage image) {

1460         Toolkit.getToolkit().checkFxUserThread();

1461 
1462         return doSnapshot(image);
1463     }
1464 
1465     /**
1466      * Takes a snapshot of this scene at the next frame and calls the
1467      * specified callback method when the image is ready.
1468      * CSS and layout processing will be done for the scene prior to
1469      * rendering it.
1470      * The entire destination image is cleared using the fill {@code Paint}
1471      * of this scene. The nodes in the scene are then rendered to the image.
1472      * The point (0,0) in scene coordinates is mapped to (0,0) in the image.
1473      * If the image is smaller than the size of the scene, then the rendering
1474      * will be clipped by the image.
1475      *
1476      * <p>
1477      * This is an asynchronous call, which means that other
1478      * events or animation might be processed before the scene is rendered.
1479      * If any such events modify a node in the scene that modification will
1480      * be reflected in the rendered image (as it will also be reflected in


< prev index next >