
/**
 * test 1.0 2001/08/12
 *
 * @summary To check whether getModifiersEx() returns the extended Modifiers
 * flag for this event. Extended Modifiers represent state of all Mouse buttons
 * just after the event occured.
 *
 * @author Vishal Byakod(vishal.byakod@india.sun.com) area= AWT
 * @run applet MouseButtonExTest.html
 */
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Rectangle;
import java.awt.Robot;
import java.awt.Toolkit;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.image.BufferedImage;
import javax.imageio.ImageIO;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollBar;
import javax.swing.JTextArea;
import javax.swing.JTextField;

public class MouseButtonExTest extends MouseAdapter {

    private JFrame frame;
    private JPanel panel;
    private JButton button;
    private JLabel label;
    private JList list;
    private JComboBox combo;
    private JCheckBox checkbox;
    private JScrollBar scrollbar;
    private JTextField textfield;
    private JTextArea textarea;
    private JComponent[] components;
    private JComponent testedComponent;

    private int[] keyTypes;
    private String[] keyNames;
    private int[] keyMasks;

    private int[] mouseButtonTypes = {
        InputEvent.BUTTON1_MASK,
        InputEvent.BUTTON2_MASK,
        InputEvent.BUTTON3_MASK
    };
    private String[] mouseButtonNames = {
        "BUTTON1",
        "BUTTON2",
        "BUTTON3"
    };

    private int mouseMasks[] = {
        InputEvent.BUTTON1_DOWN_MASK,
        InputEvent.BUTTON2_DOWN_MASK,
        InputEvent.BUTTON3_DOWN_MASK
    };

    private static String WORK_DIR = ".";
    private int delay = 500;
    private int keyDelay = 50;

    private boolean passed = true;
    private int modifier = 0;

    private final Object lock = new Object();
    private boolean eventFired = false;

    @SuppressWarnings("CallToPrintStackTrace")
    public MouseButtonExTest() {
        if (System.getProperty("os.name").toUpperCase().equals("SUNOS") && !(System.getProperty("os.arch").equals("x86") || System.getProperty("os.arch").equals("amd64"))) {
            keyTypes = new int[] {KeyEvent.VK_CONTROL, KeyEvent.VK_SHIFT, KeyEvent.VK_META};
            
            keyNames = new String[] {"CONTROL", "SHIFT", "META"};
            
            keyMasks = new int[]{
                InputEvent.CTRL_DOWN_MASK,
                InputEvent.SHIFT_DOWN_MASK,
                InputEvent.META_DOWN_MASK
            };
        } else if (System.getProperty("os.name").toUpperCase().startsWith("WIN")) {
            keyTypes = new int[]{
                KeyEvent.VK_CONTROL,
                KeyEvent.VK_SHIFT,
                KeyEvent.VK_ALT
            };
            
            keyNames = new String[] { "CONTROL", "SHIFT", "ALT" };
            keyMasks = new int[]{
                InputEvent.CTRL_DOWN_MASK,
                InputEvent.SHIFT_DOWN_MASK,
                InputEvent.ALT_DOWN_MASK
            };
        } else {
            keyTypes = new int[]{
                KeyEvent.VK_CONTROL,
                KeyEvent.VK_SHIFT
            };
            keyNames = new String[]{
                "CONTROL",
                "SHIFT"
            };
            keyMasks = new int[]{
                InputEvent.CTRL_DOWN_MASK,
                InputEvent.SHIFT_DOWN_MASK
            };
        }
        try {
            Toolkit.getDefaultToolkit().getSystemEventQueue().invokeAndWait(new Runnable() {
                @Override
                public void run() {
                    initializeGUI();
                }
            });
        } catch (Exception e) {
            e.printStackTrace();
            System.exit(1);
        }
    }

    private void initializeGUI() {
        frame = new JFrame("Test Frame");
        frame.getContentPane().setLayout(new FlowLayout());

        panel = new JPanel();
        button = new JButton("Button");
        label = new JLabel("Label");
        String[] jla = new String[] {"One", "Two", "Three"};        
        list = new JList(jla);
        combo = new JComboBox();
        combo.addItem("Red");
        combo.addItem("Orange");
        combo.addItem("Yellow");
        checkbox = new JCheckBox("Checkbox");
        scrollbar = new JScrollBar(JScrollBar.HORIZONTAL, 0, 1, 0, 255);
        textfield = new JTextField(15);
        textarea = new JTextArea(5, 15);

        components = new JComponent[]{
            /*panel, button, label, list,*/ combo/*, checkbox, scrollbar, textfield, textarea*/
        };

        frame.addWindowListener(new WindowAdapter() {
            @Override
            public void windowClosing(WindowEvent event) {
                System.err.println("User closed the window");
                System.exit(1);
            }
        });

        for (JComponent component : components) {
            component.addMouseListener(this);
            frame.getContentPane().add(component);
        }

        frame.setSize(300, 300);
        frame.setVisible(true);
    }

    @SuppressWarnings("CallToPrintStackTrace")
    public static void main(String[] args) {
        WORK_DIR = System.getProperty("resultsDir");
        if (WORK_DIR == null || WORK_DIR.equals("")) {
            System.err.println("ERROR: resultsDir not set!");
            System.exit(1);
        }
        try {
            MouseButtonExTest test = new MouseButtonExTest();
            test.doTest();
        } catch (Exception e) {
            e.printStackTrace();
            System.exit(1);
        }
    }

    @Override
    public void mousePressed(MouseEvent event) {
        if (!event.getSource().equals(testedComponent)) {
            return;
        }
        if(event.getSource() instanceof javax.swing.JComboBox) {
            System.out.println("Mouse pressed");
        }
        modifier = event.getModifiersEx();
        eventFired = true;
        synchronized (lock) {
            try {
                lock.notifyAll();
            } catch (Exception e) {
            }
        }
    }

    @Override
    public void mouseReleased(MouseEvent event) {
        super.mouseReleased(event); //To change body of generated methods, choose Tools | Templates.
        if(event.getSource() instanceof javax.swing.JComboBox) {
            System.out.println("Mouse released");
        }        
    }

    @SuppressWarnings("CallToPrintStackTrace")
    private void doTest() throws Exception {
        Robot robot = null;
        try {
            robot = new Robot();
            Thread.sleep(delay * 10);
        } catch (Exception e) {
            e.printStackTrace();
            System.exit(1);
        }

        int keysToTest = keyTypes.length - 1;
        if (System.getProperty("os.name").toUpperCase().equals("SUNOS") && !(System.getProperty("os.arch").equals("x86") || System.getProperty("os.arch").equals("amd64"))) {
            keysToTest = keyTypes.length;
        } else if (System.getProperty("os.name").toUpperCase().equals("WINDOWS")) {
            keysToTest = keyTypes.length - 1;
        }

        for (JComponent component : components) {
            testedComponent = component;
            robot.mouseMove((int) component.getLocationOnScreen().x + component.getSize().width / 2, (int) component.getLocationOnScreen().y + component.getSize().height / 2);

            robot.delay(delay);
            robot.mousePress(InputEvent.BUTTON1_MASK);
            robot.delay(delay);
            robot.mouseRelease(InputEvent.BUTTON1_MASK);
            robot.delay(delay);
            robot.keyPress(KeyEvent.VK_ESCAPE);
            robot.delay(keyDelay);
            robot.keyRelease(KeyEvent.VK_ESCAPE);
            robot.delay(delay * 5);

            for (int j = 0; j < keysToTest; j++) {
                for (int k = 0; k < mouseButtonTypes.length; k++) {
                    eventFired = false;
                    robot.keyPress(keyTypes[j]);
                    robot.delay(keyDelay);
                    System.out.println("Press mouse: "+mouseButtonNames[k]);
                    robot.mousePress(mouseButtonTypes[k]);
                    robot.delay(delay);
                    if (!eventFired) {
                        synchronized (lock) {
                            try {
                                lock.wait(delay * 5);
                            } catch (Exception e) {
                            }
                        }
                    }
                    if (eventFired) {
                        if ((keyMasks[j] | mouseMasks[k]) == modifier) {
                        } else {
                            System.out.println("Expected: "+(keyMasks[j] | mouseMasks[k]));
                            System.out.println("Actual: "+modifier);
                            System.err.println("FAIL: getModifiersEx failed. Component: " + component.getClass() + " Key: " + keyNames[j] + " MouseButton: " + mouseButtonNames[k]);
                            passed = false;
                        }
                    } else {
                        System.err.println("FAIL: Event was not fired. Component: " + component.getClass() + " Key: " + keyNames[j] + " MouseButton: " + mouseButtonNames[k]);
                        passed = false;
                    }
                    robot.mouseRelease(mouseButtonTypes[k]);
                    robot.delay(delay);
                    robot.keyRelease(keyTypes[j]);
                    robot.delay(keyDelay);
                    robot.keyPress(KeyEvent.VK_ESCAPE);
                    robot.delay(keyDelay);
                    robot.keyRelease(KeyEvent.VK_ESCAPE);
                    robot.delay(keyDelay);
                }
            }
        }

        if (passed) {
            System.out.println("Test passed!");
            System.exit(0);
        } else {
            System.err.println("Test failed!");
            captureScreenAndSave();
            System.exit(1);
        }
    }

    /**
     * Do screen capture and save it as image
     */
    @SuppressWarnings("CallToPrintStackTrace")
    private static void captureScreenAndSave() {
        try {
            Robot robot = new Robot();
            Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
            Rectangle rectangle = new Rectangle(0, 0, screenSize.width, screenSize.height);
            System.out.println("About to screen capture - " + rectangle);
            BufferedImage image = robot.createScreenCapture(rectangle);
            ImageIO.write(image, "jpg", new java.io.File(WORK_DIR, "ScreenImage.jpg"));
            robot.delay(3000);
        } catch (Throwable t) {
            System.out.println("WARNING: Exception thrown while screen capture!");
            t.printStackTrace();
        }
    }
}
