/*
 * The contents of this file are subject to the terms of the Common Development
 * and Distribution License (the License). You may not use this file except in
 * compliance with the License.
 *
 * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
 * or http://www.netbeans.org/cddl.txt.
 * 
 * When distributing Covered Code, include this CDDL Header Notice in each file
 * and include the License file at http://www.netbeans.org/cddl.txt.
 * If applicable, add the following below the CDDL Header, with the fields
 * enclosed by brackets [] replaced by your own identifying information:
 * "Portions Copyrighted [year] [name of copyright owner]"
 *
 * The Original Software is NetBeans. The Initial Developer of the Original
 * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
 * Microsystems, Inc. All Rights Reserved.
 */
/*
 * DropShadowBorder.java
 *
 * Created on December 22, 2003, 9:06 PM
 */

package org.netbeans.swing.plaf.aqua;

import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Component;
import java.awt.Composite;
import java.awt.GradientPaint;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Insets;
import java.awt.Paint;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.Shape;
import java.awt.geom.Area;
import java.awt.geom.GeneralPath;
import java.awt.geom.Point2D;
import java.util.HashMap;
import java.util.Map;
import javax.swing.UIManager;
import javax.swing.border.Border;
import org.netbeans.swing.plaf.util.UIUtils;

/** A translucent drop shadow border class with settable colors and size.
 * Generally it's a goood idea to use a transparent color as the second
 * color.  The default size is 5 pixels, and the default colors are 
 * <code>UIManager.getColor(&quot;controlDkShadow&quot;)</code> for the
 * darker portion of the shadow, fading towards transparent white.
 *
 * @author  Tim Boudreau   */
public final class DropShadowBorder implements Border {
    int offset = 7;
    /** Scratch array for x coordinates to avoid extra allocations while painting */
    private static final int[] xpoints = new int[5];
    /** Scratch array for y coordinates to avoid extra allocations while painting */
    private static final int[] ypoints = new int[5];
    /** Default light shadow color if none is specified */
    static final Color DEFAULT_SHADOWLIGHT=new Color(255, 255, 255, 0);
    /** Field for the light shadow color */
    private Color shadowLight = DEFAULT_SHADOWLIGHT;
    /** Field for the dark shadow color */
    private Color shadowDark = null;
    /** AlphaComposite doesn't cache non 1.0 alpha instances, so we will */
    private static final Composite transparency =
        AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.7f);
    
    /** Creates a new instance of DropShadowBorder with default settings */
    public DropShadowBorder() {
    }
    
    private Color getShadowLight() {
        return DEFAULT_SHADOWLIGHT;
    }
    
    private Color getShadowDark() {
        Color result = null;
        if (shadowDark == null) {
            result = UIManager.getColor("controlDkShadow"); //NOI18N
            result = new Color (result.getRed(), result.getGreen(), result.getBlue(), 128);
        } else {
            result = shadowDark;
        }
        return result;
    }
    private static final int WIDTH = 17;
    private static final int HEIGHT = 17;
    private static final int ARC = 12;
    public Insets getBorderInsets(Component c) {
        return new Insets(1,WIDTH,HEIGHT + 5, WIDTH);
    }
    
    public boolean isBorderOpaque() {
        return false;
    }
    
    private static final int GAP = ARC / 2;
    public void paintBorder(Component c, Graphics g, int x, int y, int w, int h) {
        UIUtils.configureRenderingHints (g);
        
        Graphics2D g2d = (Graphics2D) g;
        Composite comp = g2d.getComposite();
        Paint paint = g2d.getPaint();
        try {
            Insets ins = getBorderInsets(c);
            
            int bottom = (y + (h - (ins.bottom + ins.top))) + GAP;
            int left = (x + ins.left) - GAP;
            int right = (x + w - ins.right) + GAP;
            int top = (y + ins.top) + 1;
            
            int arctop = y + (h - (ins.bottom + ins.top + ARC));
            int arcright = right - (ARC + GAP);
            int arcleft = x + ins.left + ARC;
            
            GeneralPath gp = new GeneralPath();
            gp.moveTo (left, top + 27); //orig: left, top - 
            
            gp.lineTo (left, arctop); 
            gp.quadTo (left, bottom, arcleft, bottom);
            
            gp.lineTo (arcright, bottom);
                        
            gp.quadTo (right, bottom, right, arctop);
            
            //**Special handling for Aqua tabs - move to near the top of the
            //right edge
            gp.lineTo (right, top + 27);
            //Do a slight curve in on the upper right side to the bottom
            //of the tabs are, inset a bit like the tabs are
            gp.quadTo (right, top + 22, right - 6, top + 18);
            //Up the right edge of the tab
            gp.lineTo (right - 9, top + 5);
            //Curve at the top of the tab
            gp.quadTo (right - 9, top, right - 14, top);
            //Across the top toward the left edge
            gp.lineTo (left + 11, top);
            //And do a curve there too
            gp.quadTo (left + 11, top, left + 8, top + 3);
            gp.lineTo (left + 11, top + 16);
            gp.quadTo (left, top + 21, left, top + 26);
            
            

/*            gp.quadTo (left, top, left + 9, top);
            gp.lineTo (left + 6, top + 16); //Fragile - connected with tab heights
            gp.lineTo (left + 6, top + 3);
 */
            
            gp.closePath();
            
            g.setColor (Color.WHITE);
            g2d.fill (gp);
            
            Area a = new Area (new Rectangle (x, y, w, h));
            a.subtract (new Area (gp));
            
            g2d.setPaint (new ShapeGradientPaint (gp.getBounds(), getShadowDark(), getShadowLight()));
            g2d.fill(a);
            
            g.setColor (UIManager.getColor ("controlShadow")); //NOI18N
            g2d.draw(gp);
            
            
        } finally {
            g2d.setComposite(comp);
            g2d.setPaint(paint);
        }
    }   
}
