/*
 * @(#)RPanPanel.java
 *
 * Copyright 2001 Nomura Research Institute, LTD. All rights reserved.
 *
 * RID-X : Scaled Item draw Panel
 *
 * @author  Intelligent Technology Inc.
 * @version 1.01 2001/05/08
 */
package jp.co.nri.rid;

import java.util.Vector;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Point;
import java.awt.Shape;
import java.awt.BorderLayout;

import java.awt.event.MouseEvent;

import javax.swing.JComponent;
import javax.swing.JPanel;
import javax.swing.JViewport;

//import jp.co.iti.fagot.fob.FobManager;
import jp.co.iti.fagot.fob.FColor;

import jp.co.iti.fagot.fob.xml.XElementNS;

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

import jp.co.iti.fagot.gob.GElement;
import jp.co.iti.fagot.gob.GOperation;
import jp.co.iti.fagot.gob.GOperationSelect;
import jp.co.iti.fagot.gob.GRectangle;
import jp.co.iti.fagot.gob.PTransform;

import jp.co.iti.fagot.gob.GobManager;

import jp.co.iti.fagot.doc.DocPane;
import jp.co.iti.fagot.doc.DocElement;
import jp.co.iti.fagot.doc.DocGraphics;
import jp.co.iti.fagot.doc.DocGridControler;
import jp.co.iti.fagot.doc.DocUIAdapter;

import jp.co.iti.fagot.util.ZInstance;
import jp.co.iti.fagot.util.ZResource;
import jp.co.iti.fagot.util.ZString;
import jp.co.iti.fagot.util.ZDebug;

import jp.co.iti.fagot.ZApp;

import jp.co.nri.Rid;
/**
 * Pan Panel
 *
 * 拡大図を描画するために、RDocumentのページ、ゾーンを複写して、ミニDrawPaneを作成する
 * 利用するクラスは、
 * RPanDrawPanel	:VDrawPaneの派生クラス
 * RPanMouseAdapter	:VMouseAdapterの派生クラス
 *					 マウス移動によるカーソル変更など
 * GViewport		:GRectangleの派生クラス
 *					 コンテナをあらわすBlueのRectを描画する
 * GViewportZoom	:GOperationSelectの派生クラス
 *					 Vierportの拡大縮小時の操作で利用する
 *
 */
public class RPanPanel extends JPanel {

	/**
     * コンストラクタ
	 */
	public RPanPanel() {
		// 地図の追加
		mPanel = new RPanDrawPanel();
		setLayout(new BorderLayout());
		add("Center",mPanel);
	}

	/**
     * 再構築
	 */
	public void restract() {
	mPanel.updateGobs();
	// パンパネルは、それほど重要な画面ではないし、
	// Mapパネルと情報を共有しているので、Mapパネルよりあとで描画するよう
	// 遅延描画する
	repaint(2000);
	}

	//## アトリビュート ###############################################
    /**
     * パンパネル
     */
	protected RPanDrawPanel	mPanel	= null;

	//## サブクラス：パンパネル #######################################
	/**
	 * パンパネル
	 */
	public class RPanDrawPanel extends DocPane {
	/**
	 * コンストラクタ
	 */
	public RPanDrawPanel() {
	super("pan");
	}

	//## 再構築 #######################################################
	/**
	 * 再構築
	 */
	public void createGobs() {
	// Gobの初期化
	Vector gobs = GobManager.getElement(getPanelId());
	gobs.removeAllElements();

	// アクティブパネルの取得
	String szTitle = ZInstance.prop().getProperty( Rid.PANEL_ACTIVE );
	JComponent active = (JComponent)ZInstance.map().get(szTitle);
	if ( !(active instanceof DocPane) ) {
		// アクティブパネルが描画パネルでない場合は描画しない
		return;
	}

	DocPane panel = (DocPane)active;

	// コンテナ全体のGob
	if ( panel != null ) {
		GRectangle grect = new GRectangle();
		Dimension dim = panel.getDocument().getLogicalSize();
		grect.setRect(new ZRectangle(0,0,dim.width,dim.height));
		grect.getStyle().setFillColor( new FColor( panel.getBackground() ));
		grect.getStyle().setStrokeColor( new FColor( Color.black ));
		gobs.add( grect );
//		rect.setSelectable(false);
//		rect.setSelect(false);

		// アクティブパネルのスケルトンGobを生成
		gobs.addAll( panel.getDocument().createSkeltonGobs(panel.getPanelId()) );

		// ビューポートのGobを生成
		mViewPort = new GViewport();
		JViewport port = (JViewport)panel.getParent();
		Dimension vwdim = port.getSize();
		Point    ptTL = port.getViewPosition();
		ZRectangle rtport = new ZRectangle( ptTL.getX(),ptTL.getY(),
										(double)vwdim.width,(double)vwdim.height);

		PTransform trans = null;
		DocElement root = (DocElement)panel.getDocument().getRootElement(panel.getPanelId());
		if ( root != null ) {
			trans = root.getDisplayScaledTransform(panel.getPanelId());
		} else {
			trans = new PTransform(1,0,0,1,0,0);
		}
		Shape sh = trans.inverseTransform( rtport );

		mViewPort.setRect(new ZRectangle(sh.getBounds2D()));
		gobs.add(mViewPort);

		// 座標変換の設定
		Dimension mydim = this.getSize();
		recalcTransform(mydim.width,mydim.height);

		// ビューポートのみを選択済みに設定
		mViewPort.setSelect(true);
//		updateCurrent();
	}
	}

	/**
	 * 再構築
	 * @param width コンポーネントの幅
	 * @param height コンポーネントの高さ
	 */
	public void recalcTransform(int width,int height) {
	// アクティブパネルの取得
	String szTitle = ZInstance.prop().getProperty( Rid.PANEL_ACTIVE );
	JComponent cmp = (JComponent)ZInstance.map().get(szTitle);
	if ( !(cmp instanceof DocPane) ) {
		return ;
	}
	DocPane panel = (DocPane)cmp;

	if ( panel != null ) {
		Dimension dim = panel.getDocument().getLogicalSize();
		double inset = 5;
		// 縮小率の計算
		double dx = (width-inset*2)/dim.width;
		double dy = (height-inset*2)/dim.height;
		double dz = Math.min(dx,dy);
		// オフセットの計算
		double ox = (width-dim.width*dz)/2;
		double oy = (height-dim.height*dz)/2;

		DocElement root = (DocElement)getDocument().getRootElement(getPanelId());

		XElementNS elm = root.getChildElement(".ViewInfo."+getPanelId(),null);
		elm.setDoubleAttr("DisplayOffsetX",ox);
		elm.setDoubleAttr("DisplayOffsetY",oy);
		elm.setDoubleAttr("DisplayScale",dz);
	}
	}

	//## オーバライド #################################################
	/**
	 * UIアダプタの作成
	 * @return UIアダプタ
	 */
	public DocUIAdapter createUIAdapter() {
	return new RPanMouseAdapter(this);
	}

	/*
	 * サイズの変更
	 * @param x コンポーネントのx
	 * @param y コンポーネントのy
	 * @param width コンポーネントの幅
	 * @param height コンポーネントの高さ
	 */
	public void setBounds(int x,int y,int width,int height){
	recalcTransform(width,height);
	super.setBounds(x,y,width,height);
//	repaint();
	}

	//## Scrollableブロック ###########################################
	/**
	 * コンポーネントに最適なサイズを返します
	 */
	public Dimension getPreferredSize() {
	Dimension dim = new Dimension(50,50);
	return dim;
	}

	//## ビューポート #################################################
	/**
	 * ビューポートGOBの取得
	 */
	public GRectangle getViewPortGob() {
	return mViewPort;
	}

	//## アトリビュート ###############################################
	/**
	 * ビューポートGOB
	 */
	protected GRectangle mViewPort = null;
    }

	//## サブクラス：マウスアダプター #################################
	/**
	 * マウスアダプター
	 */
	public class RPanMouseAdapter extends DocUIAdapter {
	/**
	 * コンストラクタ
	 * @param container コンテナ
	 */
	public RPanMouseAdapter(DocPane container){
	super(container);
	}

	/**
	 * マウスがドラッグされながら移動中
	 * @param evt マウスイベント
	 */
	public void mouseDragged(MouseEvent evt){
	mEditor.getGridControler().setMoving( new ZPoint(evt.getPoint()),0 );
	mEditor.repaint();
	}

	/**
	 * 操作の取得
	 * @param evt マウスイベント
	 */
	public GElement createOperation(MouseEvent evt){
	return null;
	}

	//## イベント #####################################################
	/**
	 * 左ボタンdown
	 * @param evt マウスイベント
	 */
	protected void OnLButtonDown( MouseEvent evt ) {
	mStartPoint = new ZPoint(evt.getPoint());
	mMoveMode = GobManager.getSelectedHitMode(mEditor,mStartPoint);
	if ( mMoveMode != GOperation.HANDON ) {
		GobManager.setCurrent(mEditor.getPanelId(),new GViewportZoom());
	} else {
		// 現在選択エレメントにヒットしたので、選択されているエレメントをカレントに設定
		GobManager.updateCurrent(mEditor.getPanelId());
	}

	// 移動開始
	mEditor.getGridControler().setMoveStart( mStartPoint,mMoveMode ) ;
	GobManager.moveStart(mEditor,mEditor.getGridControler());

	// 移動中
	mEditor.getGridControler().setMoving( mStartPoint,0 ) ;

	// カーソルの変更と再描画
	mEditor.setCursor(GOperation.getCursor(mMoveMode));
	mEditor.repaint();
	}

	/**
	 * 左ボタンup
	 * @param evt マウスイベント
	 */
	protected void OnLButtonUp( MouseEvent evt ) {
	super.OnLButtonUp(evt);
	}

	/**
	 * 右ボタンdown
	 * @param evt マウスイベント
	 */
	protected void OnRButtonDown( MouseEvent evt ) {
	// 何もしない
	}
	}

	//## サブクラス：Viewportオブジェクト #############################
	/**
	 * Viewportの移動オブジェクト
	 */
	public class GViewport extends GRectangle {
	/**
	 * コンストラクタ
	 */
	public GViewport(){
	super();

	getStyle().setStrokeColor( new FColor( Color.blue ));
	mSelect = true;
	}

	/**
	 * 選択の変更
	 */
	public boolean setSelect( boolean bSelect ) {
	return false;
	}

	//## 移動##########################################################
	/**
	 * 移動の終了
	 * @param grid グリッドコントローラ
	 */
	public void moveEndGob( DocGridControler grid ) {
	ZRectangle rect = getMovingRectGob( grid ) ;
	ZPoint pt = rect.getCenter();

	// アクティブパネルの取得
	String szTitle = ZInstance.prop().getProperty( Rid.PANEL_ACTIVE );
	DocPane panel  = (DocPane)ZInstance.map().get(szTitle);
//	panel.getDocument().beginTransaction();
	panel.setCenter(pt);
	// setCenter内でupdateCenterを呼ぶよう修正
//	panel.updateCenter(pt);
//	panel.getDocument().commit();
	panel.repaint();

	// 自分自身の再構築
//	DocPane myPanel = grid.getEditor();
//	myPanel.updateGobs();
	}

	//## 位置##########################################################
	/**
	 * 要素にヒットするか？
	 * @param pt 論理座標
	 */
	public byte getHitModeGob(ZPoint pt) {
	byte mode = super.getHitModeGob(pt);
	if ( mode != GOperation.NONE ) {
//		ZDebug.trace("Hit:"+pt);
		mode = GOperation.HANDON;
	} else {
//		ZDebug.trace("　だめ"+pt);
	}
	return mode;
	}

	//## 描画##########################################################
	/**
	 * 選択点は描画しない
	 * @param g グラフィックス
	 */
	public void paintSelector(DocGraphics g) {
//	ZDebug.trace();
	}
	}

	//## サブクラス：ViewportZoomオブジェクト #########################
	/**
	 * Viewportの拡大オブジェクト
	 */
	public class GViewportZoom extends GOperationSelect {
	/**
	 * コンストラクタ
	 */
	public GViewportZoom(){
	super();
	}

	//## 移動##########################################################
	/**
	 * 移動の終了
	 * @param grid グリッドコントローラ
	 */
	public void moveEndGob( DocGridControler grid ) {
	ZRectangle rect = getMovingRectGob( grid ) ;

	// アクティブパネルの取得
	String szTitle = ZInstance.prop().getProperty( Rid.PANEL_ACTIVE );
	DocPane panel  = (DocPane)ZInstance.map().get(szTitle);

	JViewport port = (JViewport)panel.getParent();
	Dimension dim  = port.getSize();
	double dx = dim.width/ Math.max(1,rect.getWidth());
	double dy = dim.height/Math.max(1,rect.getHeight());
	double dz = Math.min(dx,dy);

	// 最大/最小サイズへの補正
	if ( dz > 4.00 ) {
		dz = 4.00;
	} else if ( dz < 0.1 ) {
		dz = 0.1;
	}

	ZPoint center = rect.getCenter();

	// 拡大率の変更
//	panel.getDocument().beginTransaction();

	// ポートの再レイアウト
	DocElement element = (DocElement)panel.getDocument().getRootElement(panel.getPanelId());
	element.setDisplayScale( panel.getPanelId(), dz );
	port.doLayout();

	// ビューポートの移動
//	ZDebug.trace("Center:"+center.toString());
	panel.setCenter( center );
	// setCenter内でupdateCenterを呼ぶよう修正
//	panel.updateCenter(center);
	// 前回描画タイミングとはTransfromが変わっているので、ハッシュを使いまわしできない。
	// したがって、移動とはことなり、CreateGobが必要
	panel.updateGobs();
	panel.repaint();
//	panel.getDocument().commit();
	}

	//## アトリビュート ###############################################
	}
}
