/*
 * "Peko" Visual Novel System
 *
 * All Rights Reserved.
 * Copyright (c) 1999-2003 Tsukuba Bunko.
 *
 * $Id: SelectItemButton.java,v 1.1.2.1 2003/12/11 10:23:24 ppoi Exp $
 */
package tsukuba_bunko.peko.canvas.select;

import	java.awt.AlphaComposite;
import	java.awt.Color;
import	java.awt.Dimension;
import	java.awt.Font;
import	java.awt.Graphics;
import	java.awt.Graphics2D;
import	java.awt.RenderingHints;

import	java.awt.event.MouseEvent;
import	java.awt.event.MouseListener;

import	java.awt.font.LineBreakMeasurer;
import	java.awt.font.TextAttribute;

import	java.text.AttributedString;

import	java.util.List;
import	java.util.Map;

import	javax.swing.BorderFactory;
import	javax.swing.JComponent;

import	tsukuba_bunko.peko.Logger;
import	tsukuba_bunko.peko.PekoSystem;

import	tsukuba_bunko.peko.canvas.text.Line;


/**
 * 選択肢をユーザーに選択させるためのボタンです。
 * @author	$Author: ppoi $
 * @version	$Revision: 1.1.2.1 $
 */
public class SelectItemButton	extends	JComponent	implements MouseListener	{

	/**
	 * ボタンスタイル：幅
	 */
	public static final String	STYLE_WIDTH = "select.button.witdth";

	/**
	 * ボタンスタイル：背景色
	 */
	public static final String	STYLE_BACKGROUND_COLOR = "select.button.background.color";

	/**
	 * ボタンスタイル：背景透明度
	 */
	public static final String	STYLE_BACKGROUND_TRANSPARENCY = "select.button.background.transparency";

	/**
	 * ボタンスタイル：前景色(選択時)
	 */
	public static final String	STYLE_FOREGROUND_SELECTED = "select.button.foreground.selected";

	/**
	 * ボタンスタイル：前景色(非選択時)
	 */
	public static final String	STYLE_FOREGROUND_UNSELECTED = "select.button.foreground.unselected";

	/**
	 * ボタンスタイル：影
	 */
	public static final String	STYLE_FOREGROUND_SHADOW = "select.button.foreground.shadow";

	/**
	 * ボタンスタイル：フォント
	 */
	public static final String	STYLE_FONT = "select.button.font";


	/**
	 * owner
	 */
	private SelectCanvas	_owner = null;


	/**
	 * 選択肢
	 */
	private SelectItem	_item = null;

	/**
	 * lines
	 */
	private List	_lines = null;

	/**
	 * active foreground color
	 */
	private Color	_foregroundActive = null;

	/**
	 * non-active foreground color
	 */
	private Color	_foregroundNonActive = null;

	/**
	 * 影
	 */
	private Color	_shadow = null;

	/**
	 * 背景色を塗りつぶす際に使用する AlphaComposite
	 */
	private AlphaComposite	_alphaComposite = AlphaComposite.getInstance( AlphaComposite.SRC_OVER, 0.5f );

	/**
	 * 選択状態フラグ
	 */
	private boolean	_selected = false;

	/**
	 * size cache
	 */
	private Dimension	_size = new Dimension();


	/**
	 * <code>SelectItemButton</code> のインスタンスを作成します。
	 */
	public SelectItemButton( SelectCanvas owner )
	{
		super();
		setBorder( BorderFactory.createLoweredBevelBorder() );
		addMouseListener( this );
		_owner = owner;
	}


	public void addNotify()
	{
		super.addNotify();
		synchronized( this )	{
			notify();
		}
	}

	/**
	 * 選択肢を設定します。
	 * @param	item	選択肢
	 */
	public void setSelectItem( SelectItem item )
	{
		_item = item;
	}

	/**
	 * 選択肢を取得します。
	 * @return	選択肢
	 */
	public SelectItem getSelectItem()
	{
		return _item;
	}

	//	エラー処理は、CanvasManager でされている前提です。
	public void prepare( Map style )
	{
		Color	colorValue = (Color)style.get( SelectItemButton.STYLE_FOREGROUND_SELECTED );
		if( colorValue != null )	{
			_foregroundActive = colorValue;
		}
		else	{
			_foregroundActive = Color.white;
		}

		colorValue = (Color)style.get( SelectItemButton.STYLE_FOREGROUND_UNSELECTED );
		if( colorValue != null )	{
			_foregroundNonActive = colorValue;
		}
		else	{
			_foregroundNonActive = Color.darkGray;
		}

		colorValue = (Color)style.get( SelectItemButton.STYLE_BACKGROUND_COLOR );
		if( colorValue != null )	{
			setBackground( colorValue );
		}
		else	{
			setBackground( Color.black );
		}

		colorValue = (Color)style.get( SelectItemButton.STYLE_FOREGROUND_SHADOW );
		if( colorValue != null )	{
			_shadow = colorValue;
		}
		else	{
			_shadow = Color.black;
		}

		setForeground( _foregroundNonActive );

		Float	fv = (Float)style.get( SelectItemButton.STYLE_BACKGROUND_TRANSPARENCY );
		if( fv != null )	{
			if( fv.floatValue() != _alphaComposite.getAlpha() )	{
				_alphaComposite = AlphaComposite.getInstance( AlphaComposite.SRC_OVER, fv.floatValue() );
			}
		}
		else	{
			if( _alphaComposite.getAlpha() != 0.5f )	{
				_alphaComposite = AlphaComposite.getInstance( AlphaComposite.SRC_OVER, 0.5f );
			}
		}

		float	width = 320f;
		Integer	intValue = (Integer)style.get( SelectItemButton.STYLE_WIDTH );
		if( intValue != null )	{
			width = intValue.floatValue();
		}

		Font	fontValue = (Font)style.get( SelectItemButton.STYLE_FONT );
		if( fontValue != null )	{
			setFont( fontValue );
		}

		prepareLabel( width, 2 );
	}

	/**
	 * 選択肢を表示する準備を行います。
	 * @param	maxWidth	１行の最大幅
	 * @param	maxRows	最大行数
	 */
	public void prepareLabel( float width, int maxRows )
	{
		if( _item == null )	{
			Logger.error( "[canvas.text] not specified corresponding SelectItem." );
			return;
		}

		Graphics2D	g2 = (Graphics2D)PekoSystem.getInstance().getMainWindow().getGraphics();
		g2.setRenderingHint( RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON );

		List	lines = new java.util.ArrayList();
		float	lineWidth = width - 10f;
		float	lineHeight = 0f;

		String	text = _item.getText();
		AttributedString	astring = new AttributedString( text );
		astring.addAttribute( TextAttribute.FONT, getFont() );
		LineBreakMeasurer	lbm = new LineBreakMeasurer( astring.getIterator(), g2.getFontRenderContext() );
		int	length = text.length();
		Line	line = null;
		for( int i = 0; (i < maxRows) && (lbm.getPosition() < length); ++i )	{
			line = new Line();
			line.setTextLayout( lbm.nextLayout(width) );
			line.setShadowColor( _shadow );
			lines.add( line );
			lineHeight += line.getAscent();
			lineHeight += line.getDescent();
		}
		_lines = lines;

		Dimension	componentSize = new Dimension( (int)width, (int)lineHeight + 10 );
		setPreferredSize( componentSize );
		setSize( componentSize );
	}

	/**
	 * この選択肢ボタンの選択状態を設定します。
	 * @param	selected	選択されている場合 <code>true</code>、選択されていない場合 <code>false</code>
	 */
	public void setSelected( boolean selected )
	{
		if( _selected == selected )	{
			return;
		}

		if( selected )	{
			setForeground( _foregroundActive );
			_owner.itemSelecting( this );
		}
		else	{
			setForeground( _foregroundNonActive );
			_owner.itemDeselected( this );
		}
		_selected = selected;
		repaint();
	}


//
//	JComponent の実装
//
	public void paintComponent( Graphics g )
	{
		Graphics2D      g2 = (Graphics2D)g.create();
		g2.setComposite( _alphaComposite );
		g2.setColor( getBackground() );
		Dimension       size = getSize( _size );
		g2.fillRect( 0, 0, size.width, size.height );

		List    lines = _lines;
		if( lines != null )     {
			g2 = (Graphics2D)g;
			int	length = lines.size();
			float	x = 5f;
			float	y = 5f;
			Line	line = null;
			for( int i = 0; i < length; ++i )       {
				line = (Line)lines.get( i );
				line.setForeground( getForeground() );
				y += line.getAscent();
				line.draw( g2, x, y );
				y += line.getDescent();
			}
		}
	}

//
//	MouseListener の実装
//
	public void mousePressed( MouseEvent ev )
	{
	}

	public void mouseReleased( MouseEvent ev )
	{
	}

	public void mouseEntered( MouseEvent ev )
	{
		setSelected( true );
	}

	public void mouseExited( MouseEvent ev )
	{
		setSelected( false );
	}

	public void mouseClicked( MouseEvent ev )
	{
		if( _selected && (ev.getModifiers() == MouseEvent.BUTTON1_MASK) )	{
			_owner.itemSelected( this );
		}
	}

}
