/*
 * Copyright (c) 2007 Sun Microsystems, Inc.  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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
 * CA 95054 USA or visit www.sun.com if you need additional information or
 * have any questions.
 */

/*
  @test
  @bug 6479820
  @library ../../../regtesthelpers
  @build Util
  @summary verify that enter/exit events still comes correctly
  @author andrei dmitriev: area=awt.event
  @run main SpuriousExitEnter_3
*/

/**
 * SpuriousExitEnter_3.java
 *
            "There is a plain JFrame with JButton in it.",
            "Let A area is the area inside JButton.",
            "Let B area is the area inside JFrame but not inside JButton.",
            "Let C area is the area outside JFrame.",
            "Now check that the correct events and are in the correct number generates when you",
            "move the pointer between those areas.",
            " 1) Verify that the Enter and Exit events comes to JButton and JFrame when ",
            " you move the pointer between A and B areas.",
            " 2) Verify that the Enter and Exit events comes to JButton when you",
            " move the pointer between A to C.",
            " 3) Verify that the Enter and Exit events comes to JFrame when you",
            " move the pointer between B to C.",
 */

import java.awt.*;
import java.awt.event.*;
import test.java.awt.regtesthelpers.Util;
import javax.swing.*;

public class SpuriousExitEnter_3 {
    static JFrame frame = new JFrame("SpuriousExitEnter_3_LW");
    static JButton jbutton = new JButton("jbutton");
    static Frame frame1 = new Frame("SpuriousExitEnter_3_HW");
    static Button button1 = new Button("button");

    static EnterExitAdapter frameAdapter;
    static EnterExitAdapter buttonAdapter;
    static Robot r = Util.createRobot();

    public static void testCase(Window w, Component comp) {
        frameAdapter = new EnterExitAdapter(w);
        buttonAdapter = new EnterExitAdapter(comp);

        w.addMouseListener(frameAdapter);
        comp.addMouseListener(buttonAdapter);

        w.setSize(200, 200);
        w.add(comp, BorderLayout.NORTH);
        w.setLocationRelativeTo(null);
        w.setVisible(true);

        Point centerA = new Point(comp.getLocationOnScreen().x + comp.getWidth() / 2,
                                  comp.getLocationOnScreen().y + comp.getHeight() / 2);
        Point centerB = new Point(w.getLocationOnScreen().x + w.getWidth() / 2,
                                  w.getLocationOnScreen().y + w.getHeight() / 2);
        //for moving from A outside: don't cross the A area. Move straight to the right.
        Point centerC_1 = new Point(w.getLocationOnScreen().x + w.getWidth() + 20,  //go right off the border
                                    comp.getLocationOnScreen().y + comp.getHeight() / 2); //don't cross the A area!

        //for moving from B outside: don't cross the B area. Move straight to the bottom.
        Point centerC_2 = new Point(w.getLocationOnScreen().x + w.getWidth() / 2,
                                    w.getLocationOnScreen().y + w.getHeight() + 20); //go below the bottom border
        //A and B areas
        Util.pointOnComp(comp, r);
        Util.waitForIdle(r);
        frameAdapter.zeroCounters();
        buttonAdapter.zeroCounters();

        moveBetween(r, centerA, centerB);
        checkEvents(frameAdapter, 1, 1);
        checkEvents(buttonAdapter, 1, 1);

        //A and C areas
        Util.pointOnComp(comp, r);
        Util.waitForIdle(r);
        frameAdapter.zeroCounters();
        buttonAdapter.zeroCounters();
        moveBetween(r, centerA, centerC_1);
        checkEvents(frameAdapter, 0, 0);
        checkEvents(buttonAdapter, 1, 1);

        //B and C areas
        Util.pointOnComp(w, r);
        Util.waitForIdle(r);
        frameAdapter.zeroCounters();
        buttonAdapter.zeroCounters();
        moveBetween(r, centerB, centerC_2);
        checkEvents(frameAdapter, 1, 1);
        checkEvents(buttonAdapter, 0, 0);
        w.setVisible(false);
    }

    public static void main(String []s)
    {
        //LW case:
        testCase(frame, jbutton);
        //HW case
        testCase(frame1, button1);
    }

    private static void moveBetween(Robot r, Point first, Point second) {
        Util.waitForIdle(r);
        Util.mouseMove(r, first, second);
        Util.waitForIdle(r);
        Util.mouseMove(r, second, first);
        Util.waitForIdle(r);
    }

    // component should get exactly entered of Entered events and exited of Exited events.
    private static void checkEvents(EnterExitAdapter adapter, int entered, int exited) {
        if (adapter.getEnteredEventCount() != entered ||
            adapter.getExitedEventCount() != exited)
        {
            throw new RuntimeException(adapter.getTarget().getClass().getName()+": incorrect event number: Entered got: " +
                                       adapter.getEnteredEventCount() +" expected : " + entered
                                       + ". Exited got : " + adapter.getExitedEventCount() + " expected : "
                                       + exited);
        }
    }

}


class EnterExitAdapter extends MouseAdapter {
    private Component target;
    private int enteredEventCount = 0;
    private int exitedEventCount = 0;

    public EnterExitAdapter(Component target) {
        this.target = target;
    }

    public Component getTarget(){
        return target;
    }
    public int getEnteredEventCount(){
        return enteredEventCount;
    }

    public int getExitedEventCount(){
        return exitedEventCount;
    }

    public void zeroCounters(){
        System.out.println("Zeroeing on " +target.getClass().getName());
        enteredEventCount = 0;
        exitedEventCount = 0;
    }

    public void mouseEntered(MouseEvent e){
        System.out.println("Entered on " + e.getSource().getClass().getName());
        enteredEventCount ++;
    }
    public void mouseExited(MouseEvent e){
        System.out.println("Exited on " + e.getSource().getClass().getName());
        exitedEventCount ++;
    }
}
