/*
 * MouseMask.java  $Revision: 1.4 $  $Date: 2007/10/03 04:39:40 $
 *
 * Copyright (C) 2007 Meldcraft Corporation
 *
 * This file is part of Scaffold.
 * 
 * Scaffold is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * Scaffold 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 Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public License
 * along with Scaffold.  If not, see <http://www.gnu.org/licenses/>.
 */
package com.meldcraft.gui.swing;

import java.awt.AWTEvent;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Window;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;

import javax.swing.JComponent;
import javax.swing.RepaintManager;
import javax.swing.SwingUtilities;

/**
 * @version $Revision: 1.4 $ $Date: 2007/10/03 04:39:40 $
 * @author Rob Richards
 */
public class MouseMask extends JComponent implements ComponentListener
{
    protected Component         mMaskedComponent;
    protected BufferedImage     mImage;
    private   Point             mBasePoint;
    private   boolean           mShowMask;
    
    public MouseMask(Component maskedComponent)
    {
        mMaskedComponent = maskedComponent;
        mMaskedComponent.addComponentListener(this);
        //this.addMouseListener(new MouseAdapter(){});
        //this.addMouseMotionListener(new MouseAdapter(){});
        //configureMask();
        enableEvents(AWTEvent.MOUSE_EVENT_MASK | AWTEvent.MOUSE_MOTION_EVENT_MASK | AWTEvent.MOUSE_WHEEL_EVENT_MASK);
    }

    public Dimension getMaximumSize()
    {
        return mMaskedComponent.getMaximumSize();
    }

    public Dimension getMinimumSize()
    {
        return mMaskedComponent.getMinimumSize();
    }

    public Dimension getPreferredSize()
    {
        return mMaskedComponent.getPreferredSize();
    }

    public void componentResized(ComponentEvent e)
    {
        //System.err.println("=== resized " + e.getComponent().getSize());
        configureMask();
    }

    public void componentMoved(ComponentEvent e)
    {
    }

    public void componentShown(ComponentEvent e)
    {
    }

    public void componentHidden(ComponentEvent e)
    {
    }

    public boolean getShowMask()
    {
        return mShowMask;
    }

    public void setShowMask(boolean showMask)
    {
        mShowMask = showMask;
    }

    @Override
    public void paintComponent(Graphics g)
    {
        super.paintComponent(g);
        if (mShowMask)
        {
            if (mImage != null)
            {
                g.drawImage(mImage, 0,0, this);
            }
        }
    }

    @Override
    public boolean contains(Point p)
    {
        int val = 0;
        if (mImage != null)
        {
            if ((p.x > 0) && (p.y > 0) && (p.x < mImage.getWidth()) && (p.y < mImage.getHeight()))
            {
                val = mImage.getRGB(p.x, p.y);
            }
        }
        return ((val & 0xff000000) == 0);
    }

    @Override
    protected void processMouseEvent(MouseEvent e)
    {
        Point point = e.getPoint();

        int mod = e.getModifiers();
        if ((mod & MouseEvent.MOUSE_PRESSED) != 0)
        {
            mBasePoint = e.getLocationOnScreen();
        }

        if (!contains(point))
        {
            Component comp = SwingUtilities.getDeepestComponentAt(mMaskedComponent, point.x, point.y);
            MouseEvent mouseEvent= SwingUtilities.convertMouseEvent(this, e, comp);
            comp.dispatchEvent(mouseEvent);
        }
        else
        {
            e.consume();
        }
    }

    protected void processMouseMotionEvent(MouseEvent e)
    {
        Point point = e.getPoint();
        if (!contains(point))
        {
            Component comp = SwingUtilities.getDeepestComponentAt(mMaskedComponent, point.x, point.y);
            MouseEvent mouseEvent= SwingUtilities.convertMouseEvent(this, e, comp);
            comp.dispatchEvent(mouseEvent);
        }
        else
        {
            int mod = e.getModifiers();
            if ((mod & MouseEvent.MOUSE_DRAGGED) != 0)
            {
                Window window = SwingUtil.getWindow(this);
                point = e.getLocationOnScreen();
                Point wpoint = window.getLocation();
                if (mBasePoint != null)
                {
                    int dx = point.x - mBasePoint.x;
                    int dy = point.y - mBasePoint.y;
                    window.setLocation(wpoint.x + dx, wpoint.y + dy);
                }
                mBasePoint = point;
            }

            e.consume();
        }
    }

    protected void configureMask()
    {
        Dimension dim = mMaskedComponent.getSize();
        if ((dim.width > 0) && (dim.height > 0))
        {
            System.err.println("+++ " + dim);
            BufferedImage image = new BufferedImage(dim.width, dim.height, BufferedImage.TYPE_INT_ARGB);
            Graphics2D g = (Graphics2D)image.getGraphics();
            int alpha = mShowMask ? 192 : 0;
            g.setColor(new Color(255,255,64,alpha));
            g.fillRect(0,0, dim.width,dim.height);
            RepaintManager mgr = RepaintManager.currentManager(mMaskedComponent);
            boolean dbl = mgr.isDoubleBufferingEnabled();
            if (dbl)
            {
                mgr.setDoubleBufferingEnabled(false);
            }
            try
            {
                mMaskedComponent.paint(g);
            }
            finally
            {
                mImage = image;
                if (dbl)
                {
                    mgr.setDoubleBufferingEnabled(dbl);
                }
            }
        }
        else
        {
            mImage = null;
        }
        revalidate();
        repaint();
    }
}



