1 /* 2 * Copyright (c) 2013, 2018, 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 test.robot.javafx.embed.swing; 27 28 import static com.sun.javafx.application.PlatformImpl.runAndWait; 29 import com.sun.javafx.tk.TKPulseListener; 30 import java.awt.Color; 31 import javafx.animation.AnimationTimer; 32 import javafx.scene.Scene; 33 34 import javax.swing.SwingUtilities; 35 36 import javafx.application.Application; 37 import javafx.application.Platform; 38 import javafx.embed.swing.SwingNode; 39 import javafx.scene.layout.Background; 40 import javafx.scene.layout.BackgroundFill; 41 import javafx.scene.layout.Pane; 42 import javafx.scene.layout.StackPane; 43 import javafx.scene.robot.Robot; 44 import javafx.stage.Stage; 45 import javax.swing.JPanel; 46 47 /** 48 * RT-30650: SwingNode is not Resizable 49 * 50 * The scenario: SwingNode contains JPanel. It should be initialized with the same layout bounds. 51 * SwingNode is added to StackPane. The JPanel's max size is unbounded, so SwingNode is expected 52 * to fill the whole space. 53 */ 54 public class RT30650GUI extends Application { 55 SwingNode swingNode; 56 57 private final static int SIZE = 400; 58 59 // 100 pulses is not enough for the interop case, so we wait for 400 instead 60 private static int pulseCount = 400; 61 private static volatile boolean passed; 62 63 public static boolean test() { 64 launch(new String[]{}); 65 return passed; 66 } 67 68 private AnimationTimer animationTimer; 69 private TKPulseListener pulseListener; 70 71 @Override 72 public void start(final Stage stage) { 73 74 // start constant pulse activity 75 animationTimer = new AnimationTimer() { 76 @Override public void handle(long l) {} 77 }; 78 animationTimer.start(); 79 80 swingNode = new SwingNode(); 81 82 Pane pane = new StackPane(); 83 pane.setBackground(new Background(new BackgroundFill(javafx.scene.paint.Color.GREEN, null, null))); 84 pane.getChildren().add(swingNode); 85 Scene scene = new Scene(pane, SIZE, SIZE); 86 87 stage.setScene(scene); 88 stage.setTitle("RT-30650"); 89 stage.show(); 90 91 SwingUtilities.invokeLater(() -> { 92 JPanel panel = new JPanel(); 93 panel.setBackground(Color.RED); 94 swingNode.setContent(panel); 95 96 Platform.runLater(() -> { 97 pulseListener = () -> { 98 if (--pulseCount == 0) { 99 SwingUtilities.invokeLater(() -> { 100 passed = testColor(stage); 101 Platform.runLater(stage::close); 102 }); 103 } 104 }; 105 com.sun.javafx.tk.Toolkit.getToolkit().addSceneTkPulseListener(pulseListener); 106 }); 107 }); 108 } 109 110 public boolean testColor(Stage stage) { 111 int x = (int)stage.getX(); 112 int y = (int)stage.getY(); 113 114 final javafx.scene.paint.Color rgb[] = new javafx.scene.paint.Color[1]; 115 runAndWait(() -> { 116 Robot r = new Robot(); 117 rgb[0] = r.getPixelColor(x + SIZE/2, y + SIZE/2); 118 }); 119 120 System.out.println("detected color: " + rgb[0].toString()); 121 122 // On MacOSX the robot returns the color affected by the color profile. 123 // And so the resulting color may differ from the requested one. 124 // Here we have to check that the color is closer to red rather than to green. 125 return rgb[0].getRed() * 255d > 200 && rgb[0].getGreen() * 255d < 100; 126 } 127 }