/* * 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 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; /* * @author Dmitriy Ermashov (dmitriy.ermashov@oracle.com) */ public abstract class Common { ExtendedRobot robot; Class windowClass; Frame background; BufferedImage foreground; Window window; Container componentsContainer; float opacity = 1.0f; static final int STATIC_STEP = 30; static final int STATIC_WIDTH = 25; static final int STATIC_BLOCKS = 30; static final Color BG_COLOR = Color.BLUE; static final 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 = { Window.class, Frame.class, Dialog.class }; public Common(Class windowClass, float opacity) throws Exception{ 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); } public void doTest() throws Exception { robot.waitForIdle(delay); }; public void dispose() { window.dispose(); background.dispose(); } public abstract 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 void applyStaticShape() { final Area a = new Area(); for (int x = 0; x < STATIC_BLOCKS; x++) { for (int y = 0; y < STATIC_BLOCKS; y++) { a.add(new Area(new Rectangle2D.Float( x*STATIC_STEP, y*STATIC_STEP, STATIC_WIDTH, STATIC_WIDTH))); } } 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 checkStaticShape() throws Exception { Point[] points = new Point[4]; Dimension size = window.getSize(); int xFactor = (int) Math.floor(size.getWidth()/STATIC_STEP)-1; int yFactor = (int) Math.floor(size.getHeight()/STATIC_STEP)-1; // background points[0] = new Point((STATIC_STEP+STATIC_WIDTH)/2, (STATIC_STEP+STATIC_WIDTH)/2); points[1] = new Point(STATIC_STEP*xFactor+(STATIC_STEP+STATIC_WIDTH)/2, STATIC_STEP*yFactor+(STATIC_STEP+STATIC_WIDTH)/2); points[2] = new Point((STATIC_STEP+STATIC_WIDTH)/2, STATIC_STEP*yFactor+(STATIC_STEP+STATIC_WIDTH)/2); points[3] = new Point(STATIC_STEP*xFactor+(STATIC_STEP+STATIC_WIDTH)/2, (STATIC_STEP+STATIC_WIDTH)/2); checkShape(points, true); // foreground if (opacity < 1.0f){ checkTranslucentShape(); } else { points[0] = new Point((STATIC_WIDTH) / 2, (STATIC_WIDTH) / 2); points[1] = new Point(STATIC_STEP * xFactor + (STATIC_WIDTH) / 2, STATIC_STEP * yFactor + (STATIC_WIDTH) / 2); points[2] = new Point((STATIC_WIDTH) / 2, STATIC_STEP * yFactor + (STATIC_WIDTH) / 2); points[3] = new Point(STATIC_STEP * xFactor + (STATIC_WIDTH) / 2, (STATIC_WIDTH) / 2); checkShape(points, false); } } 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); if (areBackgroundPoints) { if (!robot.getPixelColor(p.x, p.y).equals(BG_COLOR)) throw new RuntimeException("Background point " + p + " color " + robot.getPixelColor(p.x, p.y) + " does not equal to background color " + BG_COLOR); else System.out.println("OK with background point " + p); } else { if (robot.getPixelColor(p.x, p.y).equals(BG_COLOR)) throw new RuntimeException("Foreground point " + p + " equals to background color " + BG_COLOR); else System.out.println("OK with foreground point " + p); } } } public void initBackgroundFrame() { background = new Frame(); background.setUndecorated(true); background.setBackground(BG_COLOR); background.setSize(500, 500); background.setLocation(dl, dl); background.setVisible(true); } public void initGUI() { if (windowClass.equals(Frame.class)) { window = new Frame(); ((Frame) window).setUndecorated(true); } else if (windowClass.equals(Dialog.class)) { window = new Dialog(background); ((Dialog) window).setUndecorated(true); } else { window = new Window(background); } window.setBackground(FG_COLOR); componentsContainer = new Panel(); window.add(componentsContainer, BorderLayout.CENTER); window.setLocation(2 * dl, 2 * dl); window.setSize(255, 255); if (opacity < 1.0f) window.setOpacity(opacity); window.addComponentListener(new ComponentAdapter() { public void componentResized(ComponentEvent e) { applyShape(); } }); applyShape(); window.setVisible(true); applyAppDragNResizeSupport(); window.toFront(); } }