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 }