/*
 * @(#)GLine.java
 *
 * Copyright 2001 by Intelligent Technology Inc. All rights reserved.
 */

package jp.co.iti.fagot.gob;

import java.awt.Shape;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Rectangle;

import java.awt.geom.Rectangle2D;
import java.awt.geom.AffineTransform;

import java.util.Enumeration;

import jp.co.iti.fagot.geom.ZPath;
import jp.co.iti.fagot.geom.ZPoint;
import jp.co.iti.fagot.geom.ZLine;
import jp.co.iti.fagot.geom.ZRectangle;

import jp.co.iti.fagot.fob.FobManager;
import jp.co.iti.fagot.fob.FInteger;
import jp.co.iti.fagot.fob.FDouble;

import jp.co.iti.fagot.doc.DocGraphics;
import jp.co.iti.fagot.doc.DocGridControler;

import jp.co.iti.fagot.util.ZGraphicUtil;
import jp.co.iti.fagot.util.ZDebug;
/**
 * Line
 *
 * @author  福島康治
 * @version 1.01 2001/01/07
 */
public class GLine extends GPath {

	/**
	 * コンストラクタ
	 */
	public GLine() {
		super();
		//{{FAGOT_ATTR
		mLine  = new ZLine();
		mArrow = new FInteger();
		//}}FAGOT_ATTR
	}

	//## 位置##########################################################
	/**
	 * 位置の取得
	 */
	public ZRectangle getMyBounds() {
	return new ZRectangle(mLine.getBounds2D());
	}

	/**
	 * 要素にヒットするか？
	 * @param pt   論理座標
	 */
	public byte getHitModeGob(ZPoint pt) {

	// セレクターにヒットするか？
	GSelector sel = new GSelector();
	AffineTransform at = getTransform().getTransform();
	sel = sel.createScaledSelector( 1/at.getScaleX(), 1/at.getScaleY() );
	if ( isSelect() ) {
		if ( sel.isHit(mLine.getP1Z(),pt) ) {
			mMovePoint = PT_START;
			return ( GOperation.POINT ) ;
		}
		if ( sel.isHit(mLine.getP2Z(),pt) ) {
			mMovePoint = PT_END;
			return ( GOperation.POINT ) ;
		}
	}

	// パスの近くか検索する
	if ( ZGraphicUtil.isNearLine(
		mLine.getP1Z(),mLine.getP2Z(),pt,sel.getMargin(1,0) ) ) {
		mMovePoint = PT_NONE;
		return ( GOperation.MOVE ) ;
	}
	return ( GOperation.NONE );
	}

	//## 移動##########################################################
	/**
	 * 移動の開始
	 * @param grid グリッドコントローラ
	 */
	public void moveStartGob(DocGridControler grid) {
	
	switch ( grid.getMoveMode() ) {
	  case GOperation.MOVE:		// 移動
		mMovePoint = PT_NONE;
		break;

	  case GOperation.NEW:		// 新規作成
		mMovePoint = PT_END;
		break;

	  case GOperation.POINT:	// 点の移動
		double p1 = ZGraphicUtil.getDistance(
						grid.getStartPoint(),mLine.getP1Z());
		double p2 = ZGraphicUtil.getDistance(
						grid.getStartPoint(),mLine.getP2Z());
		if ( p1 < p2 ) {
			mMovePoint = PT_START;
		} else {
			mMovePoint = PT_END;
		}
	}
	}

	/**
	 * 移動中Pathの取得
	 * @param grid グリッドコントローラー
	 */
	public ZPath getMovingPathGob(DocGridControler grid) {
		return new ZPath( getMovingLine(grid) );
	}

	/**
	 * 移動中座標の取得
	 * @param grid グリッドコントローラー
	 */
	public ZLine getMovingLine(DocGridControler grid) {

	ZPoint pt1 = grid.getStartGrid();
	ZPoint pt2 = grid.getMoveGrid();
	ZLine  line = getLine() ;

	switch ( grid.getMoveMode() ) {
	  case GOperation.MOVE:		// 移動
		line.translate( grid.getOffsetGrid() ) ;
		break;

	  case GOperation.NEW:		// 新規作成
		line = new ZLine( pt1, pt2 );
		break;

	  case GOperation.POINT:	// 点の移動
		if ( mMovePoint == PT_START ) {
			// 始点の移動
			line = new ZLine( pt2, mLine.getP2Z() );
		} else if ( mMovePoint == PT_END ) {
			// 終点の移動
			line = new ZLine( mLine.getP1Z(), pt2 );
		}
		break;
	}
	return( line );
	}
	//## 固有##########################################################
	/**
	 * 移動点の取得
	 */
	public int getMovePoint() {
	return mMovePoint;
	}

	//## 描画##########################################################
	/**
	 * 描画
	 * @param graphics グラフィックス
	 */
	public void paintContents(DocGraphics graphics) {
	super.paintContents(graphics);

	// 矢印の描画
	Graphics2D g2 = graphics.getGraphics();
	PStyle style = getStyle();

	// 色の設定
	Color oldColor = g2.getColor();
	g2.setColor( style.getStroke().getColor().get() );

//	ZDebug.trace(mLine.getP1Z().toString()+"→"+mLine.getP2Z().toString());
	ZPoint pt1 = graphics.getGridControler().transform( mLine.getP1Z() );
	ZPoint pt2 = graphics.getGridControler().transform( mLine.getP2Z() );

	if ( isArrow(ARROW_FORWARD) ) {
		Shape sh = ZGraphicUtil.createArrowShape( pt1, pt2, 8,4);
		// 塗りつぶし
		g2.fill( sh );
	}

	if ( isArrow(ARROW_BACKWARD) ) {
		Shape sh = ZGraphicUtil.createArrowShape( pt2, pt1, 8,4);
		// 塗りつぶし
		g2.fill( sh );
	}

	// 元に戻す
	g2.setColor( oldColor ) ;
	}

	/**
	 * 選択点の描画：開始点、終了点
	 * @param graphics グラフィックス
	 */
	public void paintSelector(DocGraphics graphics) {
	// 座標変換の適用
	graphics.getGridControler().pushTransform(getTransform());

	GSelector sel = new GSelector();
	ZPoint ptTrans = graphics.getGridControler().transform( mLine.getP1Z() );
	sel.paint(graphics.getGraphics(),ptTrans);

	ptTrans = graphics.getGridControler().transform( mLine.getP2Z() );
	sel.paint(graphics.getGraphics(),ptTrans);

	// 座標変換を元に戻す
	graphics.getGridControler().popTransform();
	}

	/**
	 * 性能向上のため描画を間引くか否かを判定する。
	 * main gobでのみ判定し、子gobはmain gobに従う
	 * @param graphics グラフィックス
	 */
	protected boolean paintCheck(DocGraphics graphics) {
	boolean bPaint = true;
	createPaintShape(graphics);

	// クリップ領域に座標が含まれない場合は、描画しない
	Rectangle2D rt     = mPaintShape.getBounds2D();
	Rectangle clipRect = graphics.getGraphics().getClipBounds();
	if (  clipRect != null &&
		( clipRect.x > (rt.getX()+rt.getWidth())  || (clipRect.x+clipRect.width)  < rt.getX() ) &&
		( clipRect.y > (rt.getY()+rt.getHeight()) || (clipRect.y+clipRect.height) < rt.getY() ) ) {
		bPaint = false;
	}

	return bPaint;
	}

	/**
	 * 描画図形の計算
	 * @param graphics グラフィックス
	 */
	protected void createPaintShape(DocGraphics graphics) {
	ZPath path  = new ZPath( getLine() );
	setPath( path );
	mPaintShape = graphics.getGridControler().transform( path );
	}

	//## FAGOT ########################################################
	/**
	 * 位置の設定
	 */
	public void setLine(ZLine data) {
		mLine.setLine( data );
	}

	/**
	 * 位置の取得
	 */
	public ZLine getLine() {
	return new ZLine(mLine);
	}

	/**
	 * 矢印の設定
	 */
	public void setArrow(int nDirection) {
	mArrow.set(nDirection);
	}

	/**
	 * 矢印の取得
	 */
	public boolean isArrow(int nDirection) {
	int nValue = mArrow.get();
	return ((nValue&nDirection)!=0);
	}

	/**
	 * Fobマネージャの登録
	 * @param mgr マネージャ
	 */
	public void setFobManager(FobManager mgr) {
		super.setFobManager(mgr);
		//{{FAGOT_ATTR
//		mLine.setFobManager(mgr,this);
		mArrow.setFobManager(mgr,this);
		//}}FAGOT_ATTR
	}

	//## CLONE ########################################################
	/**
	 * 複製インスタンスの作成
	 * 各実現クラスにおいてインスタンスを生成する
	 * 仮想クラス（およびインスタンス化されないクラス）ではnullを返す
	 */
	public Object createClone() {
	return new GLine();
	}

	/**
	 * アトリビュートの複製
	 * @param obj 複製先のオブジェクト
	 */
	public void copyAttribute( Object obj ) {
	super.copyAttribute( obj );
	((GLine)obj).setLine( getLine() );
	((GLine)obj).mArrow.set( mArrow.get() );
	}

	//##{FAGOT_ATTRIBUTE###############################################
	/**
	 * 座標
	 */
	protected ZLine		mLine;

	/**
	 * 矢印
	 */
	protected FInteger	mArrow;

	/**
	 * 矢印状態：前向き
	 */
	static final public int   ARROW_FORWARD = 1;

	/**
	 * 矢印状態：後向き
	 */
	static final public int   ARROW_BACKWARD = 2;



	/**
	 * 移動点のポインタもどき
	 */
	protected int		mMovePoint = 0;

	/**
	 * 移動点状態：なし＝全体
	 */
	static final public int   PT_NONE    = -1;

	/**
	 * 移動点状態：開始
	 */
	static final public int   PT_START   = 0;

	/**
	 * 移動点状態：終了
	 */
	static final public int   PT_END     = 1;
}
