/**
* summary Checking whether it is possible to consume the Mouse Wheel event
*          and avoid native handling of the Mouse Wheel Events
*
*                  1. Clients must be able to avoid Native handling of Mouse Wheel (by
*             Components having native peers with integrated Scroll Bars) by
*             adding MouseWheelListener and consuming the events
*
* author M.Abdul Rahuman(abdul@siptech.co.in) area=MouseWheelSupport
*/

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.awt.image.*;
import java.io.File;

public class ConsumeMouseWheelEventTest implements MouseWheelListener {

    private final static int delay  = Delays.getRobotDelay();
    private final static int keyDelay  = Delays.getKeyDelay();
    private final static int mouseDelay  = Delays.getMouseDelay();
    private final static int waitDelay  = Delays.getWaitDelay();

    private Frame frame;
    private TextArea textArea;

    private JFrame jFrame;
    private JTextArea jTextArea;
    private JScrollPane jScrollPane;

    private boolean passed = true;
    private boolean textAreaWheelEvent = false;
    private boolean jTextAreaWheelEvent = false;
    private boolean isConsumedAfter = false;
    private boolean isConsumedBefore = false;

    private Object wheelMovedLock = new Object();
    private static String WORK_DIR=".";

    public ConsumeMouseWheelEventTest() {
        try {
            Toolkit.getDefaultToolkit().getSystemEventQueue().invokeAndWait(new Runnable() {
                public void run() {
                    initializeGUI();
                }
            });
        } catch (Exception e) {
            e.printStackTrace();
            System.exit(1);
        }
    }

    public void mouseWheelMoved(MouseWheelEvent me) {
        if (textArea.equals(me.getSource())) {
            textAreaWheelEvent = true;
        } else {
            jTextAreaWheelEvent = true;
        }
        isConsumedBefore = me.isConsumed();
        me.consume();
        isConsumedAfter = me.isConsumed();
        synchronized (wheelMovedLock) {
            try {
                wheelMovedLock.notifyAll();
            } catch (Exception e) {
            }
        }
    }

    private void initializeGUI() {
        frame = new Frame("Test Frame");
        frame.setLayout(new BorderLayout());
        StringBuffer stringBuffer = new StringBuffer();
        for(int i=0; i<=20; i++) {
            stringBuffer.append("Mouse Wheel Consume\n");
        }
        textArea = new TextArea(stringBuffer.toString());
        textArea.addMouseWheelListener(this);
        frame.add(textArea);
        frame.addWindowListener(new WindowAdapter() {
            public void windowClosing(WindowEvent event) {
                System.err.println("User closed the window");
                System.exit(1);
            }
        });
        frame.setSize(300, 300);
        frame.setVisible(true);

        jFrame = new JFrame("Test JFrame");
        jFrame.getContentPane().setLayout(new BorderLayout());
        jTextArea = new JTextArea(stringBuffer.toString());
        jTextArea.addMouseWheelListener(this);
        jScrollPane = new JScrollPane(jTextArea);
        jFrame.getContentPane().add(jScrollPane);
        jFrame.addWindowListener(new WindowAdapter() {
            public void windowClosing(WindowEvent event) {
                System.err.println("User closed the window");
                System.exit(1);
            }
        });
        jFrame.setSize(300, 300);
        jFrame.setLocation(frame.getLocation().x + 300, frame.getLocation().y);
        jFrame.setVisible(true);
    }

    public static void main(String[] args) {
        try {
            if (System.getProperty("os.name").toUpperCase().equals("SUNOS")) {
                System.out.println("MouseWheel not supported on Solaris. Skipping the test!");
                System.exit(0);
            }
            WORK_DIR = System.getProperty("resultsDir");
            if (WORK_DIR == null || WORK_DIR.equals("")) {
                System.err.println("ERROR: resultsDir not set!");
                System.exit(1);
            }
            ConsumeMouseWheelEventTest test = new ConsumeMouseWheelEventTest();
            test.doTest();
        } catch (Exception e) {
            e.printStackTrace();
            System.exit(1);
        }
    }

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

        frame.requestFocus();
        robot.waitForIdle();
        robot.delay(delay);

        robot.mouseMove((int) textArea.getLocationOnScreen().x + textArea.getSize().width / 2,
                        (int) textArea.getLocationOnScreen().y + textArea.getSize().height / 2);
        robot.delay(delay);
        robot.mousePress(InputEvent.BUTTON1_MASK);
        robot.delay(mouseDelay);
        robot.mouseRelease(InputEvent.BUTTON1_MASK);
        robot.delay(delay);

        robot.mouseWheel(2);
        robot.delay(delay);
        robot.mouseWheel(-2);

        robot.waitForIdle();
        robot.delay(delay);

        if (! textAreaWheelEvent) {
            synchronized (wheelMovedLock) {
                try {
                    wheelMovedLock.wait(waitDelay);
                } catch (Exception e) {
                }
            }
        }
        if (! textAreaWheelEvent) {
            System.err.println("FAIL: MouseWheelEvent did not occur when mouse wheel " +
                               "scrolled over the TextArea");
            passed = false;
        } else if (isConsumedBefore || !isConsumedAfter) {
            System.err.println("FAIL: Mouse wheel event is not properly consumed when the mouse " +
                               "is scrolled over the TextArea");
            System.err.println("Before calling consume(), isConsumed: " + isConsumedBefore);
            System.err.println("After calling consume(), isConsumed: " + isConsumedAfter);
            passed = false;
        }

        jTextAreaWheelEvent = false;
        robot.mouseMove((int) jScrollPane.getLocationOnScreen().x + jScrollPane.getSize().width / 2,
                        (int) jScrollPane.getLocationOnScreen().y + jScrollPane.getSize().height / 2);
        robot.delay(delay);
        robot.mousePress(InputEvent.BUTTON1_MASK);
        robot.delay(mouseDelay);
        robot.mouseRelease(InputEvent.BUTTON1_MASK);
        robot.delay(delay);

        robot.mouseWheel(2);
        robot.delay(delay);
        robot.mouseWheel(-2);

        if (! jTextAreaWheelEvent) {
            synchronized (wheelMovedLock) {
                try {
                    wheelMovedLock.wait(waitDelay);
                } catch (Exception e) {
                }
            }
        }
        if (! jTextAreaWheelEvent) {
            System.err.println("FAIL: MouseWheelEvent did not occur when mouse wheel " +
                               "scrolled over the JTextArea");
            passed = false;
        } else if (isConsumedBefore || !isConsumedAfter) {
            System.err.println("FAIL: Mouse wheel event is not properly consumed when the mouse " +
                               "is scrolled over the JTextArea");
            System.err.println("Before calling consume(), isConsumed: " + isConsumedBefore);
            System.err.println("After calling consume(), isConsumed: " + isConsumedAfter);
            passed = false;
        }

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

    /**
     * Do screen capture and save it as image
     */
    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);
            javax.imageio.ImageIO.write(image, "jpg", new File(WORK_DIR,
                                                               "ScreenImage.jpg"));
            robot.delay(3000);
        } catch (Throwable t) {
            System.out.println("WARNING: Exception thrown while screen capture!");
            t.printStackTrace();
        }
    }
}
