/**
 * @(#)DocComponent.java
 *
 * Copyright 2000 by Intelligent Technology Inc. All rights reserved.
 *
 * ドキュメントコンテナ
 */
package jp.co.iti.fagot.doc;

import java.awt.Dimension;
import java.awt.Rectangle;
import java.awt.Graphics;

import java.awt.image.BufferedImage;

import javax.accessibility.Accessible;
import javax.accessibility.AccessibleContext;
import javax.swing.UIManager;
import javax.swing.JComponent;
import javax.swing.JViewport;
import javax.swing.Scrollable;
import javax.swing.SwingConstants;

import javax.swing.event.AncestorListener;
import javax.swing.event.AncestorEvent;

import jp.co.iti.fagot.ZApp;

import jp.co.iti.fagot.util.ZResource;
import jp.co.iti.fagot.util.ZDebug;
/**
 * ドキュメントコンテナとなるJComponent
 * JComponentとして必要なメソッド群を定義する。
 * このクラスの派生クラスであるDocPaneにおいて、描画に必要な構造を定義する。
 *
 * DocComponent(JComponent):コンテナ
 *
 * DocUI(ComponentUI):
 *     - コンテナのL&Fを設定
 *     - PropertyChangeハンドラの登録
 *     - EditorKitを呼び出してView,Docuemntの生成
 *     - 描画(DocView.paintの呼び出し)
 * DocUIAdapter:マウス、キーボードイベントハンドラ
 * DocGridControler:拡大縮小されても普遍なサイズのグリッドを定義する
 *
 * @author  福島康治
 * @version 1.01 2000/12/01
 */
public class DocComponent extends JComponent implements Scrollable, Accessible {

	/**
	 * コンストラクタ
	 */
	public DocComponent() {
	super();
	updateUI();
	setDocument(createDocument());

	addAncestorListener( new DocAncestorAdapter());
	}

	/**
	 * コンストラクタ
	 * @param panelId パネル識別子
	 */
	public DocComponent(String panelId){
	this();
	mPanelId = panelId;
	}

	//## IPane ########################################################
	/**
	 * パネル識別子の取得
	 */
	public String getPanelId() {
	return mPanelId;
	}

	/**
	 * ドキュメントの作成
	 */
	public DocDocument createDocument() {
	DocDocument doc = new DocDocument();
	doc.initDocument();
	return doc;
	}

	/**
	 * ドキュメントの設定
	 * @param doc ドキュメント
	 * @see JComponent#accessibleContext
	 */
	public void setDocument(DocDocument doc) {
	DocDocument oldDoc = mDoc;
    mDoc = doc;
    firePropertyChange("document", oldDoc, mDoc);
    revalidate();	// JComponent:遅延自動レイアウトをサポートします。
					// 自動レイアウトは使わないので関係ないかな？
    repaint();		//

	// コンポーネントの初期化
	setUIAdapter( createUIAdapter() );
	setGridControler( createGridControler() );
	}

	/**
	 * ドキュメントの取得
	 */
	public DocDocument getDocument() {
	return mDoc ;
	}

	//## UIアダプター #################################################
	/**
	 * UIアダプタの作成
	 * @return UIアダプタ
	 */
	public DocUIAdapter createUIAdapter() {
	return null;
	}

	/**
	 * UIアダプタの設定
	 * @param adapter UIアダプタ
	 */
	public void setUIAdapter(DocUIAdapter adapter) {
	// アダプターの設定
	if ( mUIAdapter != null ) {
		removeMouseListener( mUIAdapter );
		removeMouseMotionListener( mUIAdapter );
		removeKeyListener( mUIAdapter );
	}
	mUIAdapter = adapter;
	addMouseListener( mUIAdapter );
	addMouseMotionListener( mUIAdapter );
	addKeyListener( mUIAdapter );
	}


	//## グリッドコントローラ #########################################
	/**
	 * グリッドコントローラの作成
	 * @param grid グリッドコントローラ
	 */
	public DocGridControler createGridControler() {
	return new DocGridControler();
	}

	/**
	 * グリッドコントローラの設定
	 * @param grid グリッドコントローラ
	 */
	public void setGridControler(DocGridControler grid) {
	mGrid = grid;
	}

	/**
	 * グリッドコントローラの設定
	 * @param grid グリッドコントローラ
	 */
	public DocGridControler getGridControler() {
	ZResource res = ZApp.getTheApp().getResource();
	boolean isGrid = res.getBoolean( "edit.grid", true );
	double  dSize  = res.getInt( "edit.gridsize", 10 );
	mGrid.setEnable(isGrid);
	mGrid.setGrid(dSize,dSize);
	return mGrid;
	}

	//## UI ###########################################################
	/**
	 * UIの更新
	 */
	public void updateUI() {
	setUI( new DocUI() );
	invalidate();
	}

	/**
	 * 仮描画(Gobの作成)
	 */
	public void paintTemporary() {
	BufferedImage bi = new BufferedImage(
		(int)10,
		(int)10,
		BufferedImage.TYPE_INT_RGB);
	paintComponent(bi.createGraphics());
    }

	//## インターフェイス：Scrollable #################################
	/**
	 * コンポーネントに最適なサイズを返します
	 */
	public Dimension getPreferredScrollableViewportSize() {
	return getPreferredSize() ;
	}

	/**
	 * 1 行または 1 列を完全にエクスポーズするスクロール増分値を計算します
	 */
	public int getScrollableUnitIncrement(Rectangle visibleRect,
    	                                  int orientation,
    	                                  int direction) {
	switch(orientation) {
      case SwingConstants.VERTICAL:
        return ( 10 );
      case SwingConstants.HORIZONTAL:
        return ( 10 );
      default:
        throw new IllegalArgumentException("Invalid orientation: " + orientation);
    }
	}

	/**
	 *ブロック分をエクスポーズするスクロール増分値を計算します
	 */
	public int getScrollableBlockIncrement(Rectangle visibleRect,
    	                                   int orientation,
    	                                   int direction) {
	switch(orientation) {
      case SwingConstants.VERTICAL:
        return ( 100 /*visibleRect.height*/ );
      case SwingConstants.HORIZONTAL:
        return ( 100 /*visibleRect.width*/ );
      default:
        throw new IllegalArgumentException("Invalid orientation: " + orientation);
    }
	}

	/**
	 * ビューポートでこの Scrollable の幅を常にビューポートの幅に合わせる場合
	 * に、true を返します。
	 */
	public boolean getScrollableTracksViewportWidth() {
	if (getParent() instanceof JViewport) {
	    return (((JViewport)getParent()).getWidth() > getPreferredSize().width);
	}
	return (false);
	}

	/**
	 * ビューポートでこの Scrollable の高さを常にビューポートの高さに
	 * 合わせる場合に、true を返します。
	 */
	public boolean getScrollableTracksViewportHeight() {
	if (getParent() instanceof JViewport) {
	    return (((JViewport)getParent()).getHeight() > getPreferredSize().height);
	}
	return false;
	}

	//## インターフェイス：Accessible #################################
	/**
	 * オブジェクトに関連した AccessibleContext を返します
	 * @see JComponent#accessibleContext
	 */
	public AccessibleContext getAccessibleContext() {
	if (accessibleContext == null) {
		accessibleContext = new DocAccessibleComponent();
    }
    return accessibleContext;
	}

	//## サブクラス ###################################################
	/**
	 * 描画クラス用のユーザ補助機能のサポートを実装しています。
	 */
	public class DocAccessibleComponent extends AccessibleJComponent {
	/**
	 * コンストラクタ
	 */
	public DocAccessibleComponent() {
	}
	}

	//## サブクラス:ComponentAdapter ##################################
	public class DocAncestorAdapter implements AncestorListener{
	/*
	 * コンストラクタ
	 */
	public DocAncestorAdapter(){
	}

	/*
	 * ウィンドウがアクティブ化された
	 * 新規作成ボタンの置き換え ＆ ボタンの初期化
	 */
	public void ancestorAdded(AncestorEvent event){
	requestFocus();
	}

	/*
	 *
	 */
	public void ancestorMoved(AncestorEvent event){
	}

	/*
	 *
	 */
	public void ancestorRemoved(AncestorEvent event){
	}

	}

	//## アトリビュート################################################
    /**
     * UIアダプタ
     */
	protected DocUIAdapter	mUIAdapter = null;

    /**
     * ドキュメント
     */
	protected DocDocument	mDoc = null;

	/**
	 * パネル識別子
	 */
	protected String mPanelId = "default";

	/**
	 * グリッドコントローラー
	 */
	protected DocGridControler	mGrid = null;
}
