/*
 * Copyright (c) 1995, 2008, Oracle and/or its affiliates. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Oracle or the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */


import javax.swing.*;
import javax.swing.event.*;
import java.awt.*;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.MouseEvent;
import javax.swing.event.MouseInputAdapter;
import java.awt.image.*;

/** An application that requires no other files. */
public class GlassPaneDemo {
    static private MyGlassPane myGlassPane;

    private static void createAndShowGUI() {
        //Create and set up the window.
        JFrame frame = new MonitoringFrame("GlassPaneDemo");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        //Set up the content pane, where the "main GUI" lives.
        Container contentPane = frame.getContentPane();
        contentPane.setLayout(new FlowLayout());
        contentPane.add(new JButton("Button 1"));
        for(int i = 0; i < 10000; i++) {
        contentPane.add(new JButton("Button 2"));}

        //Set up the glass pane, which appears over both menu bar
        //and content pane and is an item listener on the change
        //button.
        myGlassPane = new MyGlassPane(frame.getContentPane());
        frame.setGlassPane(myGlassPane);
        myGlassPane.setVisible(true);

        frame.setCursor(MyGlassPane.blankCursor);

        //Show the window.
        frame.pack();
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        createAndShowGUI();
    }
}

/**
 * We have to provide our own glass pane so that it can paint.
 */
class MyGlassPane extends JComponent implements MouseInputListener {
    Point point;
    Container contentPane;
    double lastPaint = 0;

    final static Image cursorImg = Toolkit.getDefaultToolkit().createImage(new MemoryImageSource(0, 0, new int[0], 0, 0));
    public final static Cursor blankCursor = Toolkit.getDefaultToolkit().createCustomCursor(cursorImg, new Point(0, 0), "blank cursor");


    protected void paintComponent(Graphics g) {
        if (point != null) {
            g.setColor(Color.red);
            g.fillOval(point.x - 10, point.y - 10, 20, 20);
            if(lastPaint != 0)
              System.out.println("@" + (System.currentTimeMillis() - lastPaint));
            lastPaint = System.currentTimeMillis();
        }
        g.dispose();
    }

    public void setPoint(Point p) {

        point = p;
        this.repaint();

    }

    public MyGlassPane(Container contentPane) {
        super();
        setOpaque(false);
        this.contentPane = contentPane;
        addMouseListener(this);
        addMouseMotionListener(this);
    }


    public void mouseMoved(MouseEvent e) {
        redispatchMouseEvent(e, false);
    }

    public void mouseDragged(MouseEvent e) {
        redispatchMouseEvent(e, false);
    }

    public void mouseClicked(MouseEvent e) {
        redispatchMouseEvent(e, false);
    }

    public void mouseEntered(MouseEvent e) {
        redispatchMouseEvent(e, false);
    }

    public void mouseExited(MouseEvent e) {
        redispatchMouseEvent(e, false);
        setPoint(null);
        repaint();
    }

    public void mousePressed(MouseEvent e) {
        redispatchMouseEvent(e, false);
    }

    public void mouseReleased(MouseEvent e) {
        redispatchMouseEvent(e, true);
    }

    //A basic implementation of redispatching events.
    private void redispatchMouseEvent(MouseEvent e,
                                      boolean repaint) {
        Point glassPanePoint = e.getPoint();
/*
        Container container = contentPane;
        Point containerPoint = SwingUtilities.convertPoint(
                                        this,
                                        glassPanePoint,
                                        contentPane);

       contentPane.dispatchEvent(new MouseEvent(contentPane,
                                       e.getID(),
                                       e.getWhen(),
                                       e.getModifiers(),
                                       containerPoint.x,
                                       containerPoint.y,
                                       e.getClickCount(),
                                       e.isPopupTrigger()));
*/


        //The mouse event is probably over the content pane.
        //Find out exactly which component it's over.
/*
        Component component =
            SwingUtilities.getDeepestComponentAt(
                                    container,
                                    containerPoint.x,
                                    containerPoint.y);
*/


/*
        if (component != null) {
            //Forward events over the check box.
            Point componentPoint = SwingUtilities.convertPoint(
                                        this,
                                        glassPanePoint,
                                        component);
            component.dispatchEvent(new MouseEvent(component,
                                                 e.getID(),
                                                 e.getWhen(),
                                                 e.getModifiers(),
                                                 componentPoint.x,
                                                 componentPoint.y,
                                                 e.getClickCount(),
                                                 e.isPopupTrigger()));
        }
*/


        //Update the glass pane if requested.
        setPoint(glassPanePoint);
    }
}




class MonitoringFrame extends JFrame{

	/** Creates a new instance of MyFrame */
	public MonitoringFrame() {
		super();
	}
	public MonitoringFrame(String title) {
		super(title);
	}

	public void paint(Graphics g)
	{
		long start = System.currentTimeMillis();
		super.paint(g);
		long end = System.currentTimeMillis();
		System.out.println("Paint time : " + (end-start));
	}
	public void repaint()
	{
		long start = System.currentTimeMillis();
		super.repaint();
		long end = System.currentTimeMillis();
		System.out.println("Repaint time : " + (end-start));
	}
}
