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

import java.util.*;
import java.io.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.font.*;
import java.awt.geom.*;
import javax.swing.*;
import javax.swing.event.*;
import jp.riken.brain.ni.samuraigraph.base.*;
import jp.riken.brain.ni.samuraigraph.data.*;
import jp.riken.brain.ni.samuraigraph.figure.*;


/**
 * レジェンドクラス
 */

public class SGLegendElement extends SGFigureElement
	implements SGILegendElement, CaretListener, WindowListener
{

	/**
	 *
	 */
	private SGIGraphElement mGraphElement = null;


	/**
	 * 
	 */
	private ArrayList mGroupSetList = new ArrayList();



	/**
	 * 倍率100%の状態での、レジェンドのＸ座標値
	 * グラフ描画領域の原点からの相対的位置
	 */
	private float mLegendX = 0.0f;
	
	
	/**
	 * 倍率100%の状態での、レジェンドのＹ座標値
	 * グラフ描画領域の原点からの相対的位置
	 */
	private float mLegendY = 0.0f;


	/**
	 * 倍率100%の状態での、レジェンドの横幅
	 */
	private float mLegendWidth = 0.0f;


	/**
	 * 倍率100%の状態での、レジェンドの縦幅
	 */
	private float mLegendHeight = 0.0f;


	/**
	 * 
	 */
	private float mFontSize = SGConstants.FONT_SIZE;


	/**
	 * 
	 */
	private int mFontStyle = SGConstants.FONT_STYLE;


	/**
	 * 
	 */
	private String mFontFamilyName = SGConstants.FONT_FAMILY_NAME;


	/**
	 * 
	 */
	private Color mStringColor = SGConstants.FONT_COLOR;


	/**
	 * 
	 */
	private float mWidthOfDataElement = 3.0f/SGConstants.CM_POINT_RATIO;


	/**
	 * 
	 */
	private float mFrameLineWidth = 0.10f/SGConstants.CM_POINT_RATIO;


	/**
	 * 
	 */
	private Color mFrameLineColor = Color.BLACK;


	/**
	 * 
	 */
	private Color mBackgroundColor = Color.WHITE;



	/**
	 *
	 */
	private boolean mLegendVisibleFlag = true;


	/**
	 * 
	 */
	private boolean mEnteredFlag = false;


	/**
	 * 
	 */
	private boolean mFrameVisibleFlag = true;


	/**
	 * 
	 */
	private boolean mLegendTransparentFlag = true;


	/**
	 * 
	 */
	private SGProperties mTemporaryProperties = null;


	/**
	 * ポップアップメニュー
	 */
	private JPopupMenu mPopupMenu = null;


	/**
	 * ダイアログ
	 */
	private SGLegendDialog mDialog = null;


	/**
	 * 
	 */
	private JTextField mEditField = new JTextField();


	/**
	 * 
	 */
	protected static final String ADD_POLYLINE_GRAPH = "Add the Polyline Graph";

	/**
	 * 
	 */
	protected static final String ADD_SYMBOL_GRAPH = "Add the Symbol Graph";

	/**
	 * 
	 */
	protected static final String ADD_BAR_GRAPH = "Add the Bar Graph";


	/**
	 * 
	 */
	private final String SHOW_LEGEND = "Show legend";


	/**
	 * 
	 */
	private final String DRAW_FRAME = "Draw flame";



	/**
	 * コンストラクタ
	 */
	public SGLegendElement()
	{
		super();
		this.initEditField();

		if( this.init() == false )
		{
			throw new Error();
		}
	}



	/**
	 * 
	 */
	private boolean init()
	{
		this.setLegendVisible( SGDefaultValues.LEGEND_VISIBLE );
		this.setFontFamilyName( SGDefaultValues.LEGEND_FONT_FAMILY_NAME );
		this.setFontSize( SGDefaultValues.LEGEND_FONT_SIZE );
		final int style = SGUtilityText.getFontStyle( SGDefaultValues.LEGEND_FONT_STYLE );
		if( style==-1 )
		{
			return false;
		}
		this.setFontStyle( style );
		this.setStringColor( SGDefaultValues.LEGEND_STRING_COLOR );
		this.setFrameVisible( SGDefaultValues.LEGEND_FRAME_VISIBLE );
		this.setFrameLineWidth( SGDefaultValues.LEGEND_FRAME_WIDTH );
		this.setFrameLineColor( SGDefaultValues.LEGEND_FRAME_COLOR );
		this.setBackgroundColor( SGDefaultValues.LEGEND_BACKGROUND_COLOR );
		this.setLegendTransparent( SGDefaultValues.LEGEND_TRANSPARENT );

		return true;
	}




	/**
	 * 
	 * @return
	 */
	public String toString()
	{
		return new String("SGLegendElement");
	}


	/**
	 *
	 */
	public boolean addData( final SGData data )
	{

		if( mGraphElement==null || data==null )
		{
			throw new Error("mGraphElement==null || data==null");
		}

		super.addData( data );


		//
		// レジェンドの要素を新規作成
		//

		ElementGroupSetInLegend legend = this.createLegendElement( data );
		if( legend == null )
		{
			return false;
		}


		// 倍率
		legend.setMagnification( this.mMagnification );

//System.out.println(legend);

		// LegendDataをリストに追加
		this.mGroupSetList.add( legend );


		// 描画要素の作成
		this.createAllDrawingElements();


		return true;
	}



	/**
	 * 
	 */
	private ElementGroupSetInLegend createLegendElement( final SGData data )
	{

		ElementGroupSetInLegend legend = null;
		if( ( data instanceof SGSXYData )
			|| ( data instanceof SGSXYMultipleData ) )
		{
			legend = new ElementGroupSetInLegendSXY();
		}
		else if( data instanceof SGVXYData )
		{
			legend = new ElementGroupSetInLegendVXY();
		}
		else
		{
			return null;
		}


		// name of data
		String name = mGraphElement.getDataName(data);
		legend.setName( name );


		// drawing elements
		ArrayList elementList = mGraphElement.getDrawingElementList(data);
		if( ( data instanceof SGSXYData )
			|| ( data instanceof SGSXYMultipleData ) )
		{
			for( int ii=0; ii<elementList.size(); ii++ )
			{
				SGDrawingElement element = (SGDrawingElement)elementList.get(ii);

				if( element instanceof SGDrawingElementLine )
				{
					legend.addDrawingElementGroup( SGElementGroup.POLYLINE_GROUP );
				}
				else if( element instanceof SGDrawingElementRectangle )
				{
					legend.addDrawingElementGroup( SGElementGroup.RECTANGLE_GROUP );
				}
				else if( element instanceof SGDrawingElementSymbol )
				{
					legend.addDrawingElementGroup( SGElementGroup.SYMBOL_GROUP );
				}
				else
				{
					throw new Error();
				}
			}
		}
		else if( data instanceof SGVXYData )
		{
			for( int ii=0; ii<elementList.size(); ii++ )
			{
				SGDrawingElement element = (SGDrawingElement)elementList.get(ii);

				if( element instanceof SGDrawingElementArrow )
				{
					legend.addDrawingElementGroup( SGElementGroup.ARROW_GROUP );
				}
				else
				{
					throw new Error();
				}
			}
		}
		else
		{
			throw new Error("This data-type is not defined.");
		}


		// visible flag
		ArrayList visibleFlagList = this.mGraphElement.getVisibleFlagList(data);
		ArrayList groupList = legend.mDrawingElementGroupList;
		if( visibleFlagList.size()!=groupList.size() )
		{
			throw new Error();
		}
		for( int ii=0; ii<groupList.size(); ii++ )
		{
			SGElementGroup group = (SGElementGroup)groupList.get(ii);
			boolean b = ((Boolean)visibleFlagList.get(ii)).booleanValue();
			group.setVisible(b);
		}


		return legend;

	}



	/**
	 * 
	 */
	public ArrayList getDrawingElementList( final SGData data )
	{
		return getLegendData(data).getDrawingElementList();
	}


	/**
	 * 
	 */
	public String getDataName( final SGData data )
	{
		ElementGroupSetInLegend groupSet = getLegendData(data);
		
		if( groupSet != null )
		{
			return groupSet.mName;
		}

		return null;
	}


	/**
	 * 
	 */
	public boolean isDataVisible( SGData data )
	{
		SGElementGroupSet groupSet = this.getElementGroupSet(data);
		boolean flag = groupSet.isVisible();
//System.out.println(data+"  "+flag);

		return flag;
	}


	/**
	 * 引数で渡されたSGDataオブジェクトに対応したLegendDataオブジェクトを取得する
	 */
	protected ElementGroupSetInLegend getLegendData( final SGData data )
	{
		for( int ii=0; ii<this.mDataList.size(); ii++ )
		{
			SGData data_ = (SGData)this.mDataList.get(ii);
			if( data_.equals(data) )
			{
				ElementGroupSetInLegend lData = (ElementGroupSetInLegend)this.mGroupSetList.get(ii);
				return lData;
			}
		}

		return null;
	}



	/**
	 * 
	 */
	public ArrayList getVisibleFlagList( final SGData data )
	{

		if( data==null )
		{
			return null;
		}

		ArrayList list = new ArrayList();

		ElementGroupSetInLegend groupSet = getLegendData(data);
		
		ArrayList groupList = groupSet.mDrawingElementGroupList;
		for( int jj=0; jj<groupList.size(); jj++ )
		{
			SGElementGroup group = (SGElementGroup)groupList.get(jj);
			boolean flag = group.isVisible();
			list.add( new Boolean(flag) );
		}

		return list;
	}



	/**
	 * フィギュア内でのＸ座標を返す
	 */
	public float getLegendX()
	{
		return this.mGraphAreaX + this.mLegendX*this.mMagnification;
	}



	/**
	 * フィギュア内でのＹ座標を返す
	 */
	public float getLegendY()
	{
		return this.mGraphAreaY + this.mLegendY*this.mMagnification;
	}


	/**
	 * 
	 */
	public float getLegendWidth()
	{
		return this.mLegendWidth;
	}


	/**
	 * 
	 */
	public float getLegendHeight()
	{
		return this.mLegendHeight;
	}



	/**
	 * 倍率100%のときの、フィギュア内での位置を返す
	 */
	public Point2D getLegendLocation()
	{
		Point2D pos = new Point2D.Float(
			this.getLegendX(),
			this.getLegendY()
		);
		return pos;
	}



	/**
	 * 引数は任意の倍率における、フィギュア内における位置
	 */
	public boolean setLegendLocation( float x, float y )
	{
		this.mLegendX = ( x - this.mGraphAreaX )/this.mMagnification;
		this.mLegendY = ( y - this.mGraphAreaY )/this.mMagnification;
		return true;
	}




	/**
	 * 
	 */
	private boolean initEditField()
	{
		this.setLayout(null);
		this.add(this.mEditField);
		this.mEditField.setVisible(false);
		this.mEditField.addActionListener(this);
		this.mEditField.addCaretListener(this);

		return true;
	}



	/**
	 * 
	 * @return
	 */
	public boolean clearSelectedElements()
	{
		super.clearSelectedElements();

		if( !mLegendVisibleFlag )
		{
			return true;
		}

		// 
		if( this.mEditField.isVisible() )
		{
			this.terminateEditField();
		}
		this.clearFocusedGroup();
//		repaint();

		return true;
	}



	/**
	 * 
	 * @return
	 */
	public boolean setDialogOwner( final Frame frame )
	{
		super.setDialogOwner(frame);
		
		this.createDialog();
		
		return true;
	}



	/**
	 * 
	 */
	public JDialog getDialog()
	{

		// 色設定ボタン
		this.mDialog.setColorButtonBorder(true);


		// set the location
		this.mDialog.setLocation( this.mDialogOwner.getLocation() );


		// ダイアログに設定
		this.setDialogProperty();


		// テンポラリオブジェクトを作成
		this.mTemporaryProperties = this.getProperties();


		return this.mDialog;

	}



	/**
	 * 
	 */
	private boolean createDialog()
	{

		SGLegendDialog dg = new SGLegendDialog( this.mDialogOwner, true );

		dg.setActionListener(this);


		//
		// add an WindowListener
		//
		
		dg.addWindowListener( this );


		this.mDialog = dg;

		return true;
	}



	/**
	 * 
	 */
	private boolean setDialogProperty()
	{

		SGLegendDialog dg = this.mDialog;
		
		//
		dg.setLegendVisible( this.mLegendVisibleFlag );

		//
		dg.setFrameVisible( this.mFrameVisibleFlag );
		dg.setFrameLineWidth( this.mFrameLineWidth );
		dg.setFrameLineColor( this.mFrameLineColor );


		//
		dg.setFontFamilyName( this.mFontFamilyName );
		dg.setFontSize( this.mFontSize );
		dg.setTextColor( this.mStringColor );
		dg.setFontStyle( this.mFontStyle );


		//
		dg.setBackgroundColor( this.mBackgroundColor );
		dg.setLegendTransparent( this.mLegendTransparentFlag );

		return true;

	}


	/**
	 * 
	 */
	private LegendCommonProperties getCommonPropertiesFromDialog()
	{

		SGLegendDialog dg = this.mDialog;

		LegendCommonProperties p = dg.getCommonProperties();
		if( p==null )
		{
			return null;
		}

		p.x = this.mLegendX;
		p.y = this.mLegendY;


/*
		// visible
		p.visible = dg.getLegendVisible();

		// frame
		p.frameLineVisible = dg.getFrameVisible();
		p.frameLineWidth = dg.getFrameLineWidth();
		p.frameLineColor = dg.getFrameLineColor();
		p.backgroundColor = dg.getBackgroundColor();
		p.transparent = dg.isLegendTransparent();

		// font
		p.fontFamilyName = dg.getFontFamilyName();
		p.fontSize	= dg.getFontSize();
		p.fontStyle = dg.getFontStyle();
		p.stringColor = dg.getTextColor();
*/

		return p;
	}


	/**
	 * 
	 */
	protected SGProperties getCommonProperties()
	{
		LegendCommonProperties p = new LegendCommonProperties();

		p.x = this.mLegendX;
		p.y = this.mLegendY;

		p.visible = this.isLegendVisible();
		p.frameLineVisible = this.isFrameLineVisible();
		p.frameLineWidth = this.getFrameLineWidth();
		p.frameLineColor = this.getFrameLineColor();
		p.backgroundColor = this.getBackgroundColor();
		p.transparent = this.isLegendTransparent();
		p.fontFamilyName = this.getFontFamilyName();
		p.fontSize = this.getFontSize();
		p.fontStyle = this.getFontStyle();
		p.stringColor = this.getStringColor();

		return p;
	}


	/**
	 * 
	 */
/*	protected ArrayList getDataPropertiesList()
	{
		ArrayList list = new ArrayList();
		for( int ii=0; ii<this.mGroupSetList.size(); ii++ )
		{
			ElementGroupSetInLegend groupSet
				= (ElementGroupSetInLegend)this.mGroupSetList.get(ii);
			SGProperties p = groupSet.getProperties();
			list.add(p);
		}
		return list;
	}
*/


	/**
	 * 
	 */
	protected TreeMap getDataPropertiesMap()
	{
		TreeMap map = new TreeMap();
		for( int ii=0; ii<this.mGroupSetList.size(); ii++ )
		{
			ElementGroupSetInLegend groupSet
				= (ElementGroupSetInLegend)this.mGroupSetList.get(ii);
			if( groupSet.isVisible() == false )
			{
				continue;
			}
			SGProperties p = groupSet.getProperties();
			SGData data = this.getData( groupSet );
			map.put( new Integer(data.hashCode()), p );
		}
		return map;
	}
	


	/**
	 * 
	 */
	public SGProperties getProperties()
	{
		LegendProperties wp = new LegendProperties();

		wp.cp = (LegendCommonProperties)this.getCommonProperties();
//		wp.dpList = this.getDataPropertiesList();

wp.dpMap = this.getDataPropertiesMap();


		return wp;
	}



	/**
	 * 
	 */
	public boolean setProperties( final SGProperties p )
	{
//System.out.println("<< SGLegendElement::setProperties >>");
//System.out.println(p);

		if( ( p instanceof LegendProperties ) == false ) return false;

//System.out.println("1");

		LegendProperties wp = (LegendProperties)p;

//System.out.println(this.mGroupSetList.size());
//System.out.println(wp.dpMap.size());

//		if( this.mGroupSetList.size() != wp.dpMap.size() ) return false;

//System.out.println("2");

		if( this.setCommonProperties( wp.cp ) == false )
		{
			return false;
		}
//System.out.println("3");

/*
		for( int ii=0; ii<wp.dpList.size(); ii++ )
		{
//System.out.println("ii="+ii);
			SGProperties pp = (SGProperties)wp.dpList.get(ii);
			SGElementGroupSet groupSet = (SGElementGroupSet)this.mGroupSetList.get(ii);
			groupSet.setProperties(pp);
//System.out.println(pp);
		}
//System.out.println();
*/

		TreeMap map = wp.dpMap;
//System.out.println(map);
		Iterator itr = map.keySet().iterator();
		while( itr.hasNext() )
		{
			Integer code = (Integer)itr.next();
			SGData data = this.getData(code.intValue());
			SGElementGroupSet groupSet = this.getElementGroupSet(data);
			if( groupSet.isVisible() == false )
			{
				continue;
			}
			SGProperties pp = (SGProperties)map.get( new Integer( data.hashCode() ) );
			if( groupSet.setProperties(pp) == false )
			{
				return false;
			}
		}

/*
		for( int ii=0; ii<this.mGroupSetList.size(); ii++ )
		{
			SGElementGroupSet groupSet = (SGElementGroupSet)this.mGroupSetList.get(ii);
			SGData data = this.getData( groupSet );
			SGProperties pp = (SGProperties)map.get( new Integer( data.hashCode() ) );
			if( groupSet.setProperties(pp) == false )
			{
				return false;
			}
		}
*/

		return true;
	}



	/**
	 * 
	 * @param hashCode
	 * @return
	 */
	protected SGData getData( final int hashCode )
	{
		for( int ii=0; ii<this.mDataList.size(); ii++ )
		{
			SGData data = (SGData)this.mDataList.get(ii);
			if( data.hashCode() == hashCode )
			{
				return data;
			}
		}
		return null;
	}



	/**
	 * 
	 */
	private boolean setCommonProperties( final LegendCommonProperties p )
	{

		this.mLegendX = p.x;
		this.mLegendY = p.y;

		this.setLegendVisible( p.visible );
		this.setFrameVisible( p.frameLineVisible );
		this.setFrameLineWidth( p.frameLineWidth );
		this.setFrameLineColor( p.frameLineColor );
		this.setBackgroundColor( p.backgroundColor );
		this.setLegendTransparent( p.transparent );
		this.setFontFamilyName( p.fontFamilyName );
		this.setFontSize( p.fontSize );
		this.setFontStyle( p.fontStyle );
		this.setStringColor( p.stringColor );

		return true;
	}



	/**
	 * 
	 */
	private boolean setPropertyWithDialog()
	{
		LegendCommonProperties p = this.getCommonPropertiesFromDialog();
		if( p==null )
		{
			return false;
		}

		this.setCommonProperties(p);
		return true;
	}





	/**
	 * 属性の全データをもとに描画要素を作り直す
	 */
	private boolean createAllDrawingElements()
	{
//System.out.println("<< SGLegendElement::createAllDrawingElements >>");

		// リストから配列にコピー
		int num = mGroupSetList.size();
		ElementGroupSetInLegend[] legendArray = new ElementGroupSetInLegend[num];
		for( int ii=0; ii<num; ii++ )
		{
			legendArray[ii] = (ElementGroupSetInLegend)mGroupSetList.get(ii);
		}


		// 文字列描画要素の作成
		for( int ii=0; ii<num; ii++ )
		{
			legendArray[ii].createDrawingString();
		}


		// 文字列描画要素を囲む矩形を取得
		Rectangle2D[] nameRectArray = new Rectangle2D[num];
		for( int ii=0; ii<num; ii++ )
		{
			nameRectArray[ii] = legendArray[ii].getDrawingStringBounds();
		}


		// 文字列描画要素の高さを取得
		float[] nameHeightArray = new float[num];
		for( int ii=0; ii<num; ii++ )
		{
			nameHeightArray[ii] = (float)nameRectArray[ii].getHeight();
		}


		// 文字列描画要素を囲む矩形の中で最長の幅を取得する
		float nameLength = 0.0f;
		for( int ii=0; ii<num; ii++ )
		{
			float width = (float)nameRectArray[ii].getWidth();
			if( width > nameLength )
			{
				nameLength = width;
			}
		}
		float nameLengthRatio = nameLength;



		// データから取得した描画要素から最長の幅を取得する
		float maxWidthDataElement = 0.0f;
		for( int ii=0; ii<num; ii++ )
		{
			float width = legendArray[ii].getMaxDataElementWidth();
			if( width > maxWidthDataElement )
			{
				maxWidthDataElement = width;
			}

			// 少なくともシンボルに関してはここで幅を取得して比較
			// mWidthDataElementのデフォルト値に比べて大きい場合には、
			// mWidthDataElementの値を更新する

		}
maxWidthDataElement = this.mMagnification*mWidthOfDataElement;


		// レジェンド全体の幅
		mLegendWidth = mWidthOfDataElement + nameLengthRatio/this.mMagnification;


		// データから取得した描画要素から高さを取得する
		double[] dataElementHeightArray = new double[num];
		for( int ii=0; ii<num; ii++ )
		{
			dataElementHeightArray[ii] = legendArray[ii].getMaxDataElementHeight();
		}


		// データ描画要素とデータ文字列の対で考えた場合の高さ
		float[] dataHeightArray = new float[num];
		for( int ii=0; ii<num; ii++ )
		{
			dataHeightArray[ii] = (float)Math.max( dataElementHeightArray[ii], nameHeightArray[ii] );
//System.out.println(dataHeightArray[ii]);
		}
		float[] dataHeightRatioArray = new float[num];
		for( int ii=0; ii<num; ii++ )
		{
			dataHeightRatioArray[ii] = dataHeightArray[ii];
		}


		// 対ごとの矩形の配列
		Rectangle2D[] dataRectRatioArray = new Rectangle2D[num];
		float rectY = this.getLegendY();
		for( int ii=0; ii<num; ii++ )
		{
			if( legendArray[ii].isVisible() == false )
			{
				continue;
			}
			float x = this.getLegendX();
			float y = rectY;
			float w = this.mMagnification*mLegendWidth;
			float h = dataHeightRatioArray[ii];
			rectY += h;
			dataRectRatioArray[ii] = new Rectangle2D.Float(x,y,w,h);
//System.out.println(ii+"  "+dataRectRatioArray[ii]);
		}
//System.out.println();



		// 矩形を設定
		for( int ii=0; ii<num; ii++ )
		{
			if( legendArray[ii].isVisible() == false )
			{
				continue;
			}
			legendArray[ii].mDataRect = dataRectRatioArray[ii];
		}



		// レジェンド全体の位置情報の設定
		mLegendHeight = 0.0f;
		for( int ii=0; ii<num; ii++ )
		{
			if( legendArray[ii].isVisible() == false )
			{
				continue;
			}
			mLegendHeight += dataHeightRatioArray[ii]/this.mMagnification;
		}


		// 描画要素の作成
		for( int ii=0; ii<num; ii++ )
		{
			if( legendArray[ii].isVisible() == false )
			{
				continue;
			}
			legendArray[ii].createDrawingElement();
		}


		// 文字列描画要素の描画位置を指定
		for( int ii=0; ii<num; ii++ )
		{
			if( legendArray[ii].isVisible() == false )
			{
				continue;
			}
			float x = this.getLegendX() + mWidthOfDataElement*this.mMagnification;
			float y = ( (float)dataRectRatioArray[ii].getY()
				+ 0.50f*(float)dataRectRatioArray[ii].getHeight()
				- 0.50f*nameHeightArray[ii] );
			legendArray[ii].mDrawingString.setLocation( (float)x, (float)y );
//System.out.println(x+"  "+y);
//System.out.println(legendArray[ii].mDrawingString.getElementBounds());
		}

		return true;
	}




	/**
	 * 
	 */
	public boolean setGraphAreaRect(
		final float x, final float y, final float width, final float height )
	{
		super.setGraphAreaRect(x,y,width,height);

		this.createAllDrawingElements();

//		this.repaint();

		return true;
	}




	/**
	 * 
	 */
	public void paintGraphics2D( final Graphics2D g2d )
	{

		super.paintGraphics2D(g2d);


		if( this.mLegendVisibleFlag || this.mEnteredFlag )
		{

			// 背景の塗りつぶし
			if( this.mLegendTransparentFlag == false )
			{
				Rectangle2D rect = this.getLegendRect();
				g2d.setPaint( this.getBackgroundColor() );
				g2d.fill(rect);
			}


			// グラフの描画
			for( int ii=0; ii<this.mGroupSetList.size(); ii++ )
			{
				ElementGroupSetInLegend groupSet
					= (ElementGroupSetInLegend)this.mGroupSetList.get(ii);

				if( groupSet.isVisible() == false )
				{
					continue;
				}
	
				groupSet.paintGraphics2D( g2d );
			}


			// フレームを描画する
			if( this.mFrameVisibleFlag && this.mGroupSetList.size()!=0 )
			{
				this.drawLegendFrameLines(g2d);
			}

		}

	}



	/**
	 * 
	 * @param g2d
	 */
	private void drawLegendFrameLines( final Graphics2D g2d )
	{

		boolean flag = false;
		for( int ii=0; ii<this.mGroupSetList.size(); ii++ )
		{
			SGElementGroupSet groupSet
				= (SGElementGroupSet)this.mGroupSetList.get(ii);
			if( groupSet.isVisible() == true )
			{
				flag = true;
				break;
			}
		}

		if( !flag )
		{
			return;
		}

		g2d.setPaint( this.mFrameLineColor );

		g2d.setStroke(
			new BasicStroke
			(
				(float)(this.mMagnification*this.mFrameLineWidth),
				BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER
			)
		);

		double x = this.getLegendX();
		double y = this.getLegendY();
		double w = this.mMagnification*mLegendWidth;
		double h = this.mMagnification*mLegendHeight;

		g2d.drawRect(
			(int)x,
			(int)y,
			(int)w,
			(int)h
		);

	}



	/**
	 * 
	 */
	public boolean contains( final int x, final int y )
	{
		Rectangle2D rect = new Rectangle2D.Float(
			this.getLegendX(),
			this.getLegendY(),
			mLegendWidth,
			mLegendHeight );
		return rect.contains(x,y);
	}



	/**
	 * 
	 */
	public boolean removeData( final SGData data )
	{

		for( int ii=this.mDataList.size()-1; ii>=0; ii-- )
		{
			SGData data_ = (SGData)mDataList.get(ii);
			if( data_.equals(data) )
			{
				this.mDataList.remove(ii);
				this.mGroupSetList.remove(ii);
			}
		}

		return true;
	}


	/**
	 * 
	 */
	protected boolean moveGraphToFront( final SGElementGroupSet groupSet )
	{
		SGData data = null;

		for( int ii=0; ii<this.mGroupSetList.size(); ii++ )
		{
			if( groupSet.equals(this.mGroupSetList.get(ii)) )
			{
				mGroupSetList.remove(ii);
				data = (SGData)mDataList.remove(ii);
				break;
			}
		}

		mGroupSetList.add(mGroupSetList.size(),groupSet);
		mDataList.add(mDataList.size(),data);

		return true;
	}


	/**
	 * 
	 */
	protected boolean moveGraphToBack( final SGElementGroupSet groupSet )
	{
		SGData data = null;

		for( int ii=0; ii<this.mGroupSetList.size(); ii++ )
		{
			if( groupSet.equals(this.mGroupSetList.get(ii)) )
			{
				mGroupSetList.remove(ii);
				data = (SGData)mDataList.remove(ii);
				break;
			}
		}

		mGroupSetList.add(0,groupSet);
		mDataList.add(0,data);

		return true;
	}


	/**
	 * 
	 */
	protected boolean removeGraph( final SGElementGroupSet groupSet )
	{
		for( int ii=0; ii<this.mGroupSetList.size(); ii++ )
		{
			if( groupSet.equals(this.mGroupSetList.get(ii)) )
			{
				mGroupSetList.remove(ii);
				mDataList.remove(ii);
				return true;
			}
		}

		return false;
	}



	/**
	 * 同期を取る
	 */
	public boolean synchronize( final SGIFigureElement element )
	{

		boolean flag = true;
		if( element instanceof SGIAxisElement )
		{

		}
		else if( element instanceof SGIGraphElement )
		{
//System.out.println("SGIGraphElement");

			SGIGraphElement gElement = (SGIGraphElement)element;
			flag = this.synchronizeToGraphElement( gElement );

		}
		else if( element instanceof SGIStringElement )
		{
			
		}
		else if( element instanceof SGILegendElement )
		{
			
		}
		else
		{
			flag = element.synchronizeArgument( this );
		}


		return flag;
	}



	/**
	 * 
	 */
	private boolean synchronizeToGraphElement( final SGIGraphElement gElement )
	{

//System.out.println("&&& synchronizeToGraphElement &&&");
//System.out.println(this.mDataList);
//System.out.println();

//		boolean diffFlag = false;


		// グラフからデータのリストを取得し、自分の持っているデータリストと
		// 描画要素リストをそれに合わせて並び替える

		ArrayList dataList = gElement.getDataList();
		if( dataList.size() != this.mDataList.size() )
		{
			throw new Error("dataList.size() != this.mDataList.size()");
		}
		ArrayList dataListNew = new ArrayList();
		ArrayList groupSetListNew = new ArrayList();
		for( int ii=0; ii<dataList.size(); ii++ )
		{
			SGData data = (SGData)dataList.get(ii);
			for( int jj=this.mDataList.size()-1; jj>=0; jj-- )
			{
				SGData data_ = (SGData)this.mDataList.get(jj);
				if( data.equals(data_) )
				{
					SGData dataRemoved = (SGData)this.mDataList.remove(jj);
					dataListNew.add(dataRemoved);
					SGElementGroupSet groupSetRemoved
						= (SGElementGroupSet)this.mGroupSetList.remove(jj);
					groupSetListNew.add(groupSetRemoved);
					break;
				}
			}
		}
		this.mDataList = dataListNew;
		this.mGroupSetList = groupSetListNew;
			

		// 描画要素のプロパティの同期を取る
		for( int ii=this.mDataList.size()-1; ii>=0; ii-- )
		{
			SGData data = (SGData)mDataList.get(ii);

			ElementGroupSetInLegend legend
				= (ElementGroupSetInLegend)this.mGroupSetList.get(ii);

			// name of data
			String nameNew = gElement.getDataName(data);
//			if( nameNew.equals( legend.mName ) == false )
//			{
//				diffFlag = true;
//			}
			legend.mName = nameNew;

			// visible
			legend.setVisible( gElement.isDataVisible(data) );


			// drawing element of data
			legend.mDrawingElementGroupList.clear();
			ArrayList sList = gElement.getDrawingElementList(data);
			for( int jj=0; jj<sList.size(); jj++ )
			{
				SGDrawingElement el = (SGDrawingElement)sList.get(jj);
				legend.addDrawingElementGroup(el);
			}


			// add to the group-set list
			mGroupSetList.set( ii, legend );

		}


		this.createAllDrawingElements();			


//		if( diffFlag )
//		{
//			this.addToLatestHistory();
//		}


		return true;
	}



	/**
	 * 同期させる
	 */
	public boolean synchronizeArgument( final SGIFigureElement element )
	{
		if( true )
		{
			throw new Error("");
		}

		return false;
	}



	/**
	 * 
	 */
	public boolean setISize( final SGTuple2f size )
	{
		super.setISize(size);

		this.drawBackLegend();


		// 描画要素を作成
		createAllDrawingElements();
//		repaint();

		return true;

	}



	/**
	 * ズーム
	 */
	public boolean zoom( final float ratio )
	{
		super.zoom(ratio);

		for( int ii=0; ii<this.mGroupSetList.size(); ii++ )
		{
			ElementGroupSetInLegend lData
				= (ElementGroupSetInLegend)this.mGroupSetList.get(ii);
			lData.zoom(ratio);
		}


		// 描画要素を作成
		createAllDrawingElements();
//		repaint();

		return true;
	}





	/**
	 * 
	 */
	public boolean getMarginAroundGraphAreaRect(
		SGTuple2f topAndBottom, SGTuple2f leftAndRight )
	{

		if( super.getMarginAroundGraphAreaRect( topAndBottom, leftAndRight ) == false )
		{
			return false;
		}


		Rectangle2D graphRect = this.getGraphAreaRect();
		Rectangle2D lRect = this.getLegendRect();
		if( lRect.getWidth() < Double.MIN_VALUE || lRect.getHeight() < Double.MIN_VALUE )
		{
			return true;
		}


		ArrayList list = new ArrayList();
		list.add( graphRect );
		list.add( lRect );

		Rectangle2D uniRect = SGUtility.createUnion(list);

//System.out.println(graphRect);
//System.out.println(lRect);
//System.out.println(uniRect);		

		final float top = (float)( graphRect.getY() - uniRect.getY() );
		final float bottom = (float)( ( uniRect.getY() + uniRect.getHeight() )
			- ( graphRect.getY() + graphRect.getHeight() ) );
		final float left = (float)( graphRect.getX() - uniRect.getX() );
		final float right = (float)( ( uniRect.getX() + uniRect.getWidth() )
			- ( graphRect.getX() + graphRect.getWidth() ) );

		topAndBottom.x += top;
		topAndBottom.y += bottom;
		leftAndRight.x += left;
		leftAndRight.y += right;

//System.out.println(topAndBottom+"  "+leftAndRight);

//System.out.println();

		return true;
	}




	/**
	 * 
	 */
	public boolean onMouseClicked( final MouseEvent e )
	{

//System.out.println("<< onMouseClicked >>");

		// if the legend is invisible, return false
		if( !mLegendVisibleFlag )
		{
			return false;
		}

/*
		// 前処理
		if( this.mEditField.isVisible() )
		{
			this.terminateEditField();
		}
*/

		final int x = e.getX();
		final int y = e.getY();

		for( int ii=0; ii<mGroupSetList.size(); ii++ )
		{
//System.out.println("ii="+ii);

			ElementGroupSetInLegend legend
				= (ElementGroupSetInLegend)mGroupSetList.get(ii);


			if( legend.isVisible() == false )
			{
				continue;
			}


			Rectangle2D rect = legend.getRect();
			if( rect == null )
			{
				continue;
			}
//System.out.println(rect);

			if( rect.contains( e.getX(), e.getY() ) == true )
			{
//System.out.println("true");

				ArrayList list = legend.mDrawingElementGroupList;
				for( int jj=list.size()-1; jj>=0; jj-- )
				{
					SGElementGroup group = (SGElementGroup)list.get(jj);
					if( group.isVisible() == false )
					{
						continue;
					}

					SGDrawingElement[] array = group.mDrawingElementArray;
					for( int kk=0; kk<array.length; kk++ )
					{
						final boolean flag = array[kk].contains(x,y);
						if( flag )
						{
							if( (SwingUtilities.isRightMouseButton(e) )
								&& ( e.getClickCount() == 1 ) )
							{
//								JPopupMenu menu = group.getPopupMenu();
//								menu.show( this, e.getX(), e.getY());
//System.out.println(element);
//System.out.println(menu);
//System.out.println();
							}
							else if( (SwingUtilities.isLeftMouseButton(e) )
							&& ( e.getClickCount() == 2 ) )
							{
//								JDialog dialog = group.getDialog();
//								dialog.show();
							}

							return true;
						}

					}

				}


				if( (SwingUtilities.isRightMouseButton(e) )
					&& ( e.getClickCount() == 1 ) )
				{
//					JPopupMenu menu = legend.getPopupMenu();
//					menu.show( this, e.getX(), e.getY());
				}
				else if( (SwingUtilities.isLeftMouseButton(e) )
				&& ( e.getClickCount() == 1 ) )
				{
//System.out.println("######################");
					Rectangle2D sRect = legend.getDrawingStringBounds();
//System.out.println(legend.mDrawingString.getX()+"  "+legend.mDrawingString.getY());
//System.out.println(sRect);
//System.out.println(e.getPoint());
//System.out.println();

					if( sRect.contains( e.getX(), e.getY() ) )
					{
//System.out.println("*** show ***");
						this.showEditField(legend);
//System.out.println(this.mEditField.getBounds());
//System.out.println(e.getPoint());
					}
//System.out.println();

				}
				else if( (SwingUtilities.isLeftMouseButton(e) )
				&& ( e.getClickCount() == 2 ) )
				{
					this.getDialog().show();
				}

				return true;
			}
			
		}

//System.out.println();

		return false;	
	}



	/**
	 * 
	 */
	private ElementGroupSetInLegend mFocusedGroup = null;



	/**
	 * 
	 */
	public String getFontFamilyName()
	{
		return this.mFontFamilyName;
	}



	/**
	 * 
	 */
	public int getFontStyle()
	{
		return this.mFontStyle;
	}


	/**
	 * 
	 */
	public float getFontSize()
	{
		return this.mFontSize;
	}


	/**
	 * 
	 */
	public float getFrameLineWidth()
	{
		return this.mFrameLineWidth;
	}


	/**
	 * 
	 */
	public Color getFrameLineColor()
	{
		return this.mFrameLineColor;
	}


	/**
	 * 
	 */
	public Color getBackgroundColor()
	{
		return this.mBackgroundColor;
	}


	/**
	 * 
	 */
	public Color getStringColor()
	{
		return this.mStringColor;
	}


	/**
	 * 
	 */
	private boolean showEditField( ElementGroupSetInLegend legend )
	{

		this.mFocusedGroup = legend;

		final Rectangle2D rect = legend.getRect();
		final float fontSize = this.getMagnification()*this.getFontSize();
		this.mEditField.setFont(
			new Font( this.getFontFamilyName(), this.getFontStyle(), (int)(fontSize) )
		);
		final double x = rect.getX() + this.mMagnification*this.mWidthOfDataElement;
		final double y = rect.getY() + ( rect.getHeight() - fontSize )/2.0;
		this.mEditField.setLocation( (int)x, (int)y );
		final double width = rect.getWidth() - this.getMagnification()*this.mWidthOfDataElement;
		this.mEditField.setSize( (int)(1.1*width), (int)(1.1*fontSize) );
		this.mEditField.setForeground( this.mStringColor );
		this.mEditField.setText( legend.getName() );
		this.mEditField.setVisible(true);
//		this.repaint();

		return true;
	}


	/**
	 * 
	 */
	private Point mLegendLocation = null;


	/**
	 * 
	 */
	private boolean isMoved()
	{
		final boolean bx = ( (int)this.mLegendX == (int)this.mLegendLocation.getX() );
		final boolean by = ( (int)this.mLegendY == (int)this.mLegendLocation.getY() );
		final boolean b = !( bx && by );
		return b;
	}



	/**
	 * 
	 */
	private boolean terminateEditField()
	{
		this.commitEdit();
		this.hideEditField();
		this.clearFocusedGroup();

		return true;
	}



	/**
	 * 
	 * @return
	 */
	private boolean commitEdit()
	{
		String str = this.mEditField.getText();

		// 文字列の長さが0の場合には設定しない
		if( str.length() == 0 )
		{
			return false;
		}

		// 文字列が空白だけの場合にも設定しない
		for( int ii=0; ii<str.length(); ii++ )
		{
			final char c = str.charAt(ii);
			if( c!=' ' && c!='　' )
			{
				break;
			}

			return false;
		}


		String before = this.mFocusedGroup.getName();
		String after = str;
		this.mFocusedGroup.setName( after );

		// draw back
		this.drawBackLegend();

		//
		this.createAllDrawingElements();


		if( before.equals(after) == false )
		{
			this.updateHistory();
		}

		notifyChange();


		return true;
	}



	/**
	 * 
	 */
	private boolean hideEditField()
	{
		this.mEditField.setText("");
		this.mEditField.setVisible(false);
		return true;
	}



	/**
	 * 
	 * @return
	 */
	private boolean clearFocusedGroup()
	{
		this.mFocusedGroup = null;
		return true;
	}






	/**
	 * 
	 */
	private Point mPressedLegendOrigin = null;



	/**
	 * 
	 * @param e
	 */
	public boolean onMousePressed( final MouseEvent e )
	{

		if( !mLegendVisibleFlag )
		{
			return false;
		}


		Rectangle2D lRect = this.getLegendRect();
		if( lRect.contains( e.getX(), e.getY() ) )
		{
			mPressedLegendOrigin = new Point(
				(int)(e.getX()-lRect.getX()),
				(int)(e.getY()-lRect.getY())
			);

			this.mLegendLocation = new Point( (int)this.mLegendX, (int)this.mLegendY );


//System.out.println(this.mPressedLegendOrigin);

			return true;
		}


		if( this.mEditField.isVisible() )
		{
			this.terminateEditField();
		}
		this.clearFocusedGroup();
//		repaint();


		return false;

	}



	/**
	 * 
	 * @param e
	 */
	public boolean onMouseDragged( final MouseEvent e )
	{

		// レジェンドの位置設定
		float x = (float)(e.getX()-mPressedLegendOrigin.x);
		float y = (float)(e.getY()-mPressedLegendOrigin.y);
		this.setLegendLocation(x,y);


		// draw back
//		this.drawBackLegend();

//System.out.println(x+"  "+y);

		this.createAllDrawingElements();
//		repaint();

//System.out.println();

		return true;

	}



	/**
	 * 
	 */
	public boolean onMouseReleased( final MouseEvent e )
	{

//System.out.println("onMouseReleased");


		// draw back
		this.drawBackLegend();


		//
		if( this.isMoved() )
		{
			this.updateHistory();
		}


		//
		mPressedLegendOrigin = null;


//		repaint();

		return true;
	}



	/**
	 * 
	 */
	public boolean chkBoundsVisible()
	{
/*
		if( this.mDataList.size()==0 )
		{
			this.setComponentBoundsVisibleFlag(false);
			return true;
		}

		Rectangle fRect = this.getBounds();
		Rectangle2D lRect = this.getLegendRect();
		boolean flag = !fRect.contains( lRect );
		this.setComponentBoundsVisibleFlag(flag);
*/
		return true;
	}



	/**
	 * レジェンドを外部から引き戻す処理
	 */
	public boolean drawBackLegend()
	{

/*
//System.out.println("draw back legend");

		Rectangle fRect = this.getBounds();
		Rectangle2D lRect = this.getLegendRect();

//System.out.println("fRect:"+fRect);
//System.out.println("lRect:"+lRect);
//System.out.println(lRect.getY()+lRect.getHeight());

//System.out.println(this.mPressedLegendOrigin);


		if( !fRect.contains( lRect ) )
		{
//System.out.println("Not included!");


			// show the bounds of this component
			this.setComponentBoundsVisibleFlag(true);


			final float x = this.mMagnification*this.getLegendX();
			final float y = this.mMagnification*this.getLegendY();
			final float w = this.mMagnification*this.mLegendWidth;
			final float h = this.mMagnification*this.mLegendHeight;

			final float lw = this.mMagnification*this.mFrameLineWidth/2.0f;

			float xx = x;
			float yy = y;
			if( x < 0.0 )
			{
				xx = lw;
			}
			else if( x + w > this.getWidth() )
			{
				xx = this.getWidth() - w - lw;
			}

			if( y < 0.0 )
			{
				yy = lw;
			}
			else if( y + h > this.getHeight() )
			{
				yy = this.getHeight() - h - lw;
			}

			// set the new location
			this.setLegendLocation(xx,yy);

			// create
			this.createAllDrawingElements();

		}
		else
		{
			this.setComponentBoundsVisibleFlag(false);
		}


		this.repaint();
*/

		return true;
	}
	


	/**
	 * 
	 */
	public Rectangle2D getLegendRect()
	{
		Rectangle2D rect = new Rectangle2D.Float(
			this.getLegendX(),
			this.getLegendY(),
			this.mMagnification*this.mLegendWidth,
			this.mMagnification*this.mLegendHeight
		);

		return rect;
	}



	/**
	 * 
	 */
	public boolean isResizable( final double w, final double h )
	{

		Rectangle2D rect = this.getLegendRect();

//System.out.println("  "+w+"  "+rect.getWidth());

		if( w<rect.getWidth() || h<rect.getHeight() )
		{
			return false;
		}
		else
		{
			return true;
		}

	}



	/**
	 * 
	 */
	public void caretUpdate( final CaretEvent e )
	{
		final String str = this.mEditField.getText();

//System.out.println("@"+str+"@");

		final Font font = new Font(
			this.getFontFamilyName(),
			this.getFontStyle(),
			(int)(this.getFontSize()*this.getMagnification()) );
		final Rectangle2D stringRect = font.getStringBounds(
			str, new FontRenderContext( null, false, false ) );

		final double width = stringRect.getWidth();
		if( width > this.mEditField.getWidth() )
		{
			this.mEditField.setSize(
				(int)( stringRect.getWidth() + this.getMagnification()*this.getFontSize() ),
				this.mEditField.getHeight()
			);
		}
	
//		this.repaint();
	}



	/**
	 * 
	 */
	public boolean onKeyPressed( final KeyEvent e )
	{
		return true;
	}


	/**
	 * 
	 */
	public boolean onKeyReleased( final KeyEvent e )
	{
		return true;
	}


	/**
	 * 
	 */
	public boolean onKeyTyped( final KeyEvent e )
	{
		return true;
	}



	/**
	 * 
	 * @param e
	 */
	public boolean onDrawingElement( final int x, final int y )
	{

/*
		for( int ii=0; ii<this.mGroupSetList.size(); ii++ )
		{
			ElementGroupSetInLegend groupSet
				= (ElementGroupSetInLegend)this.mGroupSetList.get(ii);
			boolean flag = groupSet.onGroupSet(x,y);
			if( flag )
			{
				this.mEnteredFlag = true;
				return true;
			}
			else
			{
				this.mEnteredFlag = false;
			}
		}

				repaint();
*/


		return false;
	}



	/**
	 *
	 */
	public boolean setGraphElement( final SGIGraphElement element )
	{
		mGraphElement = element;
		return true;
	}



	/**
	 * 
	 */
	public boolean setLegendVisible( final boolean flag )
	{
		this.mLegendVisibleFlag = flag;
		return true;
	}


	/**
	 * 
	 * @param flag
	 * @return
	 */
	public boolean setLegendTransparent( final boolean flag )
	{
		this.mLegendTransparentFlag = flag;
		return true;
	}


	/**
	 * 
	 */
	public boolean setFrameVisible( final boolean flag )
	{
		this.mFrameVisibleFlag = flag;
		return true;
	}


	/**
	 * 
	 */
	public boolean setFrameLineWidth( final float width )
	{
		this.mFrameLineWidth = width;
		return true;
	}


	/**
	 * 
	 */
	public boolean setFrameLineColor( final Color cl )
	{
		this.mFrameLineColor = cl;
		return true;
	}


	/**
	 * 
	 */
	public boolean setBackgroundColor( final Color cl )
	{
		this.mBackgroundColor = cl;
		return true;
	}


	/**
	 * 
	 */
	public boolean setFontSize( final float size )
	{
		this.mFontSize = size;
		return true;
	}


	/**
	 * 
	 */
	public boolean setFontStyle( final int style )
	{
		this.mFontStyle = style;
		return true;
	}


	/**
	 * 
	 */
	public boolean setStringColor( final Color color )
	{
		this.mStringColor = color;
		return true;
	}


	/**
	 * 
	 */
	public boolean setFontFamilyName( final String name )
	{
		this.mFontFamilyName = name;
		return true;
	}


	/**
	 * 
	 */
	public boolean setWidthOfDataElement( final float width )
	{
		this.mWidthOfDataElement = width;
		return true;
	}


	/**
	 * 
	 */
	private SGData getData( final ElementGroupSetInLegend groupSet )
	{
		for( int ii=0; ii<this.mGroupSetList.size(); ii++ )
		{
			ElementGroupSetInLegend groupSet_
				= (ElementGroupSetInLegend)this.mGroupSetList.get(ii);
			if( groupSet_.equals(groupSet) )
			{
				SGData data = (SGData)this.mDataList.get(ii);			
				return data;
			}
		}

		return null;
	}



	/**
	 * 
	 */
	public boolean isLegendVisible()
	{
		return this.mLegendVisibleFlag;
	}


	/**
	 * 
	 */
	public boolean isFrameLineVisible()
	{
		return this.mFrameVisibleFlag;
	}


	/*:
	 * 
	 */
	public boolean isLegendTransparent()
	{
		return this.mLegendTransparentFlag;
	}



	/**
	 * 
	 */
	public Rectangle2D getRectOfGroup( final SGElementGroup group )
	{
		for( int ii=0; ii<this.mGroupSetList.size(); ii++ )
		{
			ElementGroupSetInLegend leg
				= (ElementGroupSetInLegend)this.mGroupSetList.get(ii);
			ArrayList groupList = leg.mDrawingElementGroupList;
			for( int jj=0; jj<groupList.size(); jj++ )
			{
				SGElementGroup group_ = (SGElementGroup)groupList.get(jj);
				if( group_.equals(group) )
				{
					return leg.mDataRect;
				}
			}

		}

		return null;
	}


	/**
	 * 
	 */
	public Rectangle2D getRectOfGroupSet( final SGElementGroupSet groupSet )
	{
		for( int ii=0; ii<this.mGroupSetList.size(); ii++ )
		{
			ElementGroupSetInLegend leg
				= (ElementGroupSetInLegend)this.mGroupSetList.get(ii);
			if( groupSet.equals(leg) )
			{
				return leg.mDataRect;
			}
		}

		return null;
	}



	/**
	 * 
	 */
	private ElementGroupLine getGroupLine( final ElementGroupSetInLegend groupSet )
	{

		ArrayList groupList = groupSet.mDrawingElementGroupList;
		for( int ii=0; ii<groupList.size(); ii++ )
		{
			SGElementGroup group = (SGElementGroup)groupList.get(ii);
			if( group instanceof ElementGroupLine )
			{
				return (ElementGroupLine)group;
			}
		}

		return null;
	}


	/**
	 * 
	 */
	private ElementGroupBar getGroupBar( final ElementGroupSetInLegend groupSet )
	{

		ArrayList groupList = groupSet.mDrawingElementGroupList;
		for( int ii=0; ii<groupList.size(); ii++ )
		{
			SGElementGroup group = (SGElementGroup)groupList.get(ii);
			if( group instanceof ElementGroupBar )
			{
				return (ElementGroupBar)group;
			}
		}

		return null;
	}


	/**
	 * 
	 */
	private ElementGroupSymbol getGroupSymbol( final ElementGroupSetInLegend groupSet )
	{

		ArrayList groupList = groupSet.mDrawingElementGroupList;
		for( int ii=0; ii<groupList.size(); ii++ )
		{
			SGElementGroup group = (SGElementGroup)groupList.get(ii);
			if( group instanceof ElementGroupSymbol )
			{
				return (ElementGroupSymbol)group;
			}
		}

		return null;
	}


	/**
	 * 
	 */
	public void actionPerformed( final ActionEvent e)
	{
		String command = e.getActionCommand();
		Object source = e.getSource();

//System.out.println(e);

		if( source.equals( this.mEditField ) )
		{
			this.terminateEditField();
			return;
		}


		if( command.equals("OK")
		|| this.mDialog.getActiveComponentList().contains(source) )
		{
			if( this.onOK() == false ) return;
		}
		else if( command.equals("Cancel") )
		{
			if( this.onCanceled() == false ) return;
		}
		else if( command.equals("Preview") )
		{
			if( this.onPreviewed() == false ) return;
		}


	}



	/**
	 * 
	 */
	private boolean onOK()
	{

		boolean flag;

		// ダイアログからプロパティを取得して設定
		flag = this.setPropertyWithDialog();
		if( !flag )
		{
			return false;
		}


		// ダイアログを出す前後でプロパティが変更されている場合のみ、
		// 履歴を更新する

		SGProperties pTemp = this.mTemporaryProperties;
		SGProperties pPresent = this.getProperties();
		if( pTemp.equals(pPresent) == false )
		{
			// オブジェクト履歴を更新
			this.updateHistory();
		}

		this.mTemporaryProperties = null;
		this.mDialog.hide();

		this.createAllDrawingElements();
		notifyChange();
//		repaint();


		return true;
	}




	/**
	 * 
	 * @return
	 */
	public boolean addPropertiesHistory( SGProperties p )
	{

		if( ( p instanceof LegendProperties ) == false )
		{
			return false;
		}

		super.addPropertiesHistory(p);

		return true;
	}


	/**
	 * 
	 */
	private boolean onCanceled()
	{
		boolean flag = this.recover();
		if( !flag ) return false;

		this.mTemporaryProperties = null;
		this.mDialog.hide();

		this.createAllDrawingElements();
		notifyChange();
//		repaint();

		return true;
	}


	/**
	 * 
	 */
	private boolean onPreviewed()
	{
		boolean flag = this.setPropertyWithDialog();
		if( !flag ) return false;

		this.createAllDrawingElements();
		notifyChange();
//		repaint();

		return true;
	}



	/**
	 * 
	 */
	public void windowActivated(final WindowEvent e)
	{
//System.out.println("windowActivated");
	}


	/**
	 * 
	 */
	public void windowDeactivated(final WindowEvent e)
	{
//System.out.println("windowDeactivated");
	}


	/**
	 * 
	 */
	public void windowIconified(final WindowEvent e)
	{
//System.out.println("windowIconified");
	}


	/**
	 * 
	 */
	public void windowDeiconified(final WindowEvent e)
	{
//System.out.println("windowDeiconified");
	}


	/**
	 * 
	 */
	public void windowOpened(final WindowEvent e)
	{
//System.out.println("windowOpened");
	}


	/**
	 * 
	 */
	public void windowClosed(final WindowEvent e)
	{
//System.out.println("windowClosed");
	}


	/**
	 * 
	 */
	public void windowClosing(final WindowEvent e)
	{
//System.out.println("windowClosing");

		Object obj = e.getSource();
//System.out.println(obj);
		if( obj.equals( this.mDialog ) )
		{
			this.onCanceled();
		}

	}



	/**
	 * 
	 */
	public boolean undo()
	{
		boolean flag = super.undo();
		if( !flag )
		{
			return false;
		}

		this.createAllDrawingElements();
		this.notifyChange();

//		repaint();

		return true;
	}




	/**
	 * 
	 */
	public boolean redo()
	{
		boolean flag = super.redo();
		if( !flag )
		{
			return false;
		}

		this.createAllDrawingElements();
		this.notifyChange();

//		repaint();

		return true;
	}




	/**
	 * 
	 */
	public boolean recover()
	{
		if( this.setProperties( this.mTemporaryProperties ) == false )
		{
			return false;
		}

		return true;
	}


	/**
	 * 
	 */
	protected SGElementGroupSet getElementGroupSet( SGData data )
	{

		for( int ii=0; ii<this.mDataList.size(); ii++ )
		{
			SGData data_ = (SGData)this.mDataList.get(ii);
			if( data_.equals(data) )
			{
				SGElementGroupSet groupSet = (SGElementGroupSet)this.mGroupSetList.get(ii);
				return groupSet;
			}
		}

		return null;

	}



	/**
	 * 
	 */
	protected SGData getData( SGElementGroupSet groupSet )
	{

		for( int ii=0; ii<this.mGroupSetList.size(); ii++ )
		{
			SGElementGroupSet groupSet_ = (SGElementGroupSet)this.mGroupSetList.get(ii);
			if( groupSet_.equals(groupSet) )
			{
				SGData data = (SGData)this.mDataList.get(ii);
				return data;
			}
		}

		return null;
	}



	/**
	 * 
	 */
	public boolean createDataObject( final BufferedReader reader, final SGData data )
		throws IOException
	{


		super.createDataObject( reader, data );


		//
		// レジェンドの要素を新規作成
		//

		ElementGroupSetInLegend legend = this.createLegendElement( data );
//System.out.println(legend);
		if( legend == null )
		{
			return false;
		}



		// LegendDataをリストに追加
		this.mGroupSetList.add( legend );


		// 描画要素の作成
		this.createAllDrawingElements();


		return true;
	}






	/**
	 * 
	 */
	public boolean writeProperty( final Writer writer ) throws IOException
	{
		writer.write( PF_LEGEND_TITLE + "\n" );

//		SGUtilityForPropertyFile.writePropertyLine( writer, PF_CLASS_NAME, this.getClass().getName() );

		SGUtilityText.writePropertyLine( writer, PF_LEGEND_VISIBLE, new Boolean( this.mLegendVisibleFlag ) );

		SGUtilityText.writePropertyLine( writer, PF_LEGEND_X, new Float( this.mLegendX*SGConstants.CM_POINT_RATIO ) );
		SGUtilityText.writePropertyLine( writer, PF_LEGEND_Y, new Float( this.mLegendY*SGConstants.CM_POINT_RATIO ) );

		SGUtilityText.writePropertyLine( writer, PF_LEGEND_FRAME_VISIBLE, new Boolean( this.mFrameVisibleFlag ) );
		SGUtilityText.writePropertyLine( writer, PF_LEGEND_FRAME_LINE_WIDTH, new Float( this.mFrameLineWidth ) );
		SGUtilityText.writeColorPropertyLine( writer, PF_LEGEND_FRAME_LINE_COLOR, this.mFrameLineColor );
		SGUtilityText.writeColorPropertyLine( writer, PF_LEGEND_BACKGROUND_COLOR, this.mBackgroundColor );
		SGUtilityText.writePropertyLine( writer, PF_LEGEND_BACKGROUND_TRANSPARENT, new Boolean( this.mLegendTransparentFlag ) );

		SGUtilityText.writePropertyLine( writer, PF_FONT_FAMILY_NAME, this.mFontFamilyName );
		SGUtilityText.writePropertyLine( writer, PF_FONT_SIZE, new Float( this.mFontSize ) );
		SGUtilityText.writePropertyLine( writer, PF_FONT_STYLE, SGUtilityText.getFontStyleName( this.mFontStyle ) );
		SGUtilityText.writeColorPropertyLine( writer, PF_STRING_COLOR, this.mStringColor );

//		SGUtilityForPropertyFile.writePropertyLine( writer, PF_WIDTH_DATA_ELEMENT, new Float( this.mWidthOfDataElement*this.mRulerUnit ) );

		writer.write("\n\n");


		return true;
	}




	/**
	 * 
	 */
	public boolean readProperty( final BufferedReader br ) throws IOException
	{
		LegendProperties wp = this.readProperties(br);
		if( wp==null ) return false;
		
		if( this.setProperties(wp) == false ) return false;

		return true;

	}



	/**
	 * 
	 */
	private LegendProperties readProperties( final BufferedReader br ) throws IOException
	{

		String line = null;


		// set legend visible
		if( ( line = SGUtilityText.readLine(br) ) == null )
		{
			return null;
		}
		Boolean bLegendVisible = SGUtilityText.getBooleanPropertyFromLine(line,SGLegendElement.PF_LEGEND_VISIBLE);
		if( bLegendVisible == null )
		{
			return null;
		}
		boolean legendVisible = bLegendVisible.booleanValue();


		// set the location of SGLegendElement
		if( ( line = SGUtilityText.readLine(br) ) == null )
		{
			return null;
		}
		Double dX = SGUtilityText.getDoublePropertyFromLine(line,SGLegendElement.PF_LEGEND_X);
		if( dX == null )
		{
			return null;
		}
		float x = dX.floatValue()/SGConstants.CM_POINT_RATIO;


		if( ( line = SGUtilityText.readLine(br) ) == null )
		{
			return null;
		}
		Double dY = SGUtilityText.getDoublePropertyFromLine(line,SGLegendElement.PF_LEGEND_Y);
		if( dY == null )
		{
			return null;
		}
		float y = dY.floatValue()/SGConstants.CM_POINT_RATIO;


		// set frame visible
		if( ( line = SGUtilityText.readLine(br) ) == null )
		{
			return null;
		}
		Boolean bFrameVisible = SGUtilityText.getBooleanPropertyFromLine(line,SGLegendElement.PF_LEGEND_FRAME_VISIBLE);
		if( bFrameVisible == null )
		{
			return null;
		}
		boolean frameVisible = bFrameVisible.booleanValue();


		// set frame line width
		if( ( line = SGUtilityText.readLine(br) ) == null )
		{
			return null;
		}
		Double dFrameLineWidth = SGUtilityText.getDoublePropertyFromLine(line,SGLegendElement.PF_LEGEND_FRAME_LINE_WIDTH);
		if( dFrameLineWidth == null )
		{
			return null;
		}
		float frameLineWidth = dFrameLineWidth.floatValue();


		// set frame line color
		if( ( line = SGUtilityText.readLine(br) ) == null )
		{
			return null;
		}
		Color frameLineColor = SGUtilityText.getColorPropertyFromLine(line,SGLegendElement.PF_LEGEND_FRAME_LINE_COLOR);
		if( frameLineColor == null )
		{
			return null;
		}


		// background color
		if( ( line = SGUtilityText.readLine(br) ) == null )
		{
			return null;
		}
		Color innerColor = SGUtilityText.getColorPropertyFromLine(line,SGLegendElement.PF_LEGEND_BACKGROUND_COLOR);
		if( innerColor == null )
		{
			return null;
		}

		// set frame visible
		if( ( line = SGUtilityText.readLine(br) ) == null )
		{
			return null;
		}
		Boolean bTransparent = SGUtilityText.getBooleanPropertyFromLine(line,SGLegendElement.PF_LEGEND_BACKGROUND_TRANSPARENT);
		if( bTransparent == null )
		{
			return null;
		}
		boolean transparent = bTransparent.booleanValue();


		// set font family name
		if( ( line = SGUtilityText.readLine(br) ) == null )
		{
			return null;
		}
		String fontFamilyName = SGUtilityText.getPropertyFromLine(line,SGLegendElement.PF_FONT_FAMILY_NAME);
		if( fontFamilyName == null )
		{
			return null;
		}


		// set font size
		if( ( line = SGUtilityText.readLine(br) ) == null )
		{
			return null;
		}
		Double dFontSize = SGUtilityText.getDoublePropertyFromLine(line,SGLegendElement.PF_FONT_SIZE);
		if( dFontSize == null )
		{
			return null;
		}
		float fontSize = dFontSize.floatValue();


		// set font style
		if( ( line = SGUtilityText.readLine(br) ) == null )
		{
			return null;
		}
		Integer nFontStyle = SGUtilityText.getFontStyleFromLine(line,SGLegendElement.PF_FONT_STYLE);
		if( nFontStyle == null )
		{
			return null;
		}
		int fontStyle = nFontStyle.intValue();


		// set the string color
		if( ( line = SGUtilityText.readLine(br) ) == null )
		{
			return null;
		}
		Color strColor = SGUtilityText.getColorPropertyFromLine(line,SGLegendElement.PF_STRING_COLOR);
		if( strColor == null )
		{
			return null;
		}


		LegendCommonProperties cp = new LegendCommonProperties();
		cp.visible = legendVisible;
		cp.x = x;
		cp.y = y;
		cp.frameLineVisible = frameVisible;
		cp.frameLineWidth = frameLineWidth;
		cp.frameLineColor = frameLineColor;
		cp.backgroundColor = innerColor;
		cp.transparent = transparent;
		cp.fontFamilyName = fontFamilyName;
		cp.fontSize = fontSize;
		cp.fontStyle = fontStyle;
		cp.stringColor = strColor;

/*
		ArrayList dpList = new ArrayList();
		for( int ii=0; ii<this.mGroupSetList.size(); ii++ )
		{
			ElementGroupSetInLegend groupSet
				= (ElementGroupSetInLegend)this.mGroupSetList.get(ii);
			SGProperties p = groupSet.getProperties();
			dpList.add(p);
		}
*/

		TreeMap map = this.getDataPropertiesMap();

		LegendProperties wp = new LegendProperties();
		wp.cp = cp;
		wp.dpMap = map;

		return wp;
	}






	/**
	 * 
	 */
	interface ILegendElement
	{
		/**
		 * 
		 * @return
		 */
		public float getDataElementWidth();

		/**
		 * 
		 * @return
		 */
		public float getDataElementHeight();

		/**
		 * 
		 * @return
		 */
		public boolean createDrawingElementInLegend();

		/**
		 * 
		 * @return
		 */
		public int getNumberOfPoints();

	}



	/**
	 * 一つのデータに対応したレジェンド
	 */
	class ElementGroupSetInLegend
		extends SGElementGroupSetInFigureElement implements ActionListener
	{


		/**
		 * 
		 */
		protected final String SET_FONT_SIZE = "Set font size";


		/**
		 * 
		 */
		private final String SET_FONT_STYLE = "Set font style";


		/**
		 * 
		 */
		protected final String SET_FONT_FAMILY_NAME = "Set font family name";


		/**
		 * 
		 */
		protected final String SET_STRING_COLOR = "Set the color of string";


		/**
		 * 一つのデータに対する矩形
		 */
		protected Rectangle2D mDataRect = null;


		/**
		 * 実際に描画するデータ名の文字列描画要素
		 */		
		protected SGDrawingElementString2DExtended mDrawingString = null;



		/**
		 * 
		 */
		protected JPopupMenu mPopupMenu = new JPopupMenu();


		/**
		 * 
		 */
		protected ElementGroupSetInLegend()
		{
			this.createPopupMenu();
		}



		/**
		 * 
		 * @return
		 */
		public void setVisible( boolean b )
		{
			this.mVisibleFlag = b;
		}


		/**
		 * 
		 */
		public boolean isVisible()
		{
			return this.mVisibleFlag;
		}




		/**
		 * データ名の文字列描画要素を作成
		 */
		private boolean createDrawingString()
		{
			String name = this.mName + " ";
			mDrawingString = new SGDrawingElementString2DExtended(
				name, mFontFamilyName, mFontStyle, mFontSize );
			mDrawingString.setColor( mStringColor );
			mDrawingString.setMagnification( mMagnification );

			return true;
		}


		/**
		 * 
		 * @return
		 */
		private boolean paintString( final Graphics2D g2d )
		{
			this.mDrawingString.drawString(g2d);
			return true;
		}


		/**
		 * 
		 * @return
		 */
		private Rectangle2D getDrawingStringBounds()
		{
			Rectangle2D rect = mDrawingString.getElementBounds();
			return rect;
		}


		/**
		 * 
		 * @return
		 */
		private Rectangle2D getRect()
		{
			if( mDataRect == null )
			{
				return null;
			}

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

			return new Rectangle2D.Float(x,y,w,h);
		}


		/**
		 * 
		 */
		public float getMaxDataElementWidth()
		{
			float max = 0.0f;
			for( int ii=0; ii<this.mDrawingElementGroupList.size(); ii++ )
			{
				ILegendElement el = (ILegendElement)this.mDrawingElementGroupList.get(ii);
				float width = el.getDataElementWidth();
				if( width > max )
				{
					max = width;
				}
			}

			return max;
		}


		/**
		 * 
		 */
		public double getMaxDataElementHeight()
		{
			double max = 0.0;
			for( int ii=0; ii<this.mDrawingElementGroupList.size(); ii++ )
			{
				ILegendElement el = (ILegendElement)this.mDrawingElementGroupList.get(ii);
				double height = el.getDataElementHeight();
				if( height > max )
				{
					max = height;
				}
			}

			return max;
		}


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


		/**
		 * 
		 * @return
		 */
		private boolean createDrawingElement()
		{
			for( int ii=0; ii<this.mDrawingElementGroupList.size(); ii++ )
			{
				ILegendElement el = (ILegendElement)this.mDrawingElementGroupList.get(ii);
				el.createDrawingElementInLegend();
			}

			return true;
		}


		/**
		 * 
		 */
		public void paintGraphics2D( final Graphics2D g2d )
		{
			
			// draw the name of data
			g2d.setPaint( mStringColor );
			this.paintString(g2d);
	
			// bar
			ElementGroupBar groupBar = getGroupBar( this );
			if( groupBar!=null )
			{
				if( groupBar.isVisible() )
				{
					groupBar.paintElement(g2d);
				}
			}
	
			// line
			ElementGroupLine groupLine = getGroupLine( this );
			if( groupLine!=null )
			{
				if( groupLine.isVisible() )
				{
					groupLine.paintElement(g2d);
				}
			}
	
			// symbol
			ElementGroupSymbol groupSymbol = getGroupSymbol( this );
			if( groupSymbol!=null )
			{
				if( groupSymbol.isVisible() )
				{
					groupSymbol.paintElement(g2d);
				}
			}

		}


		/**
		 * 
		 */
		protected boolean clickDrawingElements( final MouseEvent e )
		{
			return false;
		}


		/**
		 * 
		 * @return
		 */
		protected boolean createPopupMenu()
		{
			mPopupMenu.setBounds( 0, 0, 100, 100 );

			String[] commandArray = {
				SHOW_LEGEND,
				DRAW_FRAME
			};
	
			for( int ii=0; ii<commandArray.length; ii++ )
			{
				JMenuItem item = new JMenuItem(commandArray[ii]);
				item.addActionListener(this);
				this.mPopupMenu.add(item);
			}

			return true;
		}


		/**
		 * 
		 */
		private JPopupMenu getPopupMenu()
		{
			return mPopupMenu;
		}


		/**
		 * 
		 */
		public boolean addDrawingElementGroup( final int type )
		{

			SGElementGroup group = null;
			if( type == SGElementGroup.POLYLINE_GROUP )
			{
				group = new ElementGroupLine();
//System.out.println("line");
			}
			else if( type == SGElementGroup.RECTANGLE_GROUP )
			{
				group = new ElementGroupBar();
//System.out.println("rectangle");

			}
			else if( type == SGElementGroup.SYMBOL_GROUP )
			{
				group = new ElementGroupSymbol();
//System.out.println("symbol");
			}
			else if( type == SGElementGroup.ARROW_GROUP )
			{
				group = new ElementGroupArrow();
			}
			else
			{
				throw new Error("");
			}

/*
			// 既に存在する場合には追加しない
			Class cl = group.getClass();
			for( int ii=0; ii<this.mDrawingElementGroupList.size(); ii++ )
			{
				SGElementGroup group_
					= (SGElementGroup)this.mDrawingElementGroupList.get(ii);
				Class cl_ = group_.getClass();
				if( cl.equals(cl_) )
				{
					System.out.println("既に存在します！");
					return false;
				}
			}
*/

//			group.setMagnification(this.mMagnification);

			this.addDrawingElementGroup( group );


			// 描画要素の作成
//			createAllDrawingElements();


			return true;
		}


		/**
		 * 
		 */
		public boolean addDrawingElementGroup( final SGDrawingElement element )
		{

			SGElementGroup group = null;
			if( element instanceof SGDrawingElementLine )
			{
				group = new ElementGroupLine();
			}
			else if( element instanceof SGDrawingElementBar )
			{
				group = new ElementGroupBar();
//System.out.println("rectangle");

			}
			else if( element instanceof SGDrawingElementSymbol )
			{
				group = new ElementGroupSymbol();
//System.out.println("symbol");
			}
			else if( element instanceof SGDrawingElementArrow )
			{
				group = new ElementGroupArrow();
			}
			else
			{
				throw new Error("");
			}

/*
			// 既に存在する場合には追加しない
			Class cl = group.getClass();
			for( int ii=0; ii<this.mDrawingElementGroupList.size(); ii++ )
			{
				SGElementGroup group_
					= (SGElementGroup)this.mDrawingElementGroupList.get(ii);
				Class cl_ = group_.getClass();
				if( cl.equals(cl_) )
				{
					System.out.println("既に存在します！");
					return false;
				}
			}
*/

			group.setProperty( element );
			group.setMagnification(this.mMagnification);

			this.addDrawingElementGroup( group );


			// 描画要素の作成
			createAllDrawingElements();


			return true;
		}


		/**
		 * 
		 */
		private SGTuple2f[] mPointsArray = null;



		/**
		 * 
		 */
		private boolean addDrawingElementGroup( final SGElementGroup group )
		{

			group.mGroupSet = this;


			ILegendElement lElement = (ILegendElement)group;


			// 描画要素の作成
			group.initDrawingElement( lElement.getNumberOfPoints() );


			// set the properties to drawing elements
			if( group.setPropertiesOfDrawingElements() == false )
			{
				return false;
			}


			// 倍率
			group.setMagnification( mMagnification );


			// グループをデータのリストに追加
			this.mDrawingElementGroupList.add( group );


			return true;
		}



		/**
		 * 
		 */
		public boolean writePropertyOfData( final Writer writer ) throws IOException
		{
			return true;
		}
		
		
		
		/**
		 * 
		 */
		public void actionPerformed(final ActionEvent e)
		{
			String command = e.getActionCommand();
			Object source = e.getSource();

/*
			// dialog
			if( command.equals(CHANGE_DATA_NAME) )
			{
				this.mName = this.mDataNameField.getText();
				createAllDrawingElements();
			}
			else if( command.equals(CHANGE_FONT_SIZE) )
			{
				String str = this.mFontSizeField.getText();
				mFontSize = (Double.valueOf(str)).doubleValue()/100.0;
				createAllDrawingElements();
			}

			// popup			
			if( command.equals(SHOW_LEGEND) )
			{
				mShowLegendFlag = !mShowLegendFlag;
			}
			else if( command.equals(DRAW_FRAME) )
			{
				mDrawFrameFlag = !mDrawFrameFlag;
			}

			if( e.getSource() == mFontFamilyNameBox )
			{
				mFontFamilyName = (String)this.mFontFamilyNameBox.getSelectedItem();
				this.mDrawingString.setFontFamilyName( mFontFamilyName );
				createAllDrawingElements();
			}
*/


			//
			// for the properties of group
			//
/*
			ArrayList comList = this.getActiveDialogComponents();

			if( command.equals("OK") || comList.contains(source) )
			{
				this.setPropertyWithDialog();
				this.mDialog.hide();
			}
			else if( command.equals("Cancel") )
			{
				recover();
				this.mDialog.hide();
			}
			else if( command.equals("Preview") )
			{
				this.setPropertyWithDialog();
			}
*/

			createAllDrawingElements();
			notifyChange();
//			repaint();

		}



		/**
		 * 
		 */
		public boolean setProperties( final SGProperties p )
		{
			ElementGroupSetProperties pp = (ElementGroupSetProperties)p;
			pp.visible = this.isVisible();

			if( super.setProperties(pp) == false ) return false;

			return true;
		}



	}



	/**
	 * 
	 */
	class ElementGroupSetInLegendSXY extends ElementGroupSetInLegend
	{

		/**
		 * 
		 */
		protected SGPropertyDialogSXYData mDialog = null;


		/**
		 * 
		 */
		protected ElementGroupSetInLegendSXY()
		{
			super();
		}


	}



	/**
	 * 
	 */
	class ElementGroupSetInLegendVXY extends ElementGroupSetInLegend
	{

		/**
		 * 
		 */
		protected SGPropertyDialogVXYData mDialog = null;


		/**
		 * 
		 */
		protected ElementGroupSetInLegendVXY()
		{
			super();
		}
		
	}



	/**
	 * 
	 */
	class ElementGroupLine extends SGElementGroupLine
		implements ILegendElement
	{

		/**
		 *
		 */
		protected ElementGroupLine()
		{
			super();
			if( this.init() == false )
			{
				throw new Error();
			}
		}


		/**
		 * 
		 */
		private boolean init()
		{
			this.setVisible( SGDefaultValues.LINE_VISIBLE );
			this.setLineWidth( SGDefaultValues.LINE_WIDTH );
			final Integer n = SGDrawingElementLine.getLineTypeFromName( SGDefaultValues.LINE_TYPE );
			if( n==null )
			{
				return false;
			}
			this.setLineType( n.intValue() );
			this.setColor( SGDefaultValues.LINE_COLOR );

			return true;
		}


		/**
		 * 
		 */
		public float getDataElementWidth()
		{
			return this.mMagnification*mWidthOfDataElement;
		}


		/**
		 * 
		 */
		public float getDataElementHeight()
		{
			return 1.5f*mMagnification*mLineWidth;
		}


		/**
		 * 
		 * @return
		 */
		public int getNumberOfPoints()
		{
			return 2;
		}

	
		/**
		 * 描画要素の作成
		 */
		public boolean createDrawingElementInLegend()
		{

			Rectangle2D lRect = getRectOfGroupSet(this.mGroupSet);

			SGTuple2f start = new SGTuple2f();
			start.x = (float)lRect.getX() + 0.10f*this.getDataElementWidth();
			start.y = (float)lRect.getY() + 0.50f*(float)lRect.getHeight();
			SGTuple2f end = new SGTuple2f();
			end.x = start.x + 0.80f*this.mMagnification*mWidthOfDataElement;
			end.y = start.y;


			SGTuple2f[] array = new SGTuple2f[2];
			array[0] = start;
			array[1] = end;


			this.setLocation( array );

			return true;
		}


	}



	/**
	 * 
	 */
	class ElementGroupBar extends SGElementGroupBar
		implements ILegendElement
	{

		/**
		 *
		 */
		protected ElementGroupBar()
		{
			super();
			if( this.init() == false )
			{
				throw new Error();
			}
		}


		/**
		 * 
		 */
		private boolean init()
		{
			this.setVisible( SGDefaultValues.BAR_VISIBLE );
			this.setBaseLineValue( SGDefaultValues.BAR_BASELINE_VALUE );
			this.setRectangleWidth( SGDefaultValues.BAR_WIDTH );
			this.setColor( SGDefaultValues.BAR_COLOR );
			this.setEdgeLineWidth( SGDefaultValues.BAR_LINE_WIDTH );
			this.setEdgeLineColor( SGDefaultValues.BAR_LINE_COLOR );

			return true;
		}


		/**
		 * 
		 */
		public float getDataElementWidth()
		{
			return this.mMagnification*mWidthOfDataElement;
		}


		/**
		 * 
		 */
		public float getDataElementHeight()
		{
			return 1.5f*mRectangleWidth*this.mMagnification;
		}


		/**
		 * 
		 * @return
		 */
		public int getNumberOfPoints()
		{
			return 1;
		}


		/**
		 * 
		 */
		public boolean createDrawingElementInLegend()
		{

			Rectangle2D lRect = getRectOfGroupSet(this.mGroupSet);

			final float barWidth = this.mMagnification*mRectangleWidth;

			SGTuple2f start = new SGTuple2f();
			start.x = (float)lRect.getX() + 0.20f*this.getDataElementWidth();
			start.y = (float)lRect.getY() + 0.50f*(float)lRect.getHeight() - 0.50f*barWidth;

			SGTuple2f[] array = new SGTuple2f[1];
			array[0] = start;
			this.setLocation(array);			

			return true;
		}



		/**
		 * 
		 */
		public boolean setLocation(
			final SGTuple2f[] pointArray )
		{

			if( this.mDrawingElementArray==null )
			{
				return true;
			}

			if( pointArray.length != this.mDrawingElementArray.length )
			{
				throw new IllegalArgumentException();
			}

			// 棒グラフの描画要素を作成
			for( int ii=0; ii<this.mDrawingElementArray.length; ii++ )
			{
				SGDrawingElementBar2D bar
					= (SGDrawingElementBar2D)this.mDrawingElementArray[ii];
				SGTuple2f point = pointArray[ii];
				bar.setBounds(
					point.x, point.y,
					0.60f*this.getDataElementWidth(),
					this.mMagnification*this.mRectangleWidth
				);
			}
//			if( this.setPropertiesOfDrawingElements() == false )
//			{
//				return false;
//			}

			return true;
		}


	}



	/**
	 * 
	 */
	class ElementGroupSymbol extends SGElementGroupSymbol
		implements ILegendElement
	{

		/**
		 *
		 */
		protected ElementGroupSymbol()
		{
			super();
			if( this.init() == false )
			{
				throw new Error();
			}
		}


		/**
		 * 
		 */
		private boolean init()
		{
			this.setVisible( SGDefaultValues.SYMBOL_VISIBLE );
			Integer n = SGDrawingElementSymbol.getSymbolTypeFromName( SGDefaultValues.SYMBOL_TYPE );
			if( n==null )
			{
				return false;
			}
			this.setType( n.intValue() );
			this.setSize( SGDefaultValues.SYMBOL_SIZE );
			this.setColor( SGDefaultValues.SYMBOL_BODY_COLOR );
			this.setLineWidth( SGDefaultValues.SYMBOL_LINE_WIDTH );
			this.setLineColor( SGDefaultValues.SYMBOL_LINE_COLOR );

			return true;
		}


		/**
		 * 
		 */
		public float getDataElementWidth()
		{
			final float w = this.mMagnification*mWidthOfDataElement;
			final float s = getDataElementSize();
			if( w<s )
			{
				return s;
			}
			else
			{
				return w;
			}
		}


		/**
		 * 
		 */
		public float getDataElementHeight()
		{
			return 1.5f*getDataElementSize();
		}


		/**
		 * 
		 */
		private float getDataElementSize()
		{
			if( this.mDrawingElementArray!=null )
			{
				if( this.mDrawingElementArray.length == 0 )
				{
					return 0.0f;
				}

				SGDrawingElementSymbol2D symbol
					= (SGDrawingElementSymbol2D)this.mDrawingElementArray[0];
				Rectangle2D rect = symbol.getElementBounds().getBounds2D();
				return (float)rect.getHeight();
			}
			else
			{
				return 0.0f;
			}
		}


		/**
		 * 
		 * @return
		 */
		public int getNumberOfPoints()
		{
			return 1;
		}


		/**
		 * 
		 */
		public boolean createDrawingElementInLegend()
		{

			Rectangle2D lRect = getRectOfGroupSet(this.mGroupSet);

			SGTuple2f position = new SGTuple2f();
			position.x = (float)lRect.getX() + 0.50f*this.mMagnification*mWidthOfDataElement;
			position.y = (float)lRect.getY() + 0.50f*(float)lRect.getHeight();

			SGTuple2f[] array = new SGTuple2f[1];
			array[0] = position;
			this.setLocation(array);

			return true;

		}


	}




	/**
	 * 
	 */
	class ElementGroupArrow extends SGElementGroupArrow
		implements ILegendElement
	{

		/**
		 * 
		 */
		protected ElementGroupArrow()
		{
			super();
		}


		/**
		 * 
		 */
		public float getDataElementWidth()
		{
			return this.mMagnification*mWidthOfDataElement;
		}


		/**
		 * 
		 */
		public float getDataElementHeight()
		{
			return 0.0f;
		}


		/**
		 * 
		 * @return
		 */
		public int getNumberOfPoints()
		{
			return 1;
		}


		/**
		 * 
		 */
		public boolean createDrawingElementInLegend()
		{
			Rectangle2D lRect = getRectOfGroupSet(this.mGroupSet);

			SGTuple2f start = new SGTuple2f();
			start.x = (float)lRect.getX() + 0.10f*this.mMagnification*mWidthOfDataElement;
			start.y = (float)lRect.getY() + 0.50f*(float)lRect.getHeight();
			SGTuple2f end = new SGTuple2f();
			end.x = start.x + 0.80f*this.mMagnification*mWidthOfDataElement;
			end.y = start.y;


			SGTuple2f[] startArray = new SGTuple2f[1];
			startArray[0] = start;
			SGTuple2f[] endArray = new SGTuple2f[1];
			endArray[0] = end;
			if( this.setLocation( startArray, endArray ) == false )
			{
				return false;
			}

			return true;
		}



		/**
		 * 
		 */
		Rectangle2D getDataElementBounds()
		{
			Rectangle2D rect = new Rectangle2D.Double();
//
//
//
			return rect;
		}



	}





	/**
	 * 
	 */
	public static class LegendCommonProperties extends SGProperties
	{

		float x;
		float y;
		boolean visible;
		boolean frameLineVisible;
		float frameLineWidth;
		Color frameLineColor;
		String fontFamilyName;
		float fontSize;
		int fontStyle;
		Color stringColor;
		Color backgroundColor;
		boolean transparent;


		/**
		 * 
		 */
		public boolean equals( final Object obj )
		{

			if( ( obj instanceof LegendCommonProperties ) == false ) return false;

			LegendCommonProperties p = (LegendCommonProperties)obj;

			if( p.x != this.x ) return false;
			if( p.y != this.y ) return false;
			if( p.visible != this.visible ) return false;
			if( p.frameLineVisible != this.frameLineVisible ) return false;
			if( p.frameLineWidth != this.frameLineWidth ) return false;
			if( p.frameLineColor.equals(this.frameLineColor) == false ) return false;
			if( p.fontFamilyName.equals(this.fontFamilyName) == false ) return false;
			if( p.fontSize != this.fontSize ) return false;
			if( p.fontStyle != this.fontStyle ) return false;
			if( p.stringColor.equals(this.stringColor) == false ) return false;
			if( p.backgroundColor.equals( this.backgroundColor ) == false ) return false;
			if( p.transparent != this.transparent ) return false;

			return true;
		}


		/**
		 * 
		 */
		public String toString()
		{
			String str = new String("[");
			str += new String("x="+x+", ");
			str += new String("y="+y+", ");
			str += new String("visible="+visible+", ");
			str += new String("frameLineVisible="+frameLineVisible+", ");
			str += new String("frameLineWidth="+frameLineWidth+", ");
			str += new String("frameLineColor="+frameLineColor+", ");
			str += new String("fontFamilyName="+fontFamilyName+", ");
			str += new String("fontSize="+fontSize+", ");
			str += new String("fontStyle="+fontStyle+", ");
			str += new String("stringColor="+stringColor+", ");
			str += new String("innerColor="+backgroundColor+", ");
			str += new String("transparent="+transparent+", ");
			str += new String("]");

			return str;
		}



	}



	/**
	 * 
	 */
	public static class LegendProperties extends SGProperties
	{

		LegendCommonProperties cp;
//		ArrayList dpList = new ArrayList();

TreeMap dpMap = new TreeMap();


		/**
		 * 
		 */
		public boolean equals( final Object obj )
		{
			if( ( obj instanceof LegendProperties ) == false ) return false;

			LegendProperties wp = (LegendProperties)obj;
			if( (wp.cp).equals(this.cp) == false ) return false;
//			if( (wp.dpList).equals(this.dpList) == false ) return false;
if( (wp.dpMap).equals(this.dpMap) == false ) return false;

			return true;
		}

		/**
		 * 
		 */
		public String toString()
		{
			String str = new String("[");
			str += cp.toString();
			str += dpMap.toString();
			str += new String("]");

			return str;
		}


		
	}


}

