jdk/test/javax/swing/JWindow/ShapedAndTranslucentWindows/Common.java
changeset 26601 2713482c0fd3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/swing/JWindow/ShapedAndTranslucentWindows/Common.java	Tue Aug 26 15:04:49 2014 +0400
@@ -0,0 +1,417 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import javax.swing.*;
+import javax.swing.border.EmptyBorder;
+import java.awt.*;
+import java.awt.event.*;
+import java.awt.geom.Area;
+import java.awt.geom.Rectangle2D;
+import java.awt.image.BufferedImage;
+import java.security.SecureRandom;
+
+public abstract class Common {
+
+    ExtendedRobot robot;
+    Class<? extends JFrame> windowClass;
+    JFrame background;
+    BufferedImage foreground;
+    Window window;
+    volatile boolean gradientBackgroundEnabled = false;
+    volatile int gradientWidth = 255;
+    volatile int gradientHeight = 255;
+
+    float opacity = 1.0f;
+    float perPixelTranslucency = 1.0f;
+    static Color BG_COLOR = Color.BLUE;
+    static Color FG_COLOR = Color.RED;
+    static final int delay = 1000;
+    static final SecureRandom random = new SecureRandom();
+    static final int dl = 100;
+    static final Class[] WINDOWS_TO_TEST = { JWindow.class, JFrame.class, JDialog.class };
+
+    volatile int clicked;
+
+    public Common(Class windowClass, float opacity, float perPixelTranslucency, boolean gradient) throws Exception {
+        this.gradientBackgroundEnabled = gradient;
+        this.perPixelTranslucency = perPixelTranslucency;
+        this.opacity = opacity;
+        robot = new ExtendedRobot();
+        this.windowClass = windowClass;
+        EventQueue.invokeAndWait(this::initBackgroundFrame);
+        EventQueue.invokeAndWait(this::initGUI);
+    }
+
+    public Common(Class windowClass) throws Exception {
+        this(windowClass, 1.0f, 1.0f, false);
+    }
+
+    public Common(Class windowClass, boolean gradient) throws Exception {
+        this(windowClass, 1.0f, 1.0f, gradient);
+    }
+
+    public abstract void doTest() throws Exception;
+
+    public void dispose() {
+        window.dispose();
+        background.dispose();
+    }
+
+    public void applyShape() {};
+
+    public void applyDynamicShape() {
+        final Area a = new Area();
+        Dimension size = window.getSize();
+        for (int x = 0; x < 3; x++) {
+            for (int y = 0; y < 3; y++) {
+                a.add(new Area(new Rectangle2D.Double(
+                        x * size.getWidth() / 17*6, y * size.getHeight() / 17*6,
+                        size.getWidth() / 17*5, size.getHeight() / 17*5)));
+            }
+        }
+        window.setShape(a);
+    }
+
+    public BufferedImage getForegroundWindow() throws Exception {
+        final BufferedImage f[] = new BufferedImage[1];
+        EventQueue.invokeAndWait( () -> {
+            f[0] = new BufferedImage(window.getWidth(),
+                    window.getHeight(), BufferedImage.TYPE_INT_RGB);
+            window.printAll(f[0].createGraphics());
+        });
+        robot.waitForIdle(delay);
+        return f[0];
+    }
+
+    public static boolean checkTranslucencyMode(GraphicsDevice.WindowTranslucency mode) {
+
+        if (!GraphicsEnvironment
+                .getLocalGraphicsEnvironment()
+                .getDefaultScreenDevice()
+                .isWindowTranslucencySupported(mode)){
+            System.out.println(mode+" translucency mode isn't supported");
+            return false;
+        } else {
+            return true;
+        }
+
+    }
+
+    public void applyAppDragNResizeSupport() {
+        MouseAdapter m = new MouseAdapter() {
+
+            private Point dragOrigin = null;
+            private Dimension origSize = null;
+            private Point origLoc = null;
+            private boolean left = false;
+            private boolean top = false;
+            private boolean bottom = false;
+            private boolean right = false;
+
+            public void mousePressed(MouseEvent e) {
+                dragOrigin = e.getLocationOnScreen();
+                origSize = window.getSize();
+                origLoc = window.getLocationOnScreen();
+                right = (origLoc.x + window.getWidth() - dragOrigin.x) < 5;
+                left = !right && dragOrigin.x - origLoc.x < 5;
+                bottom = (origLoc.y + window.getHeight() - dragOrigin.y) < 5;
+                top = !bottom && dragOrigin.y - origLoc.y < 5;
+            }
+
+            public void mouseReleased(MouseEvent e) { resize(e); }
+            public void mouseDragged(MouseEvent e) { resize(e); }
+
+            void resize(MouseEvent e) {
+                Point dragDelta = e.getLocationOnScreen();
+                dragDelta.translate(-dragOrigin.x, -dragOrigin.y);
+                Point newLoc = new Point(origLoc);
+                newLoc.translate(dragDelta.x, dragDelta.y);
+                Dimension newSize = new Dimension(origSize);
+                if (left || right) {
+                    newSize.width += right ? dragDelta.x : -dragDelta.x;
+                }
+                if (top || bottom) {
+                    newSize.height += bottom ? dragDelta.y : -dragDelta.y;
+                }
+                if (right || (top || bottom) && !left) {
+                    newLoc.x = origLoc.x;
+                }
+                if (bottom || (left || right) && !top) {
+                    newLoc.y = origLoc.y;
+                }
+                window.setBounds(newLoc.x, newLoc.y, newSize.width, newSize.height);
+            }
+        };
+        for (Component comp : window.getComponents()) {
+            comp.addMouseListener(m);
+            comp.addMouseMotionListener(m);
+        }
+
+        window.addMouseListener(m);
+        window.addMouseMotionListener(m);
+    }
+
+    public void checkTranslucentShape() throws Exception {
+        foreground = getForegroundWindow();
+        Point[] points = new Point[4];
+
+        Dimension size = window.getSize();
+        Point location = window.getLocationOnScreen();
+
+        points[0] = new Point(20, 20);
+        points[1] = new Point(20, size.height-20);
+        points[2] = new Point(size.width-20, 20);
+        points[3] = new Point(size.width-20, size.height-20);
+
+        for (Point p : points){
+            p.translate(location.x, location.y);
+            Color actual = robot.getPixelColor(p.x, p.y);
+            if (actual.equals(BG_COLOR)|| actual.equals(FG_COLOR))
+                throw new RuntimeException("Error in point "+p+": "+actual+" equals to foreground or background color");
+            else
+                System.out.println("OK with foreground point "+p);
+        }
+    }
+
+    public void checkDynamicShape() throws Exception {
+        Point[] points = new Point[4];
+
+        Dimension size = window.getSize();
+
+        int blockSizeX = (int) (size.getWidth() / 17);
+        int blockSizeY = (int) (size.getHeight() / 17);
+
+        // background
+        points[0] = new Point((int) (blockSizeX * 5.5), (int) (blockSizeY * 5.5));
+        points[1] = new Point((int) (size.getWidth() - blockSizeX * 5.5), (int) (size.getHeight() - blockSizeY * 5.5));
+        points[2] = new Point((int) (blockSizeX * 5.5), (int) (size.getHeight() - blockSizeY * 5.5));
+        points[3] = new Point((int) (size.getWidth() - blockSizeX * 5.5), (int) (blockSizeY * 5.5));
+        checkShape(points, true);
+
+        // foreground
+        if (opacity < 1.0f){
+            checkTranslucentShape();
+        } else {
+            points[0] = new Point(3 * blockSizeX, 3 * blockSizeY);
+            points[1] = new Point(14 * blockSizeX, 14 * blockSizeY);
+            points[2] = new Point(3 * blockSizeX, 14 * blockSizeY);
+            points[3] = new Point(14 * blockSizeX, 3 * blockSizeY);
+            checkShape(points, false);
+        }
+    }
+
+    public void checkShape(Point[] points, boolean areBackgroundPoints) throws Exception {
+
+        Point location = window.getLocationOnScreen();
+
+        for (Point p : points) {
+            p.translate(location.x, location.y);
+            Color pixel = robot.getPixelColor(p.x, p.y);
+            if (areBackgroundPoints) {
+                if (pixel.getRed() != 0
+                    || pixel.getGreen() != 0 )
+                    throw new RuntimeException("Background point " + p +
+                            " color " + pixel +
+                            " does not equal to background color " + BG_COLOR);
+                else
+                    System.out.println("OK with background point " + p);
+            } else {
+                if (pixel.equals(BG_COLOR))
+                    throw new RuntimeException("Foreground point " + p +
+                            " color " + pixel +
+                            " equals to background color " + BG_COLOR);
+                else
+                    System.out.println("OK with foreground point " + p);
+            }
+        }
+    }
+
+    public void initBackgroundFrame() {
+        background = new JFrame();
+        background.setUndecorated(true);
+        background.getContentPane().setBackground(BG_COLOR);
+        background.setSize(500, 500);
+        background.setLocation(dl, dl);
+        background.setVisible(true);
+    }
+
+    public void initGUI() {
+        Container contentPane;
+        if (windowClass.equals(Frame.class)) {
+            window = new JFrame();
+            ((JFrame) window).setUndecorated(true);
+            contentPane = ((JFrame) window).getContentPane();
+        } else  if (windowClass.equals(Dialog.class)) {
+            window = new JDialog(background);
+            ((JDialog) window).setUndecorated(true);
+            contentPane = ((JDialog) window).getContentPane();
+        } else {
+            window = new JWindow(background);
+            contentPane = ((JWindow) window).getContentPane();
+        }
+
+        if (perPixelTranslucency < 1.0f) {
+            contentPane.setBackground(colorWithOpacity(FG_COLOR, perPixelTranslucency));
+            window.setBackground(colorWithOpacity(FG_COLOR, perPixelTranslucency));
+        } else {
+            contentPane.setBackground(FG_COLOR);
+            window.setBackground(FG_COLOR);
+        }
+
+        window.setLocation(2 * dl, 2 * dl);
+        window.setSize(255, 255);
+        window.setPreferredSize(new Dimension(255, 255));
+        createSwingComponents();
+        if (opacity < 1.0f)
+            window.setOpacity(opacity);
+
+        window.addComponentListener(new ComponentAdapter() {
+            @Override
+            public void componentResized(ComponentEvent e) {
+                applyShape();
+            }
+        });
+        applyShape();
+        window.setVisible(true);
+        applyAppDragNResizeSupport();
+        window.toFront();
+    }
+
+    public void createSwingComponents() {
+        Container contentPane;
+        if (gradientBackgroundEnabled) {
+            JPanel jPanel = new JPanel() {
+                @Override
+                protected void paintComponent(Graphics g) {
+                    if (g instanceof Graphics2D) {
+                        Color background = Color.RED;
+                        Paint p = new GradientPaint(0.0f, 0.0f, colorWithOpacity(background, 0),
+                                0.0f, gradientHeight - 3, colorWithOpacity(background, 1), true);
+                        Graphics2D g2d = (Graphics2D) g;
+                        g2d.setPaint(p);
+                        g2d.fillRect(0, 3, gradientWidth, gradientHeight - 3);
+                    } else {
+                        super.paintComponent(g);
+                    }
+                }
+            };
+            jPanel.setBorder(new EmptyBorder(15, 5, 5, 5));
+            jPanel.setOpaque(false);
+
+            contentPane = jPanel;
+
+            RootPaneContainer.class.cast(window).setContentPane(contentPane);
+        } else {
+            contentPane = RootPaneContainer.class.cast(window).getContentPane();
+        }
+        contentPane.setLayout(new BoxLayout(contentPane, BoxLayout.Y_AXIS));
+
+        JButton button = new JButton("JButton");
+        window.add(button);
+
+        JTextArea textArea = new JTextArea("JTextArea");
+        window.add(textArea);
+
+        JCheckBox checkbox = new JCheckBox("JCheckBox");
+        checkbox.setOpaque(false);
+        window.add(checkbox);
+
+        JComboBox comboBox = new JComboBox(new String[]{"JComboBox", "Some item"});
+        window.add(comboBox);
+
+        JLabel label = new JLabel("JLabel");
+        window.add(label);
+
+        JTextField textField = new JTextField("JTextField");
+        window.add(textField);
+
+        JPanel panel = new JPanel();
+        panel.setOpaque(false);
+        window.add(panel);
+
+        JComboBox comboBox2 = new JComboBox(new String[]{"JComboBox2", "Another item"});
+        window.add(comboBox2);
+
+        JRadioButton radioButton = new JRadioButton("JRadioButton");
+        radioButton.setOpaque(false);
+        window.add(radioButton);
+    }
+
+    Color colorWithOpacity(Color color, float opacity) {
+        return new Color(color.getColorSpace(), color.getColorComponents(null), opacity);
+    }
+
+    public void checkTranslucent() throws Exception {
+        checkTranslucentShape();
+
+        // Drag
+        Point location = window.getLocationOnScreen();
+        robot.dragAndDrop(location.x + 30, location.y + 5, location.x + dl + random.nextInt(dl), location.y + random.nextInt(dl));
+        robot.waitForIdle(delay);
+        checkTranslucentShape();
+
+        // Resize
+        location = window.getLocationOnScreen();
+        robot.dragAndDrop(location.x + 4, location.y + 4, location.x + random.nextInt(2*dl)-dl, location.y + random.nextInt(2*dl)-dl);
+        robot.waitForIdle(delay);
+        checkTranslucentShape();
+
+        EventQueue.invokeAndWait(this::dispose);
+    }
+
+    public void checkDynamic() throws Exception {
+        checkDynamicShape();
+
+        // Drag
+        Point location = window.getLocationOnScreen();
+        robot.dragAndDrop(location.x + 30, location.y + 5, location.x + dl + random.nextInt(dl), location.y + random.nextInt(dl));
+        robot.waitForIdle(delay);
+        checkDynamicShape();
+
+        // Resize
+        location = window.getLocationOnScreen();
+        robot.dragAndDrop(location.x + 4, location.y + 4, location.x + random.nextInt(2*dl)-dl, location.y + random.nextInt(2*dl)-dl);
+        robot.waitForIdle(delay);
+        checkDynamicShape();
+
+        EventQueue.invokeAndWait(this::dispose);
+    }
+
+    void checkClick(int x, int y, int flag) throws Exception {
+
+        System.out.println("Trying to click point " + x + ", " + y + ", looking for " + flag + " flag to trigger.");
+
+        clicked = 0;
+        robot.mouseMove(x, y);
+        robot.click();
+
+        for (int i = 0; i < 100; i++)
+            if ((clicked & (1 << flag)) == 0)
+                robot.delay(50);
+            else
+                break;
+
+        if ((clicked & (1 << flag)) == 0)
+            throw new RuntimeException("FAIL: Flag " + flag + " is not triggered for point " + x + ", " + y + "!");
+    }
+}