< prev index next >

modules/swing/src/main/java/javafx/embed/swing/SwingNode.java

Print this page




 118  *             launch(args);
 119  *         }
 120  *     }
 121  * </pre>
 122  * @since JavaFX 8.0
 123  */
 124 public class SwingNode extends Node {
 125     static {
 126          // This is used by classes in different packages to get access to
 127          // private and package private methods.
 128         SwingNodeHelper.setSwingNodeAccessor(new SwingNodeHelper.SwingNodeAccessor() {
 129             @Override
 130             public NGNode doCreatePeer(Node node) {
 131                 return ((SwingNode) node).doCreatePeer();
 132             }
 133 
 134             @Override
 135             public void doUpdatePeer(Node node) {
 136                 ((SwingNode) node).doUpdatePeer();
 137             }
















 138         });
 139     }
 140 
 141     private double fxWidth;
 142     private double fxHeight;
 143 
 144     private int swingPrefWidth;
 145     private int swingPrefHeight;
 146     private int swingMaxWidth;
 147     private int swingMaxHeight;
 148     private int swingMinWidth;
 149     private int swingMinHeight;
 150 
 151     private volatile JComponent content;
 152     private volatile JLightweightFrame lwFrame;
 153     final JLightweightFrame getLightweightFrame() { return lwFrame; }
 154 
 155     private NGExternalNode peer;
 156 
 157     private final ReentrantLock paintLock = new ReentrantLock();


 382     @Override public boolean isResizable() {
 383         return true;
 384     }
 385 
 386     /**
 387      * Invoked by the {@code SwingNode}'s parent during layout to set the {@code SwingNode}'s
 388      * width and height. <b>Applications should not invoke this method directly</b>.
 389      * If an application needs to directly set the size of the {@code SwingNode}, it should
 390      * set the Swing component's minimum/preferred/maximum size constraints which will
 391      * be propagated correspondingly to the {@code SwingNode} and it's parent will honor those
 392      * settings during layout.
 393      *
 394      * @param width the target layout bounds width
 395      * @param height the target layout bounds height
 396      */
 397     @Override public void resize(final double width, final double height) {
 398         super.resize(width, height);
 399         if (width != this.fxWidth || height != this.fxHeight) {
 400             this.fxWidth = width;
 401             this.fxHeight = height;
 402             impl_geomChanged();
 403             NodeHelper.markDirty(this, DirtyBits.NODE_GEOMETRY);
 404             SwingFXUtils.runOnEDT(() -> {
 405                 if (lwFrame != null) {
 406                     locateLwFrame();
 407                 }
 408             });
 409         }
 410     }
 411 
 412     /**
 413      * Returns the {@code SwingNode}'s preferred width for use in layout calculations.
 414      * This value corresponds to the preferred width of the Swing component.
 415      *
 416      * @return the preferred width that the node should be resized to during layout
 417      */
 418     @Override
 419     public double prefWidth(double height) {
 420         return swingPrefWidth / getPlatformScaleX();
 421     }
 422 


 454     /**
 455      * Returns the {@code SwingNode}'s minimum width for use in layout calculations.
 456      * This value corresponds to the minimum width of the Swing component.
 457      *
 458      * @return the minimum width that the node should be resized to during layout
 459      */
 460     @Override public double minWidth(double height) {
 461         return swingMinWidth / getPlatformScaleX();
 462     }
 463 
 464     /**
 465      * Returns the {@code SwingNode}'s minimum height for use in layout calculations.
 466      * This value corresponds to the minimum height of the Swing component.
 467      *
 468      * @return the minimum height that the node should be resized to during layout
 469      */
 470     @Override public double minHeight(double width) {
 471         return swingMinHeight / getPlatformScaleY();
 472     }
 473 
 474     /**
 475      * @treatAsPrivate implementation detail
 476      * @deprecated This is an internal API that is not intended for use and will be removed in the next version
 477      */
 478     @Deprecated
 479     @Override
 480     protected boolean impl_computeContains(double localX, double localY) {
 481         return true;
 482     }
 483 
 484     private final InvalidationListener locationListener = observable -> {
 485         locateLwFrame();
 486     };
 487 
 488     private final EventHandler<FocusUngrabEvent> ungrabHandler = event -> {
 489         if (!skipBackwardUnrgabNotification) {
 490             if (lwFrame != null) {
 491                 AccessController.doPrivileged(new PostEventAction(new UngrabEvent(lwFrame)));
 492             }
 493         }
 494     };
 495 
 496     private final ChangeListener<Boolean> windowVisibleListener = (observable, oldValue, newValue) -> {
 497         if (!newValue) {
 498             disposeLwFrame();
 499         } else {
 500             setContent(content);


 563 
 564         if (getScene() != null) {
 565             addSceneListeners(getScene());
 566         }
 567 
 568         sceneProperty().addListener((observable, oldValue, newValue) -> {
 569             if (oldValue != null) {
 570                 // Removed from scene
 571                 removeSceneListeners(oldValue);
 572                 disposeLwFrame();
 573             }
 574             if (newValue != null) {
 575                 // Added to another scene
 576                 if (content != null && lwFrame == null) {
 577                     setContent(content);
 578                 }
 579                 addSceneListeners(newValue);
 580             }
 581         });
 582 
 583         impl_treeVisibleProperty().addListener((observable, oldValue, newValue) -> {
 584             setLwFrameVisible(newValue);
 585         });
 586 
 587         return peer;
 588     }
 589 
 590     /*
 591      * Note: This method MUST only be called via its accessor method.
 592      */
 593     private void doUpdatePeer() {
 594         if (NodeHelper.isDirty(this, DirtyBits.NODE_VISIBLE)
 595                 || NodeHelper.isDirty(this, DirtyBits.NODE_BOUNDS)) {
 596             locateLwFrame(); // initialize location
 597         }
 598         if (NodeHelper.isDirty(this, DirtyBits.NODE_CONTENTS)) {
 599             peer.markContentDirty();
 600         }
 601     }
 602 
 603     /**


 677             if (lwFrame != null) {
 678                 lwFrame.setVisible(visible);
 679             }
 680         });
 681     }
 682 
 683     private void setLwFrameScale(final int scale) {
 684         if (lwFrame == null) {
 685             return;
 686         }
 687         SwingFXUtils.runOnEDT(new Runnable() {
 688             @Override
 689             public void run() {
 690                 if (lwFrame != null) {
 691                     jlfNotifyDisplayChanged.invoke(lwFrame, scale);
 692                 }
 693             }
 694         });
 695     }
 696 
 697     /**
 698      * @treatAsPrivate implementation detail
 699      * @deprecated This is an internal API that is not intended for use and will be removed in the next version
 700      */
 701     @Deprecated
 702     @Override
 703     public BaseBounds impl_computeGeomBounds(BaseBounds bounds, BaseTransform tx) {
 704         bounds.deriveWithNewBounds(0, 0, 0, (float)fxWidth, (float)fxHeight, 0);
 705         tx.transform(bounds, bounds);
 706         return bounds;
 707     }
 708 
 709     /**
 710      * @treatAsPrivate implementation detail
 711      * @deprecated This is an internal API that is not intended for use and will be removed in the next version
 712      */
 713     @Deprecated
 714     @Override
 715     public Object impl_processMXNode(MXNodeAlgorithm alg, MXNodeAlgorithmContext ctx) {
 716         return alg.processLeafNode(this, ctx);
 717     }
 718 
 719     private class SwingNodeContent implements LightweightContent {
 720         private JComponent comp;
 721         private volatile FXDnD dnd;
 722 
 723         public SwingNodeContent(JComponent comp) {
 724             this.comp = comp;
 725         }
 726         @Override
 727         public JComponent getComponent() {
 728             return comp;
 729         }
 730         @Override
 731         public void paintLock() {
 732             paintLock.lock();
 733         }
 734         @Override
 735         public void paintUnlock() {


 763 
 764                 if (getScene() != null &&
 765                         getScene().getWindow() != null &&
 766                         WindowHelper.getPeer(getScene().getWindow()) != null) {
 767                     WindowHelper.getPeer(getScene().getWindow()).grabFocus();
 768                     grabbed = true;
 769                 }
 770             });
 771         }
 772         @Override
 773         public void focusUngrabbed() {
 774             SwingFXUtils.runOnFxThread(() -> {
 775                 ungrabFocus(false);
 776             });
 777         }
 778         @Override
 779         public void preferredSizeChanged(final int width, final int height) {
 780             SwingFXUtils.runOnFxThread(() -> {
 781                 SwingNode.this.swingPrefWidth = width;
 782                 SwingNode.this.swingPrefHeight = height;
 783                 SwingNode.this.impl_notifyLayoutBoundsChanged();
 784             });
 785         }
 786         @Override
 787         public void maximumSizeChanged(final int width, final int height) {
 788             SwingFXUtils.runOnFxThread(() -> {
 789                 SwingNode.this.swingMaxWidth = width;
 790                 SwingNode.this.swingMaxHeight = height;
 791                 SwingNode.this.impl_notifyLayoutBoundsChanged();
 792             });
 793         }
 794         @Override
 795         public void minimumSizeChanged(final int width, final int height) {
 796             SwingFXUtils.runOnFxThread(() -> {
 797                 SwingNode.this.swingMinWidth = width;
 798                 SwingNode.this.swingMinHeight = height;
 799                 SwingNode.this.impl_notifyLayoutBoundsChanged();
 800             });
 801         }
 802 
 803         //@Override
 804         public void setCursor(Cursor cursor) {
 805             SwingFXUtils.runOnFxThread(() -> {
 806                 SwingNode.this.setCursor(SwingCursors.embedCursorToCursor(cursor));
 807             });
 808         }
 809 
 810         private void initDnD() {
 811             // This is a part of AWT API, so the method may be invoked on any thread
 812             synchronized (SwingNodeContent.this) {
 813                 if (this.dnd == null) {
 814                     this.dnd = new FXDnD(SwingNode.this);
 815                 }
 816             }
 817         }
 818 
 819         //@Override




 118  *             launch(args);
 119  *         }
 120  *     }
 121  * </pre>
 122  * @since JavaFX 8.0
 123  */
 124 public class SwingNode extends Node {
 125     static {
 126          // This is used by classes in different packages to get access to
 127          // private and package private methods.
 128         SwingNodeHelper.setSwingNodeAccessor(new SwingNodeHelper.SwingNodeAccessor() {
 129             @Override
 130             public NGNode doCreatePeer(Node node) {
 131                 return ((SwingNode) node).doCreatePeer();
 132             }
 133 
 134             @Override
 135             public void doUpdatePeer(Node node) {
 136                 ((SwingNode) node).doUpdatePeer();
 137             }
 138 
 139             @Override
 140             public BaseBounds doComputeGeomBounds(Node node,
 141             BaseBounds bounds, BaseTransform tx) {
 142                 return ((SwingNode) node).doComputeGeomBounds(bounds, tx);
 143             }
 144 
 145             @Override
 146             public boolean doComputeContains(Node node, double localX, double localY) {
 147                 return ((SwingNode) node).doComputeContains(localX, localY);
 148             }
 149 
 150             @Override
 151             public Object doProcessMXNode(Node node, MXNodeAlgorithm alg, MXNodeAlgorithmContext ctx) {
 152                 return ((SwingNode) node).doProcessMXNode(alg, ctx);
 153             }
 154         });
 155     }
 156 
 157     private double fxWidth;
 158     private double fxHeight;
 159 
 160     private int swingPrefWidth;
 161     private int swingPrefHeight;
 162     private int swingMaxWidth;
 163     private int swingMaxHeight;
 164     private int swingMinWidth;
 165     private int swingMinHeight;
 166 
 167     private volatile JComponent content;
 168     private volatile JLightweightFrame lwFrame;
 169     final JLightweightFrame getLightweightFrame() { return lwFrame; }
 170 
 171     private NGExternalNode peer;
 172 
 173     private final ReentrantLock paintLock = new ReentrantLock();


 398     @Override public boolean isResizable() {
 399         return true;
 400     }
 401 
 402     /**
 403      * Invoked by the {@code SwingNode}'s parent during layout to set the {@code SwingNode}'s
 404      * width and height. <b>Applications should not invoke this method directly</b>.
 405      * If an application needs to directly set the size of the {@code SwingNode}, it should
 406      * set the Swing component's minimum/preferred/maximum size constraints which will
 407      * be propagated correspondingly to the {@code SwingNode} and it's parent will honor those
 408      * settings during layout.
 409      *
 410      * @param width the target layout bounds width
 411      * @param height the target layout bounds height
 412      */
 413     @Override public void resize(final double width, final double height) {
 414         super.resize(width, height);
 415         if (width != this.fxWidth || height != this.fxHeight) {
 416             this.fxWidth = width;
 417             this.fxHeight = height;
 418             NodeHelper.geomChanged(this);
 419             NodeHelper.markDirty(this, DirtyBits.NODE_GEOMETRY);
 420             SwingFXUtils.runOnEDT(() -> {
 421                 if (lwFrame != null) {
 422                     locateLwFrame();
 423                 }
 424             });
 425         }
 426     }
 427 
 428     /**
 429      * Returns the {@code SwingNode}'s preferred width for use in layout calculations.
 430      * This value corresponds to the preferred width of the Swing component.
 431      *
 432      * @return the preferred width that the node should be resized to during layout
 433      */
 434     @Override
 435     public double prefWidth(double height) {
 436         return swingPrefWidth / getPlatformScaleX();
 437     }
 438 


 470     /**
 471      * Returns the {@code SwingNode}'s minimum width for use in layout calculations.
 472      * This value corresponds to the minimum width of the Swing component.
 473      *
 474      * @return the minimum width that the node should be resized to during layout
 475      */
 476     @Override public double minWidth(double height) {
 477         return swingMinWidth / getPlatformScaleX();
 478     }
 479 
 480     /**
 481      * Returns the {@code SwingNode}'s minimum height for use in layout calculations.
 482      * This value corresponds to the minimum height of the Swing component.
 483      *
 484      * @return the minimum height that the node should be resized to during layout
 485      */
 486     @Override public double minHeight(double width) {
 487         return swingMinHeight / getPlatformScaleY();
 488     }
 489 
 490     /*
 491      * Note: This method MUST only be called via its accessor method.

 492      */
 493     private boolean doComputeContains(double localX, double localY) {


 494         return true;
 495     }
 496 
 497     private final InvalidationListener locationListener = observable -> {
 498         locateLwFrame();
 499     };
 500 
 501     private final EventHandler<FocusUngrabEvent> ungrabHandler = event -> {
 502         if (!skipBackwardUnrgabNotification) {
 503             if (lwFrame != null) {
 504                 AccessController.doPrivileged(new PostEventAction(new UngrabEvent(lwFrame)));
 505             }
 506         }
 507     };
 508 
 509     private final ChangeListener<Boolean> windowVisibleListener = (observable, oldValue, newValue) -> {
 510         if (!newValue) {
 511             disposeLwFrame();
 512         } else {
 513             setContent(content);


 576 
 577         if (getScene() != null) {
 578             addSceneListeners(getScene());
 579         }
 580 
 581         sceneProperty().addListener((observable, oldValue, newValue) -> {
 582             if (oldValue != null) {
 583                 // Removed from scene
 584                 removeSceneListeners(oldValue);
 585                 disposeLwFrame();
 586             }
 587             if (newValue != null) {
 588                 // Added to another scene
 589                 if (content != null && lwFrame == null) {
 590                     setContent(content);
 591                 }
 592                 addSceneListeners(newValue);
 593             }
 594         });
 595 
 596         NodeHelper.treeVisibleProperty(this).addListener((observable, oldValue, newValue) -> {
 597             setLwFrameVisible(newValue);
 598         });
 599 
 600         return peer;
 601     }
 602 
 603     /*
 604      * Note: This method MUST only be called via its accessor method.
 605      */
 606     private void doUpdatePeer() {
 607         if (NodeHelper.isDirty(this, DirtyBits.NODE_VISIBLE)
 608                 || NodeHelper.isDirty(this, DirtyBits.NODE_BOUNDS)) {
 609             locateLwFrame(); // initialize location
 610         }
 611         if (NodeHelper.isDirty(this, DirtyBits.NODE_CONTENTS)) {
 612             peer.markContentDirty();
 613         }
 614     }
 615 
 616     /**


 690             if (lwFrame != null) {
 691                 lwFrame.setVisible(visible);
 692             }
 693         });
 694     }
 695 
 696     private void setLwFrameScale(final int scale) {
 697         if (lwFrame == null) {
 698             return;
 699         }
 700         SwingFXUtils.runOnEDT(new Runnable() {
 701             @Override
 702             public void run() {
 703                 if (lwFrame != null) {
 704                     jlfNotifyDisplayChanged.invoke(lwFrame, scale);
 705                 }
 706             }
 707         });
 708     }
 709 
 710     /*
 711      * Note: This method MUST only be called via its accessor method.

 712      */
 713     private BaseBounds doComputeGeomBounds(BaseBounds bounds, BaseTransform tx) {


 714         bounds.deriveWithNewBounds(0, 0, 0, (float)fxWidth, (float)fxHeight, 0);
 715         tx.transform(bounds, bounds);
 716         return bounds;
 717     }
 718 
 719     /*
 720      * Note: This method MUST only be called via its accessor method.

 721      */
 722     private Object doProcessMXNode(MXNodeAlgorithm alg, MXNodeAlgorithmContext ctx) {


 723         return alg.processLeafNode(this, ctx);
 724     }
 725 
 726     private class SwingNodeContent implements LightweightContent {
 727         private JComponent comp;
 728         private volatile FXDnD dnd;
 729 
 730         public SwingNodeContent(JComponent comp) {
 731             this.comp = comp;
 732         }
 733         @Override
 734         public JComponent getComponent() {
 735             return comp;
 736         }
 737         @Override
 738         public void paintLock() {
 739             paintLock.lock();
 740         }
 741         @Override
 742         public void paintUnlock() {


 770 
 771                 if (getScene() != null &&
 772                         getScene().getWindow() != null &&
 773                         WindowHelper.getPeer(getScene().getWindow()) != null) {
 774                     WindowHelper.getPeer(getScene().getWindow()).grabFocus();
 775                     grabbed = true;
 776                 }
 777             });
 778         }
 779         @Override
 780         public void focusUngrabbed() {
 781             SwingFXUtils.runOnFxThread(() -> {
 782                 ungrabFocus(false);
 783             });
 784         }
 785         @Override
 786         public void preferredSizeChanged(final int width, final int height) {
 787             SwingFXUtils.runOnFxThread(() -> {
 788                 SwingNode.this.swingPrefWidth = width;
 789                 SwingNode.this.swingPrefHeight = height;
 790                 NodeHelper.notifyLayoutBoundsChanged(SwingNode.this);
 791             });
 792         }
 793         @Override
 794         public void maximumSizeChanged(final int width, final int height) {
 795             SwingFXUtils.runOnFxThread(() -> {
 796                 SwingNode.this.swingMaxWidth = width;
 797                 SwingNode.this.swingMaxHeight = height;
 798                 NodeHelper.notifyLayoutBoundsChanged(SwingNode.this);
 799             });
 800         }
 801         @Override
 802         public void minimumSizeChanged(final int width, final int height) {
 803             SwingFXUtils.runOnFxThread(() -> {
 804                 SwingNode.this.swingMinWidth = width;
 805                 SwingNode.this.swingMinHeight = height;
 806                 NodeHelper.notifyLayoutBoundsChanged(SwingNode.this);
 807             });
 808         }
 809 
 810         //@Override
 811         public void setCursor(Cursor cursor) {
 812             SwingFXUtils.runOnFxThread(() -> {
 813                 SwingNode.this.setCursor(SwingCursors.embedCursorToCursor(cursor));
 814             });
 815         }
 816 
 817         private void initDnD() {
 818             // This is a part of AWT API, so the method may be invoked on any thread
 819             synchronized (SwingNodeContent.this) {
 820                 if (this.dnd == null) {
 821                     this.dnd = new FXDnD(SwingNode.this);
 822                 }
 823             }
 824         }
 825 
 826         //@Override


< prev index next >