
package jp.riken.brain.ni.samuraigraph.figure.java2d;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.GradientPaint;
import java.awt.Graphics2D;
import java.awt.Shape;
import java.awt.Stroke;
import java.awt.geom.Area;
import java.awt.geom.Rectangle2D;
import java.util.List;

import jp.riken.brain.ni.samuraigraph.figure.SGDrawingElementBar;


/**
 * 
 */
public class SGDrawingElementBar2D extends SGDrawingElementBar
	implements SGIDrawingElementJava2D
{

	/**
	 * 
	 */
	public SGDrawingElementBar2D()
	{
		super();
	}



	/**
	 * 
	 */
	public SGDrawingElementBar2D(
		final float x,
		final float y,
		final float w,
		final float h )
	{
		super();
		this.setBounds( x, y, w, h );
	}



	/**
	 * 
	 */
	public Rectangle2D getElementBounds()
	{
		final float x = this.getX();
		final float y = this.getY();
		final float w = this.getWidth();
		final float h = this.getHeight();

		final float ww = Math.abs(w);
		final float hh = Math.abs(h);

		float xx;
		float yy;
		if( this.isHorizontal() )
		{
			xx = w>0.0f ? x : x-ww;
			yy = y - 0.50f*hh;
		}
		else
		{
			xx = x - 0.50f*ww;
			yy = h>0.0f ? y : y-hh;
		}

		Rectangle2D rect = new Rectangle2D.Float(xx,yy,ww,hh);

		return rect;
	}


	/**
	 * 
	 */
	public boolean contains(final int x, final int y)
	{
		return this.getElementBounds().contains(x,y);
	}


	/**
	 * 
	 */
	public Shape getShape()
	{
		return this.getElementBounds();
	}


	/**
	 * 
	 */
	public void paintElement( Graphics2D g2d )
	{
		if( this.isVisible() == false )
		{
			return;
		}
		
		final float width = this.getMagnification()*this.getEdgeLineWidth();
		Stroke stroke = new BasicStroke(
			width, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER );
		final Rectangle2D dRect = this.getElementBounds();

		// paint
		g2d.setPaint( this.getColor(0) );
		g2d.fill(dRect);

		// draw edge lines
		g2d.setStroke(stroke);
		g2d.setPaint(this.mEdgeLineColor);
		g2d.draw(dRect);
	}


	/**
	 * 
	 */
	public void paint( final Graphics2D g2d, final Rectangle2D clipRect )
	{

		if( clipRect==null )
		{
			this.paintElement(g2d);
		}
		else
		{
			if( this.isVisible() == false )
			{
				return;
			}

			final float x = this.getX();
			final float y = this.getY();
			final float w = this.getWidth();
			final float h = this.getHeight();

			final List cList = this.getColorList();
			final int cNum = cList.size();
		
			if( cNum > 1 )
			{
				//
				// 複数の色を持つ場合には、GradientPaintを用いる
				//

				// X座標値
				final float gX = x + 0.50f*w;

				// 高さを色数で割った値
				final float diff = h/cNum;

				// グラデーションを付ける幅
//				final float delta = diff/10.0f;
	final float delta = 5.0f;

				// rectangleを分割する（色数+1）
				Rectangle2D[] rectArray = new Rectangle2D[cNum+1];
				rectArray[0] = new Rectangle2D.Float( x, y, w, 0.50f*diff );	// 上端
				rectArray[rectArray.length-1]
					= new Rectangle2D.Float(
						x, y + h - 0.50f*diff, w, 0.50f*diff );		// 下端
				for( int jj=1; jj<rectArray.length-1; jj++ )
				{
					final float yy = y+ 0.50f*diff + (jj-1)*diff;
					rectArray[jj] = new Rectangle2D.Float(
						x, yy, w, diff );
				}


				// 区切り点のY座標値の配列（色数-1）
				float[] gYArray = new float[cNum-1];
				for( int jj=0; jj<gYArray.length; jj++ )
				{
					gYArray[jj] = y + (jj+1)*diff;
				}


				// 分割した矩形を塗りつぶす
				g2d.setPaint( (Color)cList.get(0) );
				g2d.fill(rectArray[0]);

				for( int jj=0; jj<gYArray.length; jj++ )
				{
					Color c1 = (Color)this.mColorList.get(jj);
					Color c2 = (Color)this.mColorList.get(jj+1);
					final float y1 = gYArray[jj] - delta;
					final float y2 = gYArray[jj] + delta;
					GradientPaint gPaint = new GradientPaint(
						gX, y1, c1, gX, y2, c2 );
					g2d.setPaint( gPaint );
					g2d.fill(rectArray[jj+1]);
				}

				g2d.setPaint( (Color)this.getColorList().get(cNum-1) );
				g2d.fill(rectArray[rectArray.length-1]);

			}
			else
			{
				final Rectangle2D dRect = this.getElementBounds();

				Stroke stroke = new BasicStroke(
					this.getMagnification()*this.getEdgeLineWidth(),
					BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER );

				Area clipArea = new Area( clipRect );
				Shape edge = stroke.createStrokedShape( dRect );
				Area edgeArea = new Area( edge );
				Area inner = new Area( dRect );
				
				edgeArea.intersect( clipArea );
				inner.intersect( clipArea );

				// paint
				g2d.setPaint( this.getColor(0) );
				g2d.fill( inner );

				// draw edge lines
				g2d.setStroke(stroke);
				g2d.setPaint(this.mEdgeLineColor);
				g2d.fill( edgeArea );
			}
		}

	}




//	/**
//	 * 
//	 */
//	public Object copy()
//	{
//		SGDrawingElementBar2D el = new SGDrawingElementBar2D();
//		this.setPropertiesForCopy(el);
//		return el;
//	}
//
//
//	protected boolean setPropertiesForCopy( SGDrawingElementBar2D el )
//	{
//		el.setProperties( this.getProperties() );
//		el.setLocation( this.getX(), this.getY() );
//		el.setMagnification( this.mMagnification );
//		return true;
//	}


}

