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

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



/**
 * xy型データのグラフのクラス
 */
public class SGSXYGraphElement extends SGGraphElement
{

	/**
	 * 
	 */
	public static final String PF_ERROR_BAR_EMPTY = "<Error Bars Empty>";
	public static final String PF_TICK_LABELS_EMPTY = "<Tick Labels Empty>";



	/**
	 * 
	 */
	public static final String MSG_NOT_HIDE_ALL_ELEMENTS
		= "全部は消せません。";



	/**
	 * コンストラクタ
	 */
	public SGSXYGraphElement()
	{
		super();
		this.createDataDialog();
	}



	/**
	 * プロパティダイアログの作成
	 */
	protected boolean createDataDialog()
	{

		final SGPropertyDialogSXYData dg
		 = new SGPropertyDialogSXYData( mDialogOwner, true );

		mPropertyDialogForData = dg;

		return true;
	}



	/**
	 *
	 */
	public boolean addData( final SGData data )
	{
//System.out.println("addData:SGSXYGraphElement");

		// データのチェック
		if( !(data instanceof SGSXYData) && !(data instanceof SGSXYMultipleData) )
		{
			return false;
		}


		// リストに追加
		this.mDataList.add(data);


		// get axes list
		final SGAxis bAxis = this.mAxisElement.getAxisInPlane( SGAxisElement.AXIS_HORIZONTAL_1 );
		final SGAxis tAxis = this.mAxisElement.getAxisInPlane( SGAxisElement.AXIS_HORIZONTAL_2 );
		final SGAxis lAxis = this.mAxisElement.getAxisInPlane( SGAxisElement.AXIS_PERPENDICULAR_1 );
		final SGAxis rAxis = this.mAxisElement.getAxisInPlane( SGAxisElement.AXIS_PERPENDICULAR_2 );
		SGAxis axisX = null;
		SGAxis axisY = null;
		if( SGDefaultValues.SCALE_REFERENCE.equals("Left-Bottom") )
		{
			axisX = bAxis;
			axisY = lAxis;
		}
		else if( SGDefaultValues.SCALE_REFERENCE.equals("Left-Top") )
		{
			axisX = tAxis;
			axisY = lAxis;
		}
		else if( SGDefaultValues.SCALE_REFERENCE.equals("Right-Bottom") )
		{
			axisX = bAxis;
			axisY = rAxis;
		}
		else if( SGDefaultValues.SCALE_REFERENCE.equals("Right-Top") )
		{
			axisX = tAxis;
			axisY = rAxis;
		}
		else
		{
			return false;
		}


		//
		ElementGroupSetInGraph groupSet = null;
		if( data instanceof SGSXYData )
		{
			groupSet = this.createSingleGroupSet( (SGSXYData)data, axisX, axisY );
		}
		else if( data instanceof SGSXYMultipleData )
		{
			groupSet = this.createMultipleGroupSet( (SGSXYMultipleData)data, axisX, axisY );
		}
		else
		{
			return false;
		}


		//
		this.mGroupSetList.add( groupSet );


		// update the history after new data elements are added
		if( this.updateHistory() == false )
		{
			return false;
		}

this.notifyToRoot();


		return true;

	}



	/**
	 * 
	 */
/*	private ElementGroupSetForMultipleData createMultipleGroupSet(
		final SGSXYMultipleData data, final SGAxis axisX, final SGAxis axisY )
	{
//System.out.println("<< ElementGroupSetForMultipleData >>");


		final ElementGroupSetForMultipleDataInSXYGraph groupSet
			= new ElementGroupSetForMultipleDataInSXYGraph();

		// 名前
		final String name = "data"+(this.mGroupSetList.size()+1);
		groupSet.setName(name);


		groupSet.setXAxis(axisX);
		groupSet.setYAxis(axisY);


		// リストに追加
//		this.mGroupSetList.add( groupSet );


		final double[] xArray = data.getXValueArray();
		final double[][] yArray = data.getYValueArray();


		for( int ii=0; ii<yArray.length; ii++ )
		{
			SGSXYData dataSXY = new SGSXYData( xArray, yArray[ii] );

			ElementGroupSetInSXYGraph gs = new ElementGroupSetInSXYGraph();
			gs.setName(name);
			gs.setXAxis(axisX);
			gs.setYAxis(axisY);

			gs.setDrawingElementsLocation(dataSXY);
			gs.addDrawingElementGroup( SGElementGroup.POLYLINE_GROUP );
			gs.addDrawingElementGroup( SGElementGroup.SYMBOL_GROUP );
			gs.addDrawingElementGroup( SGElementGroup.RECTANGLE_GROUP );

			// 折れ線だけを描画するようにする
			final ElementGroupSymbol groupSymbol = this.getGroupSymbol( gs );
			groupSymbol.setVisible( false );

			final ElementGroupBar groupBar = this.getGroupBar( gs );
			groupBar.setVisible( false );


			//
			// エラーバーの作成
			//

			if( dataSXY.getErrorArray() != null )
			{
				final boolean flag = this.createErrorBar( gs, dataSXY );
				if( !flag )
				{
					return null;
				}
			}


			//
			// データ付属文字列の作成
			//

			if( dataSXY.getStringArray() != null )
			{
				final boolean flag = this.createTickLabels( gs, dataSXY );
				if( !flag )
				{
					return null;
				}
			}


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


			//
			gs.initPropertiesHistory();


			groupSet.mElementGroupSetList.add(gs);
		}


		groupSet.initPropertiesHistory();

//System.out.println();

		return groupSet;

	}
*/



	/**
	 * 
	 */
	private ElementGroupSetForMultipleData createMultipleGroupSet(
			final SGSXYMultipleData data, final SGAxis axisX, final SGAxis axisY )
	{
	
		final ElementGroupSetForMultipleDataInSXYGraph groupSet
			= new ElementGroupSetForMultipleDataInSXYGraph();
	
	
		// set the name
		final String name = "data"+(this.mGroupSetList.size()+1);
		groupSet.setName(name);
	
	
		// set axes
		groupSet.setXAxis(axisX);
		groupSet.setYAxis(axisY);
	

		//
		final double[] xArray = data.getXValueArray();
		final double[][] yArray = data.getYValueArray();
		for( int ii=0; ii<yArray.length; ii++ )
		{
			SGSXYData dataSXY = new SGSXYData( xArray, yArray[ii] );
			ElementGroupSetInSXYGraph gs
				= this.createGroupSetSXYInstance( dataSXY, axisX, axisY );

			gs.setName(name);
	
			//
			gs.initPropertiesHistory();

			//
			groupSet.mElementGroupSetList.add(gs);
		}	


		groupSet.initPropertiesHistory();

		return groupSet;		
	}




	/**
	 * 
	 */
	private ElementGroupSetInSXYGraph createSingleGroupSet(
		final SGSXYData data, final SGAxis axisX, final SGAxis axisY )
	{


		ElementGroupSetInSXYGraph groupSet
			= this.createGroupSetSXYInstance( data, axisX, axisY );


		// set the name of data
		final String name = "data"+(this.mGroupSetList.size()+1);
		groupSet.setName(name);


		//
		groupSet.initPropertiesHistory();


		return groupSet;		
	}




	/**
	 * 
	 * @param data
	 * @param axisX
	 * @param axisY
	 * @return
	 */
	private ElementGroupSetInSXYGraph createGroupSetSXYInstance(
		final SGSXYData data, final SGAxis axisX, final SGAxis axisY )
	{

		final ElementGroupSetInSXYGraph groupSet
			= new ElementGroupSetInSXYGraph();


		// set axes
		groupSet.setXAxis(axisX);
		groupSet.setYAxis(axisY);


		// create instances of the points
		final int num = data.getPointsNumber();
		SGTuple2d[] valueArray = data.getValueArray();
		SGTuple2f[] pointsArray = new SGTuple2f[num];
		for( int ii=0; ii<num; ii++ )
		{
			pointsArray[ii] = new SGTuple2f();
		}
		groupSet.mPointsArray = pointsArray;


		// add drawing element groups of lines, symbols and bars
		if( groupSet.addDrawingElementGroup( SGElementGroup.POLYLINE_GROUP ) == false )
		{
			throw new Error();
		}
		if( groupSet.addDrawingElementGroup( SGElementGroup.SYMBOL_GROUP ) == false )
		{
			throw new Error();
		}
		if( groupSet.addDrawingElementGroup( SGElementGroup.RECTANGLE_GROUP ) == false )
		{
			throw new Error();
		}


		// create error bar instance
		if( data.getErrorArray() != null )
		{
			ElementGroupErrorBar errorBar
				= this.createErrorBar( groupSet, data );

			if( errorBar == null )
			{
				throw new Error();
			}

			if( errorBar.setPropertiesOfDrawingElements() == false )
			{
				throw new Error();
			}

		}


		// create tick label instance
		if( data.getStringArray() != null )
		{
			if( this.createTickLabels( groupSet, data ) == null )
			{
				throw new Error();
			}
		}


		// set the location of the drawing elements of data
		if( groupSet.setDrawingElementsLocation( data ) == false )
		{
			throw new Error();
		}


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

		return groupSet;
	}




	/**
	 * 
	 */
	private ElementGroupTickLabelStringElement createTickLabels(
		ElementGroupSetInSXYGraph groupSet, SGSXYData dataSXY )
	{

		final ElementGroupTickLabelStringElement sGroup
			= new ElementGroupTickLabelStringElement();
		groupSet.mTickLabels = sGroup;
		sGroup.mGroupSet = groupSet;

		final int num = dataSXY.getPointsNumber();
		sGroup.initDrawingElement( num );

		SGTuple2f[] pointArray = new SGTuple2f[num];
		for( int ii=0; ii<num; ii++ )
		{
			pointArray[ii] = new SGTuple2f();
		}
		sGroup.mPointsArray = pointArray;

		String[] strArray = dataSXY.getStringArray();
		for( int ii=0; ii<num; ii++ )
		{
			SGDrawingElementString el
				= (SGDrawingElementString)sGroup.mDrawingElementArray[ii];
			el.setString( strArray[ii] );
		}

		if( sGroup.setPropertiesOfDrawingElements() == false )
		{
			throw new Error();
		}

		return sGroup;
	}




	/**
	 * 
	 */
	private ElementGroupErrorBar createErrorBar(
		final ElementGroupSetInSXYGraph groupSet,
		final SGSXYData dataSXY )
	{

		final ElementGroupErrorBar eGroup
			= new ElementGroupErrorBar();
		groupSet.mErrorBarGroup = eGroup;
		eGroup.mGroupSet = groupSet;

		eGroup.setMagnification( this.mMagnification );

		final int num = dataSXY.getPointsNumber();
		eGroup.initDrawingElement( num );

		SGTuple2f[] startArray = new SGTuple2f[num];
		SGTuple2f[] endArray = new SGTuple2f[num];
		for( int ii=0; ii<num; ii++ )
		{
			startArray[ii] = new SGTuple2f();
			endArray[ii] = new SGTuple2f();
		}
		eGroup.mStartArray = startArray;
		eGroup.mEndArray = endArray;


		return eGroup;
	}





	/**
	 * 
	 * @return
	 */
	private JPopupMenu createGroupSetPopupMenu( ElementGroupSetInGraph groupSet )
	{
		
		JPopupMenu menu = new JPopupMenu();
		menu.setBounds( 0, 0, 100, 100 );

		{
			final JMenuItem item = new JMenuItem( SGGraphElement.MENUCMD_MOVE_DATA_TO_BACK );
			item.addActionListener(groupSet);
			menu.add(item);
		}

		{
			final JMenuItem item = new JMenuItem( SGGraphElement.MENUCMD_MOVE_DATA_TO_FRONT );
			item.addActionListener(groupSet);
			menu.add(item);
		}

		{
			final JMenuItem item = new JMenuItem( SGGraphElement.MENUCMD_REMOVE_DATA );
			item.addActionListener(groupSet);
			menu.add(item);
		}

		menu.addSeparator();

		{
			final JMenuItem item = new JMenuItem( SGGraphElement.MENUCMD_PROPERTY );
			item.addActionListener(groupSet);
			menu.add(item);
		}

		return menu;
	}




	/**
	 * 
	 */
	protected boolean synchronizeToLegendElement( final SGILegendElement lElement )
	{

		final boolean flag = super.synchronizeToLegendElement(lElement);
		if( !flag )
		{
			return flag;
		}


ArrayList diffList = new ArrayList();

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

			final ElementGroupSetInGraph groupSet
				= (ElementGroupSetInGraph)this.mGroupSetList.get(ii);
			final ArrayList groupList = groupSet.mDrawingElementGroupList;
			final SGData data = (SGData)mDataList.get(ii);

			boolean diffFlag = false;

			// name of the data
			final String name = lElement.getDataName(data);
			if( name.equals(groupSet.mName) == false )
			{
				diffFlag = true;
			}
			groupSet.setName(name);


			// visible
			final boolean visibleFlag = lElement.isDataVisible(data);
			if( visibleFlag != groupSet.isVisible() )
			{
//				diffFlag = true;
			}
			groupSet.setVisible( visibleFlag );


			// set the properties of drawing elements
			final ArrayList dElementList = lElement.getDrawingElementList(data);
			groupSet.setDrawingElementProperties( dElementList );


			//
			if( diffFlag )
			{
				diffList.add( groupSet );
			}

		}

//System.out.println(diffList);

		if( diffList.size()!=0 )
		{
			for( int ii=0; ii<diffList.size(); ii++ )
			{
				final ElementGroupSetInGraph groupSet
					= (ElementGroupSetInGraph)diffList.get(ii);
				groupSet.updateThisObjectHistory();
			}
			this.updateObjectHistory( diffList );

			this.addToLatestHistory();
		}


		return flag;
	}



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

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

		super.paintGraphics2D(g2d);


		// データ付属文字列の描画
		for( int ii=0; ii<this.mGroupSetList.size(); ii++ )
		{
			final SGElementGroupSet groupSet
				= (SGElementGroupSet)this.mGroupSetList.get(ii);
			if( groupSet.isVisible() )
			{
				IElementGroupSetInSXYGraph iGroupSet
					= (IElementGroupSetInSXYGraph)groupSet;
				iGroupSet.paintDataString(g2d);
			}
		}


		// グラフ描画領域のクリッピング
		this.clipGraphArea(g2d);


		// タイミング線の描画
		for( int ii=0; ii<this.mTimingElementGroupSetList.size(); ii++ )
		{
//System.out.println("ii="+ii);
			final TimingElementGroupSetInGraph groupSet
				= (TimingElementGroupSetInGraph)mTimingElementGroupSetList.get(ii);
			if( groupSet.isVisible() )
			{
//System.out.println("timing");
				groupSet.paintGraphics2D(g2d);
			}
//System.out.println();
		}


		// グラフの描画
		for( int ii=0; ii<this.mGroupSetList.size(); ii++ )
		{
//System.out.println("ii="+ii);
			final SGElementGroupSet groupSet
				= (SGElementGroupSet)this.mGroupSetList.get(ii);
			if( groupSet.isVisible() )
			{
//System.out.println("!!!");
				groupSet.paintGraphics2D(g2d);
			}
		}
//System.out.println();

	}






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

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

		return null;
	}


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

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

		return null;
	}


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

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

		return null;
	}



	/**
	 * 
	 */
	protected boolean onZoomed( final float ratio )
	{

		super.onZoomed(ratio);

		for( int ii=0; ii<this.mGroupSetList.size(); ii++ )
		{
			final ElementGroupSetInGraph groupSet = (ElementGroupSetInGraph)this.mGroupSetList.get(ii);
			groupSet.zoom(ratio);
		}

		return true;
	}




	/**
	 * 
	 */
	public boolean getMarginAroundGraphAreaRect(
		SGTuple2f topAndBottom, SGTuple2f leftAndRight )
	{
//System.out.println("<< SGSXYGraphElement : getMarginAroundGraphAreaRect >>");

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


		// 各文字列群ごとに、全ての文字列を外包する矩形を取得する
		final ArrayList rectList = new ArrayList();
		for( int ii=0; ii<this.mGroupSetList.size(); ii++ )
		{
//System.out.println("ii="+ii);
			final ElementGroupSetInGraph groupSet
				= (ElementGroupSetInGraph)this.mGroupSetList.get(ii);
			SGData data = getData(groupSet);
			Rectangle2D rectAll = ((IElementGroupSetInSXYGraph)groupSet).getTickLabelsBoundingBox(data);
			if( rectAll==null )
			{
				return false;
			}

			if( rectAll.getWidth() < Double.MIN_VALUE || rectAll.getHeight() < Double.MIN_VALUE )
			{
				continue;
			}

			rectList.add(rectAll);
		}


		if( rectList.size()==0 )
		{
			return true;
		}


		// 得られた矩形を結合する
		Rectangle2D uniRect = SGUtility.createUnion(rectList);


		// 結合した矩形から幅を求める
		final float top = this.mGraphAreaY - (float)uniRect.getY();
		final float bottom = -( this.mGraphAreaY + this.mGraphAreaHeight )
			 + (float)( uniRect.getY() + uniRect.getHeight() );
		final float left = this.mGraphAreaX - (float)uniRect.getX();
		final float right = -( this.mGraphAreaX + this.mGraphAreaWidth )
			 + (float)( uniRect.getX() + uniRect.getWidth() );


		// 引数に設定
		topAndBottom.x += top;
		topAndBottom.y += bottom;
		leftAndRight.x += left;
		leftAndRight.y += right;

		return true;

	}



	/**
	 * 
	 */
	protected boolean transformDrawingElementsLocation()
	{
//System.out.println("<< SGSXYGraphElement::transformDrawingElementsLocation >>");

		// get an transform matrix
		AffineTransform af = new AffineTransform();
		Rectangle2D rect = this.getGraphAreaRect();
		if( this.mTempGraphAreaRect.getWidth()>Double.MIN_VALUE
			|| this.mTempGraphAreaRect.getHeight()>Double.MIN_VALUE )
		{
			final double ratioX = rect.getWidth()/this.mTempGraphAreaRect.getWidth();
			final double ratioY = rect.getHeight()/this.mTempGraphAreaRect.getHeight();
			af.translate( rect.getX(), rect.getY() );
			af.scale( ratioX, ratioY );
			af.translate( - this.mTempGraphAreaRect.getX(), - this.mTempGraphAreaRect.getY() );
		}
		this.mTempGraphAreaRect = rect;


		// calculate coordinates of data
		for( int ii=0; ii<this.mGroupSetList.size(); ii++ )
		{
			final ElementGroupSetInGraph groupSet
				= (ElementGroupSetInGraph)this.mGroupSetList.get(ii);

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

			final SGData data = (SGData)this.mDataList.get(ii);

			if( ((IElementGroupSetInSXYGraph)groupSet).transformDrawingElementsLocation(data,af) == false )
			{
				return false;
			}
		}


		// timing elements
		for( int ii=0; ii<this.mTimingElementGroupSetList.size(); ii++ )
		{
			final TimingElementGroupSetInGraph groupSet
				= (TimingElementGroupSetInGraph)this.mTimingElementGroupSetList.get(ii);
			if( groupSet.setDrawingElementsLocation() == false )
			{
				return false;
			}
		}


		return true;
	}



	/**
	 * 全描画要素の位置を決定
	 */
	protected boolean setAllDrawingElementsLocation()
	{
//System.out.println("<< SGSXYGraphElement::setAllDrawingElementsLocation >>");

		for( int ii=0; ii<this.mGroupSetList.size(); ii++ )
		{
			final ElementGroupSetInGraph groupSet
				= (ElementGroupSetInGraph)this.mGroupSetList.get(ii);

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

			final SGData data = (SGData)this.mDataList.get(ii);

			// calculate coordinates in graph
			if( ((IElementGroupSetInSXYGraph)groupSet).setDrawingElementsLocation(data) == false )
			{
				return false;
			}
		}


		// timing elements
		for( int ii=0; ii<this.mTimingElementGroupSetList.size(); ii++ )
		{
			final TimingElementGroupSetInGraph groupSet
				= (TimingElementGroupSetInGraph)this.mTimingElementGroupSetList.get(ii);
			if( groupSet.setDrawingElementsLocation() == false )
			{
				return false;
			}
		}


		return true;

	}




	/**
	 * 
	 */
	protected ElementGroupSetInGraph getGroupSetNewInstance( final SGData data )
	{
		ElementGroupSetInGraph groupSet = null;

		if( data instanceof SGSXYData )
		{
			groupSet = new ElementGroupSetInSXYGraph();
		}
		else if( data instanceof SGSXYMultipleData )
		{
			groupSet = new ElementGroupSetForMultipleDataInSXYGraph();
		}

		return groupSet;
	}



	/**
	 * 
	 */
	public boolean createDataObject( final BufferedReader br, final SGData data ) throws IOException
	{
//System.out.println("??? createDataObject ???");

		if( !( data instanceof SGSXYData ) && !( data instanceof SGSXYMultipleData ) )
		{
			return false;
		}

		super.createDataObject( br, data );


		// construct a SGElementGroupSet object
		ElementGroupSetInGraph groupSet = this.getGroupSetNewInstance(data);
		if( groupSet==null )
		{
			return false;
		}


		//
		this.mGroupSetList.add( groupSet );


		//
		int ret = this.setProperty( br, groupSet );
		if( ret==SGIConstants.PROPERTY_FILE_INCORRECT )
		{
			return false;
		}


		return true;

	}



	/**
	 * 
	 */
	private int setProperty(
		final BufferedReader br, final ElementGroupSetInGraph groupSet )
		throws IOException
	{
//System.out.println("&&& setProperty &&&");
//System.out.println(this.mDataList);

		SGData data = this.getData(groupSet);
//System.out.println(data);

		int ret = SGIConstants.PROPERTY_FILE_INCORRECT;
		if( data instanceof SGSXYData )
		{
			SGSXYData data_ = (SGSXYData)data;
			ElementGroupSetInSXYGraph gs = (ElementGroupSetInSXYGraph)groupSet;
			ret = this.setPropertyOfElementGroupSetInSXYGraph(br,gs,data_);
		}
		else if( data instanceof SGSXYMultipleData )
		{
			SGSXYMultipleData data_ = (SGSXYMultipleData)data;
			ElementGroupSetForMultipleDataInSXYGraph gs
				= (ElementGroupSetForMultipleDataInSXYGraph)groupSet;
			ret = this.setPropertyOfElementGroupSetForMultipleDataInSXYGraph(br,gs,data_);
		}


		return ret;
	}



	/**
	 * 
	 */
	private int setPropertyOfElementGroupSetForMultipleDataInSXYGraph(
		final BufferedReader br,
		final ElementGroupSetForMultipleDataInSXYGraph groupSet,
		final SGSXYMultipleData data )
		throws IOException
	{
//System.out.println();
//System.out.println("<< setPropertyOfElementGroupSetForMultipleDataInSXYGraph >>");

		// clear the list of the group of the drawing elements
		groupSet.mDrawingElementGroupList.clear();

		SGSXYData[] dataArray = data.getSXYDataArray();
		ElementGroupSetInSXYGraph gs = new ElementGroupSetInSXYGraph();
		int ret = this.setPropertyOfElementGroupSetInSXYGraph(br,gs,dataArray[0]);
		if( ret==SGIConstants.PROPERTY_FILE_INCORRECT )
		{
			return ret;
		}
		SGProperties p = gs.getProperties();
		SGProperties wp = gs.getWholeProperties();

//System.out.println(wp);

		ElementGroupSetInSXYGraph[] gsArray = new ElementGroupSetInSXYGraph[dataArray.length];
		ArrayList gsList = new ArrayList();
		for( int ii=0; ii<gsArray.length; ii++ )
		{
			gsArray[ii] = new ElementGroupSetInSXYGraph();
			if( gsArray[ii].setProperties(p) == false )
			{
				return SGIConstants.PROPERTY_FILE_INCORRECT;
			}

			gsArray[ii].setDrawingElementsLocation(dataArray[ii]);
			gsArray[ii].addDrawingElementGroup( SGElementGroup.POLYLINE_GROUP );
			gsArray[ii].addDrawingElementGroup( SGElementGroup.SYMBOL_GROUP );
			gsArray[ii].addDrawingElementGroup( SGElementGroup.RECTANGLE_GROUP );

			if( gsArray[ii].setWholeProperties(wp) == false )
			{
				return SGIConstants.PROPERTY_FILE_INCORRECT;
			}

			gsArray[ii].initPropertiesHistory();

			gsList.add(gsArray[ii]);
		}
		

		groupSet.mElementGroupSetList = new ArrayList( gsList );
		groupSet.mName = new String( gs.getName() );

		groupSet.initPropertiesHistory();

//System.out.println(groupSet.mElementGroupSetList);
//System.out.println();


		return SGIConstants.SUCCESSFUL_COMPLETION;

	}




	/**
	 * 
	 */
	private int setPropertyOfElementGroupSetInSXYGraph(
		final BufferedReader br,
		final ElementGroupSetInSXYGraph groupSet,
		final SGSXYData data )
		throws IOException
	{

		// clear the list of the group of the drawing elements
		groupSet.mDrawingElementGroupList.clear();


		String line = null;


		// name of data
		if( ( line = SGUtilityText.readLine(br) ) == null )
		{
			return SGIConstants.PROPERTY_FILE_INCORRECT;
		}
		String name = SGUtilityText.getStringPropertyFromLine(line,SGIGraphElement.PF_DATA_NAME);
		if( name == null )
		{
			return SGIConstants.PROPERTY_FILE_INCORRECT;
		}
//System.out.println(name);


		// configuration of X-axis
		if( ( line = SGUtilityText.readLine(br) ) == null )
		{
			return SGIConstants.PROPERTY_FILE_INCORRECT;
		}
		String strConfigX = SGUtilityText.getPropertyFromLine(line,SGIGraphElement.PF_LOCATION_X_AXIS);
		if( strConfigX==null )
		{
			return SGIConstants.PROPERTY_FILE_INCORRECT;
			
		}
		int configX = this.mAxisElement.getConfigurationInCubeFromStringInPlane(strConfigX);


		// configuration of Y-axis
		if( ( line = SGUtilityText.readLine(br) ) == null )
		{
			return SGIConstants.PROPERTY_FILE_INCORRECT;
		}
		String strConfigY = SGUtilityText.getPropertyFromLine(line,SGIGraphElement.PF_LOCATION_Y_AXIS);
		if( strConfigY==null )
		{
			return SGIConstants.PROPERTY_FILE_INCORRECT;
			
		}
		int configY = this.mAxisElement.getConfigurationInCubeFromStringInPlane(strConfigY);


		// set the name
		groupSet.setName(name);


		// set x- and y-axis
		groupSet.mXAxis = this.mAxisElement.getAxisInCube( configX );
		groupSet.mYAxis = this.mAxisElement.getAxisInCube( configY );



		// create instances of the points
		final int num = data.getPointsNumber();
		SGTuple2d[] valueArray = data.getValueArray();
		SGTuple2f[] pointsArray = new SGTuple2f[num];
		for( int ii=0; ii<num; ii++ )
		{
			pointsArray[ii] = new SGTuple2f();
		}
		groupSet.mPointsArray = pointsArray;



		// error bar
		if( ( line = SGUtilityText.readLine(br) ) == null )
		{
			return SGIConstants.PROPERTY_FILE_INCORRECT;
		}

		if( line.equals( SGElementGroupErrorBar.ERROR_BAR_TITLE ) )
		{

			// 読み込まれたデータがエラーバー情報を持っているとは限らない！
			// 持っている場合には以下の処理を行う
			if( data.getErrorArray() != null )
			{
				ElementGroupErrorBar group
					= this.createErrorBar( groupSet, data );

				group.readProperty(br);

				if( group.setPropertiesOfDrawingElements() == false )
				{
					throw new Error();
				}

				group.setLocation(
					group.mStartArray,
					group.mEndArray );

			}
			else
			{
				ElementGroupErrorBar group = new ElementGroupErrorBar();
				group.readProperty(br);
			}

		}
		else if( line.equals( PF_ERROR_BAR_EMPTY ) )
		{
			// 読み込まれたデータがエラーバー情報を持っていないとは限らない！
			// 持っている場合には以下の処理を行う
			if( data.getErrorArray() != null )
			{
				this.createErrorBar( groupSet, data );
			}
		}


		// tick labels
		if( ( line = SGUtilityText.readLine(br) ) == null )
		{
			return SGIConstants.PROPERTY_FILE_INCORRECT;
		}

		if( line.equals( SGElementGroupTickLabel.PF_TICK_LABEL_TITLE ) )
		{

			// 読み込まれたデータがデータ文字列情報を持っているとは限らない！
			if( data.getStringArray() != null )
			{
				ElementGroupTickLabelStringElement group
					= this.createTickLabels( groupSet, data );
				group.readProperty(br);

				if( group.setPropertiesOfDrawingElements() == false )
				{
					throw new Error();
				}

				group.setLocation( group.mPointsArray );
			}
			else
			{
				ElementGroupTickLabelStringElement group
					= new ElementGroupTickLabelStringElement();
				group.readProperty(br);
			}

		}
		else if( line.equals( PF_TICK_LABELS_EMPTY ) )
		{
			// 読み込まれたデータがデータ付属文字列情報を持っていないとは限らない！
			if( data.getStringArray() != null )
			{
				this.createTickLabels( groupSet, data );
			}
		}



		// group
		br.mark(256);
		while( true )
		{

			SGElementGroup group = null;


			if( ( line = SGUtilityText.readLine(br) ) == null )
			{
				break;
			}

			if( line.equals( SGElementGroupLine.PF_LINE_TITLE ) )
			{
				if( groupSet.addDrawingElementGroup( SGElementGroup.POLYLINE_GROUP ) == false )
				{
					throw new Error();
				}
				group = (SGElementGroup)(groupSet.getLineGroups().get(0));
			}
			else if( line.equals( SGElementGroupSymbol.PF_SYMBOL_TITLE ) )
			{
				if( groupSet.addDrawingElementGroup( SGElementGroup.SYMBOL_GROUP ) == false )
				{
					throw new Error();
				}
				group = (SGElementGroup)(groupSet.getSymbolGroups().get(0));
			}
			else if( line.equals( SGElementGroupBar.BAR_TITLE ) )
			{
				if( groupSet.addDrawingElementGroup( SGElementGroup.RECTANGLE_GROUP ) == false )
				{
					throw new Error();
				}
				group = (SGElementGroup)(groupSet.getBarGroups().get(0));
			}
			else
			{
				br.reset();
				break;
			}


			group.readProperty(br);

			br.mark(256);
		}


		//
		groupSet.initPropertiesHistory();


		return SGIConstants.SUCCESSFUL_COMPLETION;

	}




	/**
	 * 
	 */
	public static interface IElementGroupSetInSXYGraph
	{
		/**
		 * 
		 */
		public Rectangle2D getTickLabelsBoundingBox( final SGData data );


		/**
		 * 
		 */
		public boolean setDrawingElementsLocation( final SGData data );

		/**
		 * 
		 */
		public boolean paintDataString( final Graphics2D g2d );


		public boolean transformDrawingElementsLocation( final SGData data, final AffineTransform af );

	}




	/**
	 * 
	 */
	class ElementGroupSetForMultipleDataInSXYGraph
		extends ElementGroupSetForMultipleData
		implements ActionListener, IElementGroupSetInSXYGraph
	{

		/**
		 * 
		 */
		protected ElementGroupSetForMultipleDataInSXYGraph()
		{
			super();
			this.mPopupMenu = createGroupSetPopupMenu(this);
		}



		/**
		 * 
		 */
		protected boolean createDrawingElements()
		{
			for( int ii=0; ii<this.mElementGroupSetList.size(); ii++ )
			{
				ElementGroupSetInGraph groupSet
					= (ElementGroupSetInGraph)this.mElementGroupSetList.get(ii);
				if( groupSet.createDrawingElements() == false )
				{
					return false;
				} 
			}

			return true;
		}


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

			if( ( data instanceof SGSXYMultipleData ) == false )
			{
				return false;
			}

			SGSXYMultipleData data_ = (SGSXYMultipleData)data;
			SGSXYData[] dataSXYArray = data_.getSXYDataArray();
			for( int ii=0; ii<this.mElementGroupSetList.size(); ii++ )
			{
				IElementGroupSetInSXYGraph gs
					= (IElementGroupSetInSXYGraph)this.mElementGroupSetList.get(ii);
				if( gs.setDrawingElementsLocation(dataSXYArray[ii]) == false )
				{
					return false;
				}
			}

			return true;
		}


		/**
		 * 
		 */
		public boolean transformDrawingElementsLocation( final SGData data, final AffineTransform af )
		{
			if( ( data instanceof SGSXYMultipleData ) == false )
			{
				return false;
			}

			SGSXYMultipleData data_ = (SGSXYMultipleData)data;
			SGSXYData[] dataSXYArray = data_.getSXYDataArray();
			for( int ii=0; ii<this.mElementGroupSetList.size(); ii++ )
			{
				IElementGroupSetInSXYGraph gs
					= (IElementGroupSetInSXYGraph)this.mElementGroupSetList.get(ii);
				if( gs.transformDrawingElementsLocation(dataSXYArray[ii],af) == false )
				{
					return false;
				}
			}

			return true;
		}


		/**
		 * 
		 */
		public Rectangle2D getTickLabelsBoundingBox( final SGData data )
		{
			if( ( data instanceof SGSXYMultipleData ) == false )
			{
				return null;
			}

//System.out.println("getTickLabelsBoundingBox:"+data);
//System.out.println(this.mElementGroupSetList);

			SGSXYMultipleData data_ = (SGSXYMultipleData)data;
			SGSXYData[] dataSXYArray = data_.getSXYDataArray();

			ArrayList list = new ArrayList();
			for( int ii=0; ii<this.mElementGroupSetList.size(); ii++ )
			{
//System.out.println("ii="+ii);
				IElementGroupSetInSXYGraph groupSet
					= (IElementGroupSetInSXYGraph)this.mElementGroupSetList.get(ii);
				Rectangle2D rect = groupSet.getTickLabelsBoundingBox(dataSXYArray[ii]);
//System.out.println(rect);
				if( rect==null )
				{
					return null;
				}
				list.add(rect);
			}
//System.out.println();
//System.out.println(list);

			Rectangle2D rectAll = SGUtility.createUnion(list);
//System.out.println(rectAll);

			return rectAll;

		}



		/**
		 * 
		 */
		public boolean paintDataString( final Graphics2D g2d )
		{

			for( int ii=0; ii<this.mElementGroupSetList.size(); ii++ )
			{
				IElementGroupSetInSXYGraph groupSet
					= (IElementGroupSetInSXYGraph)this.mElementGroupSetList.get(ii);
				groupSet.paintDataString(g2d);
			}

			return true;
		}



		/**
		 * 
		 */
		public boolean showPropertyDialog()
		{

			super.showPropertyDialog();


			final SGPropertyDialogSXYData dg
				= (SGPropertyDialogSXYData)mPropertyDialogForData;


			// ダイアログにプロパティ設定
			this.setDialogProperty();


			// 現在選択されているタブの番号を取得
			final int index = dg.getTabbedPane().getSelectedIndex();
			dg.setColorButtonProperty( index );


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


			dg.setVisible(true);

			return true;
		}



		/**
		 * 
		 */
		public boolean createTemporaryPropertyObject()
		{
			this.mTemporaryProperties = this.getWholeProperties();
			return true;
		}



		/**
		 * 
		 */
		private boolean setDialogProperty()
		{
			ElementGroupSetInSXYGraph groupSet
				= (ElementGroupSetInSXYGraph)this.mElementGroupSetList.get(0);
			if( groupSet.setDialogProperty() == false )
			{
				return false;
			}

			return true;
		}


		/**
		 * 
		 */
		public boolean setPropertiesFromDialog()
		{
//System.out.println("<< setPropertyWithDialog >>");

			final SGPropertyDialogSXYData dg = (SGPropertyDialogSXYData)mPropertyDialogForData;


			// 全部がチェックアウトされたら警告
			if( !dg.getLineVisible()
			&& !dg.getBarVisible()
			&& !dg.getSymbolVisible() )
			{
				JOptionPane.showMessageDialog(
					dg, MSG_NOT_HIDE_ALL_ELEMENTS );
				return false;
			}


			for( int ii=0; ii<this.mElementGroupSetList.size(); ii++ )
			{
				ElementGroupSetInSXYGraph groupSet
					= (ElementGroupSetInSXYGraph)this.mElementGroupSetList.get(ii);
				if( groupSet.setPropertyWithDialog_() == false )
				{
					return false;
				}
			}

			return true;			
		}



		/**
		 * 
		 * @return
		 */
		protected boolean recover()
		{
			if( this.setWholeProperties( this.mTemporaryProperties ) == false )
			{
				return false;
			}

			return true;
		}



		/**
		 * 
		 */
		protected boolean clickDrawingElements( final MouseEvent e )
		{

			final int x = e.getX();
			final int y = e.getY();
			if( this.contains(x,y) == false )
			{
				return false;
			}


			if( (SwingUtilities.isRightMouseButton(e) )
				&& ( e.getClickCount() == 1 ) )
			{
//					final JPopupMenu menu = errBarGroup.getPopupMenu();
//					menu.show( this, e.getX(), e.getY() );
			}
			else if( (SwingUtilities.isLeftMouseButton(e) )
				&& ( e.getClickCount() == 2 ) )
			{
				this.showPropertyDialog();
			}

			return true;

		}



		/**
		 * 
		 */
		public SGProperties getProperties()
		{
			ElementGroupSetPropertiesForSamplingDataInSXYGraph p
				= new ElementGroupSetPropertiesForSamplingDataInSXYGraph();
			if( this.getProperties(p) == false ) return null;
			return p;
		}


		/**
		 * 
		 */
		public boolean getProperties( final SGProperties p )
		{
			if( ( p instanceof ElementGroupSetPropertiesForSamplingDataInSXYGraph ) == false )
			{
				return false;
			}

			ElementGroupSetPropertiesForSamplingDataInSXYGraph gp
				= (ElementGroupSetPropertiesForSamplingDataInSXYGraph)p;


			gp.samplingRate = this.getSamplingRate();

			return true;

		}



		/**
		 * 
		 */
		public double getSamplingRate()
		{
			SGData data =  getData(this);
			SGSXYSamplingData sData = (SGSXYSamplingData)data;
			return sData.getSamplingRate();
		}



		/**
		 * 
		 */
		public SGProperties getWholeProperties()
		{
			ElementGroupSetInSXYGraph groupSet
				= (ElementGroupSetInSXYGraph)this.mElementGroupSetList.get(0);
			WholeProperties wp = new WholeProperties();
			if( groupSet.getWholeProperties(wp) == false ) return null;
			return wp;
		}


		/**
		 * 
		 */
		public boolean setWholeProperties( SGProperties p )
		{
			if( ( p instanceof WholeProperties ) == false ) return false;

			WholeProperties wp = (WholeProperties)p;
			for( int ii=0; ii<this.mElementGroupSetList.size(); ii++ )
			{
				ElementGroupSetInSXYGraph groupSet
					= (ElementGroupSetInSXYGraph)this.mElementGroupSetList.get(ii);
				if( groupSet.setWholeProperties(p) == false ) return false;
			}

			return true;
		}


		/**
		 * 
		 */
		public boolean writePropertyOfData( final Writer writer ) throws IOException
		{

			SGSXYMultipleData data = (SGSXYMultipleData)getData( this );
//System.out.println(data);

			// write sampling rate
			if( data instanceof SGSXYSamplingData )
			{
				double sRate = this.getSamplingRate();
				SGUtilityText.writePropertyLine( writer, PF_SAMPLING_RATE, new Double(sRate) );
			}


			// call the method in the super class
			if( super.writePropertyOfData(writer) == false )
			{
				return false;
			}


			// 軸の配置の出力
			final int configX = mAxisElement.getConfigurationInCube( this.mXAxis );
			final int configY = mAxisElement.getConfigurationInCube( this.mYAxis );

			final String strX = mAxisElement.getConfigurationStringInPlaneByCube( configX );
			final String strY = mAxisElement.getConfigurationStringInPlaneByCube( configY );

			SGUtilityText.writePropertyLine( writer, PF_LOCATION_X_AXIS, strX );
			SGUtilityText.writePropertyLine( writer, PF_LOCATION_Y_AXIS, strY );

			writer.write("\n");


			// Properties of Error Bars
			writer.write( PF_ERROR_BAR_EMPTY );
			writer.write("\n\n");


			// Properties of Data String
			writer.write( PF_TICK_LABELS_EMPTY );
			writer.write("\n\n");


			// 各データが持つ描画要素群にプロパティを出力させる
			ElementGroupSetInSXYGraph groupSet
				= (ElementGroupSetInSXYGraph)this.mElementGroupSetList.get(0);
			ArrayList list = groupSet.mDrawingElementGroupList;
			for( int ii=0; ii<list.size(); ii++ )
			{
				final SGElementGroup group = (SGElementGroup)list.get(ii);
				group.writePropertyOfData(writer);
			}

			writer.write("\n");

			return true;

		}



		/**
		 * 
		 */
		public SGProperties readProperties( final BufferedReader br )
			throws IOException
		{

			ElementGroupSetInGraphProperties p = null;

			SGData data = getData(this);
			
			if( data instanceof SGSXYSamplingData )
			{
				p = new ElementGroupSetPropertiesForSamplingDataInSXYGraph();
			}
			else
			{
				p = new ElementGroupSetInGraphProperties();
			}

			if( this.readProperties(br,p) == false )
			{
				return null;
			}

			String line = null;
			if( data instanceof SGSXYSamplingData )
			{
				if( SGUtilityText.readLine(br) == null )
				{
					return null;
				}

				Double d = SGUtilityText.getDoublePropertyFromLine(line,PF_SAMPLING_RATE);
				if( d==null )
				{
					return null;
				}
				ElementGroupSetPropertiesForSamplingDataInSXYGraph ep
					= (ElementGroupSetPropertiesForSamplingDataInSXYGraph)p;
				ep.samplingRate = d.doubleValue();
			}


			WholeProperties wp = new WholeProperties();
			wp.ep = p;

			// group
			for( int ii=0; ii<this.mDrawingElementGroupList.size(); ii++ )
			{
				if( ( line = SGUtilityText.readLine(br) ) == null ) return null;

				SGElementGroup group = (SGElementGroup)this.mDrawingElementGroupList.get(ii);
				SGProperties gp = group.readProperties(br);
				(wp.ipList).add(gp);
			}

			return wp;
		}




		/**
		 * 
		 */
		class ElementGroupSetPropertiesForSamplingDataInSXYGraph
			extends ElementGroupSetInGraphProperties
		{

			double samplingRate;

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

				if( obj == null )
				{
					return false;
				}

				if( ( obj instanceof ElementGroupSetPropertiesForSamplingDataInSXYGraph ) == false )
				{
					return false;
				}

				ElementGroupSetPropertiesForSamplingDataInSXYGraph p
					= (ElementGroupSetPropertiesForSamplingDataInSXYGraph)obj;

				if( p.samplingRate!=this.samplingRate ) return false;

				return true;

			}

			
		}



	}




	/**
	 * 
	 */
	class ElementGroupSetInSXYGraph extends ElementGroupSetInGraph
		implements IElementGroupSetInSXYGraph, SGIPropertySettingListenerSXYData
	{

		/**
		 * 
		 */
		private ElementGroupErrorBar mErrorBarGroup = null;


		/**
		 * 
		 */
		private ElementGroupTickLabelStringElement mTickLabels = null;



		/**
		 * 
		 */
		protected ElementGroupSetInSXYGraph()
		{
			super();
			this.mPopupMenu = createGroupSetPopupMenu(this);
		}



		/**
		 * 
		 */
		public boolean contains( final int x, final int y )
		{
//System.out.println("<< ElementGroupSetInGraph::contains >>");

			if( super.contains(x,y) )
			{
//System.out.println("return true : gs"+"  "+this);
				return true;
			}

			if( this.mErrorBarGroup!=null )
			{
				if( this.mErrorBarGroup.contains(x,y) )
				{
					return true;
				}
			}
			
			if( this.mTickLabels!=null )
			{
				if( this.mTickLabels.contains(x,y) )
				{
					return true;
				}
			}

			return false;
		}


		/**
		 * 
		 */
		public boolean zoom( float ratio )
		{
			super.zoom(ratio);

			// error bars
			final ElementGroupErrorBar eGroup = this.mErrorBarGroup;
			if( eGroup != null )
			{
				eGroup.zoom(ratio);
			}

			// tick labels
			if( this.mTickLabels != null )
			{
				this.mTickLabels.zoom(ratio);
			}

			return true;
		}



		/**
		 * 
		 */
		public ArrayList getLineGroups()
		{
			ArrayList list = new ArrayList();
			for( int ii=0; ii<this.mDrawingElementGroupList.size(); ii++ )
			{
				Object obj = this.mDrawingElementGroupList.get(ii);
				if( obj instanceof SGElementGroupLine )
				{
					list.add(obj);
				}
			}
			return list;
		}


		/**
		 * 
		 */
		public ArrayList getSymbolGroups()
		{
			ArrayList list = new ArrayList();
			for( int ii=0; ii<this.mDrawingElementGroupList.size(); ii++ )
			{
				Object obj = this.mDrawingElementGroupList.get(ii);
				if( obj instanceof SGElementGroupSymbol )
				{
					list.add(obj);
				}
			}
			return list;
		}


		/**
		 * 
		 */
		public ArrayList getBarGroups()
		{
			ArrayList list = new ArrayList();
			for( int ii=0; ii<this.mDrawingElementGroupList.size(); ii++ )
			{
				Object obj = this.mDrawingElementGroupList.get(ii);
				if( obj instanceof SGElementGroupBar )
				{
					list.add(obj);
				}
			}
			return list;
		}


		/**
		 * 
		 */
		public ArrayList getErrorBarGroups()
		{
			ArrayList list = new ArrayList();
			if( this.mErrorBarGroup!=null )
			{
				list.add( this.mErrorBarGroup );
			}
			return list;
		}


		/**
		 * 
		 */
		public ArrayList getTickLabelGroups()
		{
			ArrayList list = new ArrayList();
			if( this.mTickLabels!=null )
			{
				list.add( this.mTickLabels );
			}
			return list;
		}



		public boolean setLineProperties( SGProperties p )
		{
			return this.setProperties( this.getLineGroups(), p );
		}


		public boolean setSymbolProperties( SGProperties p )
		{
			return this.setProperties( this.getSymbolGroups(), p );
		}


		public boolean setBarProperties( SGProperties p )
		{
			return this.setProperties( this.getBarGroups(), p );
		}


		public boolean setErrorBarProperties( SGProperties p )
		{
			return this.setProperties( this.getErrorBarGroups(), p );
		}


		public boolean setTickLabelProperties( SGProperties p )
		{
			return this.setProperties( this.getTickLabelGroups(), p );
		}



		private boolean setProperties( ArrayList groupList, SGProperties p )
		{
			for( int ii=0; ii<groupList.size(); ii++ )
			{
				SGElementGroup group = (SGElementGroup)groupList.get(ii);
				if( group.setProperties(p) == false )
				{
					return false;
				}
			}

			return true;
		}


		/**
		 * 
		 */
		public int getXAxisConfiguration()
		{
			return mAxisElement.getConfigurationInPlane( this.mXAxis );
		}


		/**
		 * 
		 */
		public int getYAxisConfiguration()
		{
			return mAxisElement.getConfigurationInPlane( this.mYAxis );
		}


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

			SGElementGroupSXY group = null;
			if( type == SGElementGroup.POLYLINE_GROUP )
			{
				group = new ElementGroupLine();
			}
			else if( type == SGElementGroup.RECTANGLE_GROUP )
			{
				group = new ElementGroupBar();
			}
			else if( type == SGElementGroup.SYMBOL_GROUP )
			{
				group = new ElementGroupSymbol();
			}
			else
			{
				throw new Error("");
			}


			// 既に存在する場合には追加しない
			if( this.checkGroupType( group ) == false )
			{
				return false;
			}

			// add a group
			this.addElementGroup(group);

			return true;
		}



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

			SGElementGroupSXY group = null;
			if( element instanceof SGDrawingElementLine )
			{
				group = new ElementGroupLine();
			}
			else if( element instanceof SGDrawingElementRectangle )
			{
				group = new ElementGroupBar();
			}
			else if( element instanceof SGDrawingElementSymbol )
			{
				group = new ElementGroupSymbol();
			}
			else
			{
				throw new Error("");
			}


			// 既に存在する場合には追加しない
			if( this.checkGroupType( group ) == false )
			{
				return false;
			}


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

			this.addElementGroup(group);


			return true;

		}



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

			final Class cl = group.getClass();
			for( int ii=0; ii<this.mDrawingElementGroupList.size(); ii++ )
			{
				final SGElementGroup group_
					= (SGElementGroup)this.mDrawingElementGroupList.get(ii);
				final Class cl_ = group_.getClass();
				if( cl.equals(cl_) )
				{
					System.out.println("既に存在します！");
					return false;
				}
			}

			return true;
		}



		/**
		 * 
		 * @return
		 */
		protected boolean isLineVisible()
		{
			ArrayList list = this.getLineGroups();
			SGElementGroup group = (SGElementGroup)list.get(0);
			return group.isVisible();
		}


		/**
		 * 
		 * @return
		 */
		protected boolean isSymbolVisible()
		{
			ArrayList list = this.getSymbolGroups();
			SGElementGroup group = (SGElementGroup)list.get(0);
			return group.isVisible();
		}


		/**
		 * 
		 * @return
		 */
		protected boolean isBarVisible()
		{
			ArrayList list = this.getBarGroups();
			SGElementGroup group = (SGElementGroup)list.get(0);
			return group.isVisible();
		}



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



		/**
		 * Called when the location of data points have changed.
		 */
		public boolean setDrawingElementsLocation( final SGData data )
		{

			if( ( data instanceof SGSXYData ) == false )
			{
				return false;
			}
			SGSXYData dataSXY = (SGSXYData)data;
			final int num = dataSXY.getPointsNumber();


			// set the location of the data points
			SGTuple2d[] valueArray = dataSXY.getValueArray();
			if( calcLocationOfSXYData(
				valueArray,
				this.mXAxis,
				this.mYAxis,
				this.mPointsArray ) == false )
			{
				return false;
			}


			for( int ii=0; ii<this.mDrawingElementGroupList.size(); ii++ )
			{
				SGElementGroupSXY group
					= (SGElementGroupSXY)this.mDrawingElementGroupList.get(ii);
				if( group.isVisible() )
				{
					if( group.setLocation( this.mPointsArray ) == false )
					{
						return false;
					}
				}
			}


			// set the location of error bars
			if( this.mErrorBarGroup!=null )
			{
				if( this.mErrorBarGroup.isVisible() )
				{
					SGTuple2f[] startArray = this.mErrorBarGroup.mStartArray;
					SGTuple2f[] endArray = this.mErrorBarGroup.mEndArray;
					if( this.mErrorBarGroup.calcErrorBarLocation(
						dataSXY,
						this.mXAxis,
						this.mYAxis,
						startArray,
						endArray ) == false )
					{
						return false;
					}

					if( this.mErrorBarGroup.setLocation(
						startArray,
						endArray ) == false )
					{
						return false;
					}
				}

			}


			// set the location of tick labels
			if( this.mTickLabels!=null )
			{
				if( this.mTickLabels.isVisible() )
				{
					SGTuple2f[] pointArray = this.mTickLabels.mPointsArray;

					if( this.mTickLabels.calcTickLabelLocation(
						dataSXY, this.mXAxis, pointArray ) == false )
					{
						return false;
					}

					if( this.mTickLabels.setLocation( pointArray ) == false )
					{
						return false;
					}
				}
			}


			return true;
		}




		public boolean transformDrawingElementsLocation(
			final SGData data, final AffineTransform af )
		{

			if( ( data instanceof SGSXYData ) == false )
			{
				return false;
			}
			SGSXYData dataSXY = (SGSXYData)data;
			final int num = dataSXY.getPointsNumber();


			for( int ii=0; ii<this.mPointsArray.length; ii++ )
			{
				SGTuple2f point = this.mPointsArray[ii];
				point.x = (float)( point.x*af.getScaleX() + af.getTranslateX() );
				point.y = (float)( point.y*af.getScaleY() + af.getTranslateY() );
			}

			for( int ii=0; ii<this.mDrawingElementGroupList.size(); ii++ )
			{
				SGElementGroupSXY group
					= (SGElementGroupSXY)this.mDrawingElementGroupList.get(ii);
				if( group.isVisible() )
				{
					if( group.setLocation( this.mPointsArray ) == false )
					{
						return false;
					}
				}
			}

			// set the location of error bars
			if( this.mErrorBarGroup!=null )
			{
				if( this.mErrorBarGroup.isVisible() )
				{
					SGTuple2f[] startArray = this.mErrorBarGroup.mStartArray;
					SGTuple2f[] endArray = this.mErrorBarGroup.mEndArray;
					if( this.mErrorBarGroup.calcErrorBarLocation(
						dataSXY,
						this.mXAxis,
						this.mYAxis,
						startArray,
						endArray ) == false )
					{
						return false;
					}

					if( this.mErrorBarGroup.setLocation(
						startArray,
						endArray ) == false )
					{
						return false;
					}
				}

			}


			// set the location of tick labels
			if( this.mTickLabels!=null )
			{
				if( this.mTickLabels.isVisible() )
				{
					SGTuple2f[] pointArray = this.mTickLabels.mPointsArray;

					if( this.mTickLabels.calcTickLabelLocation(
						dataSXY, this.mXAxis, pointArray ) == false )
					{
						return false;
					}

					if( this.mTickLabels.setLocation( pointArray ) == false )
					{
						return false;
					}
				}
			}

			return true;
		}



		/**
		 * 
		 */
		protected boolean createDrawingElements()
		{

			final ArrayList groupList = this.mDrawingElementGroupList;
			for( int jj=0; jj<groupList.size(); jj++ )
			{
				final SGElementGroupSXY group = (SGElementGroupSXY)groupList.get(jj);

				// 表示状態になっているときは、グループに描画要素を作成させる
				if( group.isVisible() )
				{
					group.setLocation( this.mPointsArray );
				}
			}


			SGSXYData dataSXY = (SGSXYData)getData(this);


			// エラーバー
			if( this.mErrorBarGroup != null )
			{
				if( this.mErrorBarGroup.mVisibleFlag )
				{
					this.mErrorBarGroup.setLocation(
						this.mErrorBarGroup.mStartArray,
						this.mErrorBarGroup.mEndArray );
				}
			}

			// データ付属文字列
			if( this.mTickLabels != null )
			{
				if( this.mTickLabels.mVisibleFlag )
				{
//					this.createDataString( dataSXY );
					this.mTickLabels.setLocation(
						this.mTickLabels.mPointsArray );
				}
			}


			return true;
		}



		/**
		 * 
		 */
		private boolean addElementGroup( final SGElementGroupSXY group )
		{

			group.mGroupSet = this;


			// 描画要素の作成
			if( group.initDrawingElement( this.mPointsArray ) == false )
			{
				throw new Error();
			}


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


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


			return true;

		}



		/**
		 * 
		 */
		public Rectangle2D getTickLabelsBoundingBox( final SGData data )
		{

			if( ( data instanceof SGSXYData ) == false )
			{
				return null;
			}
			
			SGSXYData dataSXY = (SGSXYData)data;

			ArrayList rectList = new ArrayList();
			final ElementGroupTickLabelStringElement group = this.mTickLabels;
			if( group == null )
			{
				return new Rectangle2D.Float();
			}
			if( !group.isVisible() )
			{
				return new Rectangle2D.Float();
			}


			ArrayList strList = new ArrayList();
			SGDrawingElement[] elArray = group.mDrawingElementArray;
			for( int ii=0; ii<elArray.length; ii++ )
			{
				if( elArray[ii].isVisible() )
				{
					strList.add( elArray[ii] );
				}
			}

			Rectangle2D rectAll = SGUtilityJava2D.getBoundingBox(strList);
			rectList.add(rectAll);


			// 得られた矩形を結合する
			Rectangle2D uniRect = SGUtility.createUnion(rectList);

			return uniRect;
		}




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

			// bar
			final ElementGroupBar groupBar = getGroupBar( this );
			if( groupBar!=null )
			{
				if( groupBar.isVisible() )
				{
					groupBar.paintElement(g2d);
				}
			}


			// error bar
			final ElementGroupErrorBar eGroup = this.mErrorBarGroup;
			if( eGroup!=null )
			{
				if( eGroup.isVisible() )
				{
					eGroup.paintElement(g2d);
				}
			}


			// line
			final ElementGroupLine groupLine = getGroupLine( this );
			if( groupLine!=null )
			{
				if( groupLine.isVisible() )
				{
					groupLine.paintElement(g2d);
				}
			}


			// symbol
			final ElementGroupSymbol groupSymbol = getGroupSymbol( this );
			if( groupSymbol!=null )
			{
				if( groupSymbol.isVisible() )
				{
					groupSymbol.paintElement(g2d);
				}
			}


		}




		/**
		 * 
		 */
		public boolean paintDataString( final Graphics2D g2d )
		{
			final ElementGroupTickLabelStringElement groupString = this.mTickLabels;
			if( groupString != null )
			{
				if( groupString.isVisible() )
				{
					groupString.paintElement(g2d);
				}
			}

			return true;
		}



		/**
		 * 
		 */
/*		protected boolean clickDrawingElements( final MouseEvent e )
		{
			final int x = e.getX();
			final int y = e.getY();
			if( this.contains(x,y) == false )
			{
				return false;
			}

			if( (SwingUtilities.isRightMouseButton(e) )
				&& ( e.getClickCount() == 1 ) )
			{
//				final JPopupMenu menu = errBarGroup.getPopupMenu();
//				menu.show( this, e.getX(), e.getY() );
				return true;
			}
						
			if( (SwingUtilities.isLeftMouseButton(e) )
				&& ( e.getClickCount() == 2 ) )
			{
				this.showPropertyDialog();
				return true;
			}

			return true;
		}
*/



		/**
		 * 
		 */
		public boolean setPropertiesFromDialog()
		{

			final SGPropertyDialogSXYData dg
				= (SGPropertyDialogSXYData)mPropertyDialogForData;


			// 全部がチェックアウトされたら警告
			if( !dg.getLineVisible()
			&& !dg.getBarVisible()
			&& !dg.getSymbolVisible() )
			{
				JOptionPane.showMessageDialog(
					dg, MSG_NOT_HIDE_ALL_ELEMENTS );
				return false;
			}


			//
			if( this.setPropertyWithDialog_() == false )
			{
				return false;
			}

//			setAllDrawingElementsLocation();
//			repaint();

			return true;
		}


		/**
		 * 
		 */
		private boolean setPropertyWithDialog_()
		{

			final SGPropertyDialogSXYData dg
				= (SGPropertyDialogSXYData)mPropertyDialogForData;


			// データと関係付けられた軸の設定
			this.setAxisPropertyWithDialog();			


			//
			ArrayList lineList = this.getLineGroups();
			for( int ii=0; ii<lineList.size(); ii++ )
			{
				SGElementGroupLine group = (SGElementGroupLine)lineList.get(ii);
				if( dg.isTabEnabled( dg.getLinePanel() ) )
				{
					if( dg.setLineProperties(group) == false )
					{
						return false;
					}
				}
			}

			ArrayList symbolList = this.getSymbolGroups();
			for( int ii=0; ii<symbolList.size(); ii++ )
			{
				SGElementGroupSymbol group = (SGElementGroupSymbol)symbolList.get(ii);
				if( dg.isTabEnabled( dg.getSymbolPanel() ) )
				{
					if( dg.setSymbolProperties(group) == false )
					{
						return false;
					}
				}
			}

			ArrayList barList = this.getBarGroups();
			for( int ii=0; ii<barList.size(); ii++ )
			{
				SGElementGroupBar group = (SGElementGroupBar)barList.get(ii);
				if( dg.isTabEnabled( dg.getBarPanel() ) )
				{
					if( dg.setBarProperties(group) == false )
					{
						return false;
					}
				}
			}

			if( this.mErrorBarGroup!=null )
			{
				if( dg.isTabEnabled( dg.getErrorBarPanel() ) )
				{
					if( dg.setErrorBarProperties( this.mErrorBarGroup ) == false )
					{
						return false;
					}
				}
			}

			if( this.mTickLabels!=null )
			{
				if( dg.isTabEnabled( dg.getTickLabelPanel() ) )
				{
					if( dg.setTickLabelProperties( this.mTickLabels ) == false )
					{
						return false;
					}
				}
			}

			return true;
		}


		/**
		 * 
		 */
		private boolean setAxisPropertyWithDialog()
		{

			final SGPropertyDialogSXYData dg = (SGPropertyDialogSXYData)mPropertyDialogForData;

			final SGAxis bAxis = mAxisElement.getAxisInPlane( SGAxisElement.AXIS_HORIZONTAL_1 );
			final SGAxis tAxis = mAxisElement.getAxisInPlane( SGAxisElement.AXIS_HORIZONTAL_2 );
			final SGAxis lAxis = mAxisElement.getAxisInPlane( SGAxisElement.AXIS_PERPENDICULAR_1 );
			final SGAxis rAxis = mAxisElement.getAxisInPlane( SGAxisElement.AXIS_PERPENDICULAR_2 );

			if( dg.isLeftBottomSelected() )
			{
				this.mXAxis = bAxis;
				this.mYAxis = lAxis;
			}
			else if( dg.isLeftTopSelected() )
			{
				this.mXAxis = tAxis;
				this.mYAxis = lAxis;
			}
			else if( dg.isRightBottomSelected() )
			{
				this.mXAxis = bAxis;
				this.mYAxis = rAxis;
			}
			else if( dg.isRightTopSelected() )
			{
				this.mXAxis = tAxis;
				this.mYAxis = rAxis;
			}


			return true;
		}



		/**
		 * 
		 */
		public boolean showPropertyDialog()
		{

			super.showPropertyDialog();


			final SGPropertyDialogSXYData dg
				= (SGPropertyDialogSXYData)mPropertyDialogForData;

			// ダイアログにプロパティ設定
			this.setDialogProperty();


			// 現在選択されているタブの番号を取得
			final int index = dg.getTabbedPane().getSelectedIndex();
			dg.setColorButtonProperty( index );


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


			dg.setVisible(true);

			dg.removeAllPropertySettingListeners();

			return true;
		}



		/**
		 * 
		 */
		public boolean createTemporaryPropertyObject()
		{
			this.mTemporaryProperties = this.getWholeProperties();
//System.out.println(this.mTemporaryProperties);
			return true;
		}



		/**
		 * 
		 */
		public boolean readProperties( final BufferedReader br, final SGProperties prop )
			throws IOException
		{

			if( br==null || prop==null )
			{
				return false;
			}
			
			if( super.readProperties(br,prop) == false )
			{
				return false;
			}

			if( ( prop instanceof ElementGroupSetInSXYGraphProperties ) == false )
			{
				return false;
			}

			ElementGroupSetInSXYGraphProperties p = (ElementGroupSetInSXYGraphProperties)prop;

			String line = null;

			// error bar
			if( ( line = SGUtilityText.readLine(br) ) == null )
			{
				return false;
			}
			if( line.equals( SGElementGroupErrorBar.ERROR_BAR_TITLE ) )
			{
				SGProperties ebp = this.mErrorBarGroup.readProperties(br);
				if( ebp==null )
				{
					return false;
				}
				p.errorBarProperties = ebp;
			}
			else if( line.equals( PF_ERROR_BAR_EMPTY ) )
			{
				p.errorBarProperties = null;
			}
			else
			{
				return false;
			}


			// tick labels
			if( ( line = SGUtilityText.readLine(br) ) == null )
			{
				return false;
			}
			if( line.equals( SGElementGroupTickLabel.PF_TICK_LABEL_TITLE ) )
			{
				SGProperties tlp = this.mTickLabels.readProperties(br);
				if( tlp==null )
				{
					return false;
				}
				p.tickLabelsProperties = tlp;
			}
			else if( line.equals( PF_TICK_LABELS_EMPTY ) )
			{
				p.tickLabelsProperties = null;
			}
			else
			{
				return false;
			}

			return true;
		}



		/**
		 * 
		 */
		public SGProperties readProperties( final BufferedReader br )
			throws IOException
		{

			ElementGroupSetInSXYGraphProperties p = new ElementGroupSetInSXYGraphProperties();

			if( this.readProperties(br,p) == false )
			{
				return null;
			}
			
			WholeProperties wp = new WholeProperties();
			wp.ep = p;

			// group
			String line = null;
			for( int ii=0; ii<this.mDrawingElementGroupList.size(); ii++ )
			{
				if( ( line = SGUtilityText.readLine(br) ) == null ) return null;

				SGElementGroup group = (SGElementGroup)this.mDrawingElementGroupList.get(ii);
				SGProperties gp = group.readProperties(br);
				(wp.ipList).add(gp);
			}

			return wp;
		}



		/**
		 * 
		 */
		private boolean setDialogProperty()
		{
//System.out.println("*** setDialogProperty ***");

			// 軸の設定
			this.setDialogPropertyOfAxis();


			// element group
			for( int ii=0; ii<this.mDrawingElementGroupList.size(); ii++ )
			{
//System.out.println("ii="+ii);
				final SGElementGroup group
					= (SGElementGroup)this.mDrawingElementGroupList.get(ii);
				group.setDialogProperty();
			}

			// error bar
			if( this.mErrorBarGroup!=null )
			{
				this.mErrorBarGroup.setDialogProperty();
			}

			// tick label
			if( this.mTickLabels!=null )
			{
				this.mTickLabels.setDialogProperty();
			}


			//
			// タブの設定
			//

			final SGPropertyDialogSXYData dg = (SGPropertyDialogSXYData)mPropertyDialogForData;

			dg.setTabEnabled( dg.getLinePanel(), true );
			dg.setTabEnabled( dg.getSymbolPanel(), true );
			dg.setTabEnabled( dg.getBarPanel(), true );


			// error bar
//System.out.println("error bar:"+this.mErrorBarGroup);
			if( this.mErrorBarGroup!=null )
			{
				dg.setTabEnabled( dg.getErrorBarPanel(), true );
			}
			else
			{
				if( dg.getTabbedPane().getSelectedComponent().equals( dg.getErrorBarPanel() ) )
				{
					dg.getTabbedPane().setSelectedComponent( dg.getLinePanel() );
				}
				dg.setTabEnabled( dg.getErrorBarPanel(), false );
			}


			// tick label
//System.out.println("tick labels:"+this.mTickLabels);
			if( this.mTickLabels!=null )
			{
				dg.setTabEnabled( dg.getTickLabelPanel(), true );
			}
			else
			{
				if( dg.getTabbedPane().getSelectedComponent().equals( dg.getTickLabelPanel() ) )
				{
					dg.getTabbedPane().setSelectedComponent( dg.getLinePanel() );
				}
				dg.setTabEnabled( dg.getTickLabelPanel(), false );
			}


			return true;
		}



		/**
		 * 
		 */
		private boolean setDialogPropertyOfAxis()
		{

			final SGPropertyDialogSXYData dg = (SGPropertyDialogSXYData)mPropertyDialogForData;

			final int configX = mAxisElement.getConfigurationInPlane( this.mXAxis );
			final int configY = mAxisElement.getConfigurationInPlane( this.mYAxis );

			boolean flag = dg.setAxisRadioButton( configX, configY );
			if( !flag )
			{
				return false;
			}

			return true;
		}






		/**
		 * 
		 */
		public boolean writePropertyOfData( final Writer writer ) throws IOException
		{

			if( super.writePropertyOfData(writer) == false )
			{
				return false;
			}


			// 軸の配置の出力
			final int configX = mAxisElement.getConfigurationInCube( this.mXAxis );
			final int configY = mAxisElement.getConfigurationInCube( this.mYAxis );

			final String strX = mAxisElement.getConfigurationStringInPlaneByCube( configX );
			final String strY = mAxisElement.getConfigurationStringInPlaneByCube( configY );

			SGUtilityText.writePropertyLine( writer, PF_LOCATION_X_AXIS, strX );
			SGUtilityText.writePropertyLine( writer, PF_LOCATION_Y_AXIS, strY );

			writer.write("\n");


			// Properties of Error Bars
			if( this.mErrorBarGroup != null )
			{
				this.mErrorBarGroup.writePropertyOfData(writer);
			}
			else
			{
				writer.write( PF_ERROR_BAR_EMPTY );
				writer.write("\n\n");
			}


			// Properties of Data String
			if( this.mTickLabels != null )
			{
				this.mTickLabels.writePropertyOfData(writer);
			}
			else
			{
				writer.write( PF_TICK_LABELS_EMPTY );
				writer.write("\n\n");
			}


			// 各データが持つ描画要素群にプロパティを出力させる
			for( int ii=0; ii<this.mDrawingElementGroupList.size(); ii++ )
			{
				final SGElementGroup group = (SGElementGroup)this.mDrawingElementGroupList.get(ii);
				group.writePropertyOfData(writer);
			}

			writer.write("\n");


			return true;
		}




		/**
		 * 
		 */
		public SGProperties getProperties()
		{
			ElementGroupSetInSXYGraphProperties ep
				= new ElementGroupSetInSXYGraphProperties();
			if( this.getProperties(ep) == false )
			{
				return null;
			}

			return ep;
		}


		/**
		 * 
		 */
		public boolean getProperties( final SGProperties p )
		{
			if( ( p instanceof ElementGroupSetInSXYGraphProperties ) == false ) return false;

			super.getProperties(p);

			ElementGroupSetInSXYGraphProperties ep = (ElementGroupSetInSXYGraphProperties)p;

			if( this.mErrorBarGroup!=null )
			{
				ep.errorBarProperties = this.mErrorBarGroup.getProperties();
			}

			if( this.mTickLabels!=null )
			{
				ep.tickLabelsProperties = this.mTickLabels.getProperties();
			}

			return true;
		}


		/**
		 * 
		 */
		public boolean setProperties( final SGProperties p )
		{

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

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

			ElementGroupSetInSXYGraphProperties ep = (ElementGroupSetInSXYGraphProperties)p;

			if( this.mErrorBarGroup!=null )
			{
				this.mErrorBarGroup.setProperties( ep.errorBarProperties );
			}

			if( this.mTickLabels != null)
			{
				this.mTickLabels.setProperties( ep.tickLabelsProperties );
			}

			return true;

		}




		/**
		 * 
		 */
		class ElementGroupSetInSXYGraphProperties extends ElementGroupSetInGraphProperties
		{

			SGProperties errorBarProperties;
			SGProperties tickLabelsProperties;


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

				if( super.equals(obj) == false )
				{
					return false;
				} 


				ElementGroupSetInSXYGraphProperties p = (ElementGroupSetInSXYGraphProperties)obj;

				if( p.errorBarProperties == null )
				{
					if( this.errorBarProperties != null )
					{
						return false;
					}
				}
				else
				{
				
					if( p.errorBarProperties.equals( this.errorBarProperties ) == false )
					{
						return false;
					}
				}
		
		
				if( p.tickLabelsProperties == null )
				{
					if( this.tickLabelsProperties != null )
					{
						return false;
					}
				}
				else
				{
				
					if( p.tickLabelsProperties.equals( this.tickLabelsProperties ) == false )
					{
						return false;
					}
				}
		

				return true;

			}



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

				if( this.errorBarProperties!=null )
				{
					str += this.errorBarProperties.toString();
				}
				else
				{
					str += "ErrorBars_empty, ";
				}

				if( this.tickLabelsProperties!=null )
				{
					str += this.tickLabelsProperties.toString();
				}
				else
				{
					str += "TickLabels_empty, ";
				}

				str += new String("]");

				return str;
			}

		}


	}



	/**
	 *
	 */
	class ElementGroupLine extends SGElementGroupLine
	{

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


		/**
		 * 
		 */
		private boolean init()
		{
/*
			this.mVisibleFlag = SGDefaultValues.LINE_VISIBLE;
			this.mLineWidth = SGDefaultValues.LINE_WIDTH;
			final Integer n = SGDrawingElementLine.getLineTypeFromName( SGDefaultValues.LINE_TYPE );
			if( n==null )
			{
				return false;
			}
			this.mLineType = n.intValue();
			this.mColorList.add( SGDefaultValues.LINE_COLOR );
*/


			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 boolean createDrawingElement(
			final SGTuple2f[] pointArray )
		{

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

			final float gx = mGraphAreaX;
			final float gy = mGraphAreaY;
			final float gw = mGraphAreaWidth;
			final float gh = mGraphAreaHeight;
			final float mag = mMagnification;

			final int num = pointList.size();
			SGTuple2f[] pointArray = new SGTuple2f[num];
			for( int ii=0; ii<num; ii++ )
			{
				pointArray[ii] = (SGTuple2f)pointList.get(ii);
			}


			// 点がスケール内に存在するかどうかのフラグ
			final boolean[] insideFlagArray = new boolean[num];
			for( int ii=0; ii<num; ii++ )
			{
				insideFlagArray[ii] = isInsideGraphArea(pointArray[ii]);
			}


			// 連続した二つの値がスケール内に存在しない場合には除く
			final ArrayList effectivePointList = new ArrayList();
			if( num <= 2 )
			{
				for( int ii=0; ii<num; ii++ )
				{
					effectivePointList.add(pointArray[ii]);
				}
			}
			else
			{
				if( insideFlagArray[0] || insideFlagArray[1] )
				{
					effectivePointList.add( pointArray[0] );
				}

				for( int ii=1; ii<num-1; ii++ )
				{
					if( insideFlagArray[ii-1] || insideFlagArray[ii] || insideFlagArray[ii+1] )
					{
						effectivePointList.add( pointArray[ii] );
					}
				}

				if( insideFlagArray[num-2] || insideFlagArray[num-1] )
				{
					effectivePointList.add( pointArray[num-1] );
				}
			}


			super.createDrawingElement( effectivePointArray );

			return true;
		}
*/


		/**
		 * 
		 */
		public boolean paintElement( final Graphics2D g2d )
		{
			super.paintElement(g2d);


			if( this.isSelected() )
			{
				ElementGroupSetInSXYGraph groupSet
					= (ElementGroupSetInSXYGraph)this.mGroupSet;
				if( !groupSet.isSymbolVisible() && !groupSet.isBarVisible() )
				{

					for( int ii=0; ii<this.mConnectedPathList.size(); ii++ )
					{
						GeneralPath gp = (GeneralPath)this.mConnectedPathList.get(ii);

						int num=0;
						ArrayList list = new ArrayList();

						PathIterator itr
							= gp.getPathIterator( new AffineTransform() );
						final float[] array = new float[6];
						itr.currentSegment( array );
						Point2D prev = new Point2D.Float( array[0], array[1] );
						itr.next();

						while( !itr.isDone() )
						{
							itr.currentSegment( array );
							Point2D pos = new Point2D.Float( array[0], array[1] );
							pos.setLocation(
								( prev.getX() + pos.getX() )/2.0,
								( prev.getY() + pos.getY() )/2.0
							);
							prev.setLocation( array[0], array[1] );
							list.add( pos );
							itr.next();
							num++;
						}

						if( num <= MAX_NUMBER_EMPHASIS_SYMBOLS )
						{
							for( int jj=0; jj<num; jj++ )
							{
								Point2D pos = (Point2D)list.get(jj);
								drawEmphasisSymol( g2d, pos );
							}
						}
						else
						{
							int div = num/MAX_NUMBER_EMPHASIS_SYMBOLS;
							int cnt = 0;
							while( true )
							{
								Point2D pos = (Point2D)list.get(cnt);
								drawEmphasisSymol( g2d, pos );
								cnt += div;
								if( cnt >= num )
								{
									break;
								}
							}
	
						}

					}

				}

			}


			return true;
		}



		/**
		 * 
		 */
		protected boolean setDialogProperty()
		{
			final SGPropertyDialogSXYData dg = (SGPropertyDialogSXYData)mPropertyDialogForData;

			dg.setLineVisible( this.isVisible() );
			dg.setLineWidth( new Float( this.mLineWidth ) );
			dg.setLineType( new Integer( mLineType ) );
			dg.setLineColorList( this.mColorList );

			return true;
		}


		/**
		 * 
		 */
		protected ElementGroupProperties getPropertiesFromDialog()
		{
			final SGPropertyDialogSXYData dg = (SGPropertyDialogSXYData)mPropertyDialogForData;
			LineProperties p = dg.getLineProperties();
			return p;
		}


	}





	/**
	 *
	 */
	class ElementGroupBar extends SGElementGroupBar
	{

		/**
		 *
		 */
		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;
		}



		/**
		 * 
		 */
		private float getBaselineLocation( final double baselineValue )
		{
			final SGAxis axis = ((ElementGroupSetInSXYGraph)(this.mGroupSet)).getYAxis();
			return calcLocation( baselineValue, axis, false );
		}



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

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

//System.out.println("<< ElementGroupBar::setLocation >>");

			final float gx = mGraphAreaX;
			final float gy = mGraphAreaY;
			final float gw = mGraphAreaWidth;
			final float gh = mGraphAreaHeight;


			// get the location of the baseline
			final float baseline
				= this.getBaselineLocation( this.mBaselineValue );

//System.out.println("baseline="+baseline);

			boolean baselineFlag = true;
			if( Float.isInfinite(baseline) || Float.isNaN(baseline) )
			{
				baselineFlag = false;
			}

//System.out.println("flag="+flag);

			// set the bounds of drawing elements
			final float w = this.mMagnification*this.mRectangleWidth;

			for( int ii=0; ii<this.mDrawingElementArray.length; ii++ )
			{
//System.out.println("ii="+ii);

				final SGDrawingElementBar2D bar
					= (SGDrawingElementBar2D)this.mDrawingElementArray[ii];

				float bLine = baseline;

				SGTuple2f point = pointArray[ii];
				float posY = point.y;
				if( Float.isInfinite( posY ) || Float.isNaN( posY ) )
				{

					if( baselineFlag )
					{
						posY = baseline;
						bLine = gy + gh;
					}
					else
					{
						bar.setVisible( false );
					}

					continue;
				}

				if( !baselineFlag )
				{
					bLine = gy + gh;
				}

				final float x = point.x-0.5f*w;
				float y = 0.0f;
				float h = 0.0f;

//System.out.println(point.y+"  "+baseline);

				if( posY <= bLine )
				{
					y = posY;
					h = bLine - posY;
				}
				else
				{
					y = bLine;
					h = posY - bLine;
				}

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

				bar.setVisible(true);
				bar.setBounds( x, y, w, h );

//System.out.println(bar.getElementBounds());

			}

//System.out.println();

			return true;
		}



		/**
		 * 
		 */
		public boolean paintElement( final Graphics2D g2d )
		{
			super.paintElement(g2d);

			if( this.isSelected() )
			{

				final int num = this.mDrawingElementArray.length;
		
				if( num <= MAX_NUMBER_EMPHASIS_SYMBOLS )
				{
					for( int ii=0; ii<num; ii++ )
					{
						SGDrawingElementBar2D bar
							= (SGDrawingElementBar2D)this.mDrawingElementArray[ii];
						emphasisBar( bar, g2d );
					}
				}
				else
				{
					int div = num/MAX_NUMBER_EMPHASIS_SYMBOLS;
					int cnt = 0;
					while( true )
					{
						SGDrawingElementBar2D bar
							= (SGDrawingElementBar2D)this.mDrawingElementArray[cnt];
						emphasisBar( bar, g2d );
						cnt += div;
						if( cnt >= num )
						{
							break;
						}
					}
				}
				
			}


			return true;
		}



		/**
		 * 
		 * @param g2d
		 * @param symbol
		 * @return
		 */
		private boolean emphasisBar(
			final SGDrawingElementBar2D bar,
			final Graphics2D g2d )
		{
			Rectangle2D rect = bar.getElementBounds();
			Point2D pos00 = new Point2D.Float(
				(float)rect.getX(), (float)rect.getY() );
			Point2D pos10 = new Point2D.Float(
				(float)( rect.getX() + rect.getWidth() ), (float)rect.getY() );
			Point2D pos01 = new Point2D.Float(
				(float)rect.getX(), (float)( rect.getY() + rect.getHeight() ) );
			Point2D pos11 = new Point2D.Float(
				(float)( rect.getX() + rect.getWidth() ),
				(float)( rect.getY() + rect.getHeight() ) );
			drawEmphasisSymol( g2d, pos00 );
			drawEmphasisSymol( g2d, pos10 );
			drawEmphasisSymol( g2d, pos01 );
			drawEmphasisSymol( g2d, pos11 );
			return true;
		}




		/**
		 * 
		 */
		protected boolean setDialogProperty()
		{

			final SGPropertyDialogSXYData dg = (SGPropertyDialogSXYData)mPropertyDialogForData;

			dg.setBarVisible( this.isVisible() );
//			dg.setBarTabEnabled( this.isVisible() );
			dg.setBarWidth( new Float( this.mRectangleWidth*SGIConstants.CM_POINT_RATIO ) );
			dg.setBarEdgeLineWidth(	new Float( this.mEdgeLineWidth ) );
			dg.setBarBaselineValue( new Double( this.mBaselineValue ) );
			dg.setBarInnerColorList( this.mColorList );
			dg.setBarEdgeLineColor( this.mEdgeLineColor );

			return true;

		}


		/**
		 * 
		 */
		protected ElementGroupProperties getPropertiesFromDialog()
		{
			final SGPropertyDialogSXYData dg = (SGPropertyDialogSXYData)mPropertyDialogForData;

			BarProperties p = dg.getBarProperties();
			return p;
		}


	}





	/**
	 *
	 */
	class ElementGroupSymbol extends SGElementGroupSymbol
	{

		/**
		 *
		 */
		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;
		}



		/**
		 * 
		 */
		private boolean drawRectangle( final Shape shape, final Graphics2D g2d )
		{

			final Rectangle2D rect = shape.getBounds2D();

			g2d.setPaint(Color.black);
			g2d.setStroke( new BasicStroke(1) );


			final int x = (int)rect.getX();
			final int y = (int)rect.getY();
			final int w = (int)rect.getWidth();
			final int h = (int)rect.getHeight();
			
			g2d.drawRect( x,y,w,h );

			return true;

		}




		/**
		 * 
		 */
		public boolean setLocation(
			final SGTuple2f[] pointArray )
		{
			// nothing to do
			return true;
		}


		/**
		 * 
		 */
/*		public boolean createDrawingElement(
			final ArrayList pointList )
		{

			final float gx = mGraphAreaX;
			final float gy = mGraphAreaY;
			final float gw = mGraphAreaWidth;
			final float gh = mGraphAreaHeight;
			final float mag = mMagnification;

			final int num = pointList.size();
			SGTuple2f[] pointArray = new SGTuple2f[num];
			for( int ii=0; ii<num; ii++ )
			{
				pointArray[ii] = (SGTuple2f)pointList.get(ii);
			}


			// 点がスケール内に存在するかどうかのフラグ
			final boolean[] insideFlagArray = new boolean[num];
			for( int ii=0; ii<num; ii++ )
			{
				insideFlagArray[ii] = isInsideGraphArea( pointArray[ii] );
			}


			// 点がグラフ領域内に存在しない場合には除く
			final ArrayList effectivePointList = new ArrayList();
			for( int ii=0; ii<num; ii++ )
			{
				if( insideFlagArray[ii] )
				{
					effectivePointList.add( pointArray[ii] );
				}
			}


			super.createDrawingElement( effectivePointList );


			return true;
		}
*/


		/**
		 * 
		 */
		public boolean paintElement( final Graphics2D g2d )
		{
			super.paintElement(g2d);

			if( this.isSelected() )
			{
				ElementGroupSetInSXYGraph groupSet
					= (ElementGroupSetInSXYGraph)this.mGroupSet;
				if( !groupSet.isBarVisible() )
				{
					final int num = this.mDrawingElementArray.length;

					if( num <= MAX_NUMBER_EMPHASIS_SYMBOLS )
					{
						for( int ii=0; ii<num; ii++ )
						{
							SGDrawingElementSymbol2D symbol
								= (SGDrawingElementSymbol2D)this.mDrawingElementArray[ii];
							emphasisSymbol( symbol, g2d );
						}
					}
					else
					{
						int div = num/MAX_NUMBER_EMPHASIS_SYMBOLS;
						int cnt = 0;
						while( true )
						{
							SGDrawingElementSymbol2D symbol
								= (SGDrawingElementSymbol2D)this.mDrawingElementArray[cnt];
							emphasisSymbol( symbol, g2d );
							cnt += div;
							if( cnt >= num )
							{
								break;
							}
						}
					}
				}

			}


			return true;
		}



		/**
		 * 
		 * @param g2d
		 * @param symbol
		 * @return
		 */
		private boolean emphasisSymbol(
			final SGDrawingElementSymbol2D symbol,
			final Graphics2D g2d )
		{
			Rectangle2D rect = symbol.getElementBounds();
			Point2D pos00 = new Point2D.Float(
				(float)rect.getX(), (float)rect.getY() );
			Point2D pos10 = new Point2D.Float(
				(float)( rect.getX() + rect.getWidth() ), (float)rect.getY() );
			Point2D pos01 = new Point2D.Float(
				(float)rect.getX(), (float)( rect.getY() + rect.getHeight() ) );
			Point2D pos11 = new Point2D.Float(
				(float)( rect.getX() + rect.getWidth() ),
				(float)( rect.getY() + rect.getHeight() ) );
			drawEmphasisSymol( g2d, pos00 );
			drawEmphasisSymol( g2d, pos10 );
			drawEmphasisSymol( g2d, pos01 );
			drawEmphasisSymol( g2d, pos11 );
			return true;
		}



		/**
		 * 
		 */
		protected boolean setDialogProperty()
		{

			final SGPropertyDialogSXYData dg = (SGPropertyDialogSXYData)mPropertyDialogForData;

			dg.setSymbolVisible( this.isVisible() );
			dg.setSymbolType( new Integer( this.mSymbolType ) );
			dg.setSymbolSize( new Float( this.mSymbolSize*SGIConstants.CM_POINT_RATIO ) );
			dg.setSymbolLineWidth( new Float( this.mLineWidth ) );
			dg.setSymbolColorList( this.mColorList );
			dg.setSymbolLineColor( this.mLineColor );

			return true;
		}



		/**
		 * 
		 */
		protected ElementGroupProperties getPropertiesFromDialog()
		{
			final SGPropertyDialogSXYData dg = (SGPropertyDialogSXYData)mPropertyDialogForData;
			SymbolProperties p = dg.getSymbolProperties();
			return p;
		}

	}




	/**
	 *
	 */
	class ElementGroupErrorBar extends SGElementGroupErrorBar
	{

		protected SGTuple2f[] mStartArray = null;
		
		
		protected SGTuple2f[] mEndArray = null;



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



		/**
		 * 
		 */
		private boolean init()
		{
			this.setVisible( SGDefaultValues.ERROR_BAR_VISIBLE );

			this.setLineWidth( SGDefaultValues.ERROR_BAR_LINE_WIDTH );
			this.setLineType( SGDrawingElementLine.LINE_TYPE_SOLID );

			this.setHeadSize( SGDefaultValues.ERROR_BAR_SYMBOL_SIZE );
			Integer n = SGDrawingElementSymbol.getSymbolTypeFromName( SGDefaultValues.ERROR_BAR_SYMBOL_TYPE );
			if( n==null )
			{
				return false;
			}
			this.setStartHeadType( n.intValue() );
			this.setEndHeadType( n.intValue() );
			this.setHeadEdgeLineWidth( SGDefaultValues.ERROR_BAR_LINE_WIDTH );

			Integer style = getErrorBarStyleFromName( SGDefaultValues.ERROR_BAR_STYLE );
			if( style==null )
			{
				return false;
			}
			this.mErrorBarStyle = style.intValue();

			this.setColor( SGDefaultValues.ERROR_BAR_COLOR );

			return true;
		}



		/**
		 * 
		 */
		private boolean calcErrorBarLocation(
			final SGSXYData dataSXY, final SGAxis axisX, final SGAxis axisY,
			final SGTuple2f[] startPointArray, final SGTuple2f[] endPointArray )
		{

			final SGTuple2d[] errorArray = dataSXY.getErrorArray();
			if( errorArray == null )
			{
				return false;
			}
			final SGTuple2d[] valueArray = dataSXY.getValueArray();
			final int num = valueArray.length;
			final SGTuple2d[] lowerArray = new SGTuple2d[num];
			final double[] lengthArray = new double[num];
			final double[] angleArray = new double[num];

			for( int ii=0; ii<num; ii++ )
			{
				if( this.mErrorBarStyle == ERROR_BAR_FULL )
				{
					lowerArray[ii] = new SGTuple2d(
						valueArray[ii].x, valueArray[ii].y + errorArray[ii].x
					);
					lengthArray[ii] = errorArray[ii].y - errorArray[ii].x;
				}
				else if( this.mErrorBarStyle == ERROR_BAR_UPPER_ONLY )
				{
					lowerArray[ii] = new SGTuple2d(
						valueArray[ii].x, valueArray[ii].y
					);
					lengthArray[ii] = errorArray[ii].y;
				}
				else if( this.mErrorBarStyle == ERROR_BAR_LOWER_ONLY )
				{
					lowerArray[ii] = new SGTuple2d(
						valueArray[ii].x, valueArray[ii].y + errorArray[ii].x
					);
					lengthArray[ii] = Math.abs(errorArray[ii].x);
				}
			
				angleArray[ii] = Math.PI/2.0;
			}

			final SGVXYData errorData = new SGVXYData( lowerArray, lengthArray, angleArray );

			calcLocationOfVXYData(
				errorData.getStartArray(), errorData.getEndArray(),
				axisX, axisY, startPointArray, endPointArray
			);

			return true;
		}




		/**
		 * 
		 */
		protected boolean setDialogProperty()
		{

			final SGPropertyDialogSXYData dg = (SGPropertyDialogSXYData)mPropertyDialogForData;

			dg.setErrorBarVisible( this.isVisible() );

			String typeName = null;
			if( this.mErrorBarStyle==ERROR_BAR_FULL
				|| this.mErrorBarStyle==ERROR_BAR_LOWER_ONLY )
			{
				typeName = getSymbolTypeName( this.mStartHeadType );
			}
			else if( this.mErrorBarStyle==ERROR_BAR_UPPER_ONLY )
			{
				typeName = getSymbolTypeName( this.mEndHeadType );
			}
			dg.setErrorBarType(typeName);

			dg.setErrorBarSymbolSize( new Float( this.mHeadSize*SGIConstants.CM_POINT_RATIO ) );
			dg.setErrorBarLineWidth( new Float( this.mLineWidth ) );
			dg.setErrorBarColorList( this.mColorList );
			dg.setErrorBarStyle( new Integer( this.mErrorBarStyle ) );

			return true;

		}



		/**
		 * 
		 */
		protected ElementGroupProperties getPropertiesFromDialog()
		{
			final SGPropertyDialogSXYData dg = (SGPropertyDialogSXYData)mPropertyDialogForData;

			ErrorBarProperties p = dg.getErrorBarProperties();

			// not from a dialog
//			p.setLineType( this.mLineType );
//			p.setHeadOpenAngle( this.mHeadOpenAngle );
//			p.setHeadCloseAngle( this.mHeadCloseAngle );

			return p;
		}


	}






	/**
	 * 
	 */
	class ElementGroupTickLabelStringElement extends SGElementGroupTickLabel
	{


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


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


		/**
		 * 
		 */
		private boolean init()
		{
			this.setVisible( SGDefaultValues.TICK_LABEL_VISIBLE );

//			this.setFontFamilyName( SGDefaultValues.TICK_LABEL_FONT_FAMILY_NAME );
//			this.setFontSize( SGDefaultValues.TICK_LABEL_FONT_SIZE );
//			this.setFontStyle( SGUtilityText.getFontStyle( SGDefaultValues.TICK_LABEL_FONT_STYLE ) );

			this.setFont(
				SGDefaultValues.TICK_LABEL_FONT_FAMILY_NAME,
				SGUtilityText.getFontStyle( SGDefaultValues.TICK_LABEL_FONT_STYLE ),
				SGDefaultValues.TICK_LABEL_FONT_SIZE
			);

			final Float angle = SGElementGroupTickLabel.getTickLabelAngleFromName( SGDefaultValues.TICK_LABEL_ANGLE );
			if( angle==null )
			{
				return false;
			}
			this.setAngle( angle.floatValue() );
			this.setColor( SGDefaultValues.TICK_LABEL_COLOR );

//System.out.println("*** "+this.mColorList);

			return true;
		}


		/**
		 * 
		 */
		private boolean drawStringBounds( final SGDrawingElementString2DExtended element, final Graphics2D g2d )
		{

			final float strRectLineWidth = 1.0f;
			final Color strRectLineColor = Color.BLACK;
			g2d.setPaint(strRectLineColor);
			g2d.setStroke( new BasicStroke( strRectLineWidth ) );
			final Rectangle2D rect = element.getElementBounds();
			g2d.drawRect(
				(int)rect.getX(),
				(int)rect.getY(),
				(int)rect.getWidth(),
				(int)rect.getHeight()
			);

			return true;

		}



		/**
		 * 
		 */
		protected ElementGroupProperties getPropertiesFromDialog()
		{

			final SGPropertyDialogSXYData dg = (SGPropertyDialogSXYData)mPropertyDialogForData;

			StringProperties p = new StringProperties();

			p.setVisible( dg.getTickLabelVisible() );
			p.setColorList( dg.getTickLabelColorList() );
			p.setFontFamilyName( dg.getTickLabelFontFamilyName() );


			final Number fontSize = dg.getTickLabelFontSize();
			if( fontSize==null )
			{
				SGUtility.showIllegalInputErrorMessageDialog( mDialogOwner );
				return null;
			}
			p.setFontSize( fontSize.floatValue() );

			final Integer fontStyle = dg.getTickLabelFontStyle();
			if( fontStyle==null )
			{
				SGUtility.showIllegalInputErrorMessageDialog( mDialogOwner );
				return null;
			}
			p.setFontStyle( fontStyle.intValue() );

			final Number angle = dg.getTickLabelAngle();
			if( angle==null )
			{
				SGUtility.showIllegalInputErrorMessageDialog( mDialogOwner );
				return null;
			}
			p.setAngle( angle.floatValue() );

			return p;
		}


		/**
		 * 
		 */
		protected boolean setDialogProperty()
		{
			final SGPropertyDialogSXYData dg = (SGPropertyDialogSXYData)mPropertyDialogForData;

			dg.setTickLabelVisible( this.isVisible() );
			dg.setTickLabelFontFamilyName( this.mFontFamilyName );
			dg.setTickLabelFontSize( new Float( this.mFontSize ) );
			dg.setTickLabelFontStyle( new Integer( this.mFontStyle ) );
			dg.setTickLabelAngle( new Float( this.mAngle ) );
			dg.setTickLabelColorList( this.mColorList );

			return true;
		}



		/**
		 * 
		 * @return
		 */
		protected boolean initDrawingElement( final int num )
		{
			SGDrawingElementString[] array = new TickLabelStringElement[num];
			for( int ii=0; ii<num; ii++ )
			{
				array[ii] = new TickLabelStringElement();
			}
			this.mDrawingElementArray = array;
			return true;
		}




		/**
		 * 
		 */
		private boolean calcTickLabelLocation(
			final SGSXYData dataSXY,
			final SGAxis axisX,
			final SGTuple2f[] pointArray )
		{
//System.out.println("<< calcTickLabelLocation >>");

			final float gx = mGraphAreaX;
			final float gy = mGraphAreaY;
			final float gw = mGraphAreaWidth;
			final float gh = mGraphAreaHeight;

			final int config = mAxisElement.getConfigurationInPlane(axisX);

			final float angle = this.getAngle();
			final float space = mAxisElement.getSpaceAxisLineAndNumber();


			final SGTuple2d[] valueArray = dataSXY.getValueArray();
			for( int ii=0; ii<valueArray.length; ii++ )
			{
				final TickLabelStringElement el
					= (TickLabelStringElement)this.mDrawingElementArray[ii];
/*
				if( axisX.insideRange( valueArray[ii].x ) == false )
				{
					el.setVisible(false);
					continue;
				}
				else
				{
					el.setVisible(true);
				}
*/

				final float xCenter
					= (float)calcLocation( valueArray[ii].x, axisX, true );

				Rectangle2D rect = el.getElementBounds();
				final float w = (float)rect.getWidth();
				final float h = (float)rect.getHeight();

				Rectangle2D rect_ = el.getStringRect();
				final float w_ = (float)rect_.getWidth();
				final float h_ = (float)rect_.getHeight();

				float x = 0.0f;
				float y = 0.0f;
				float yDefault = 0.0f;

				// x-coordinates
				if( angle == SGElementGroupTickLabel.ANGLE_HORIZONTAL )
				{
					x = xCenter - 0.50f*w;
				}
				else if( angle == SGElementGroupTickLabel.ANGLE_INCLINED )
				{
					if( config == SGAxisElement.AXIS_HORIZONTAL_1 )
					{
						x = xCenter - w_*( (float)Math.cos(angle) );
					}
					else if( config == SGAxisElement.AXIS_HORIZONTAL_2 )
					{
						x = xCenter - h_*( (float)Math.sin(angle) );
					}
					else
					{
						throw new Error();
					}
				}
				else
				{
					throw new Error();
				}


				// y-cooordinates
				if( config == SGAxisElement.AXIS_HORIZONTAL_1 )
				{
					yDefault = (float)( gy + gh + space );
				}
				else if( config == SGAxisElement.AXIS_HORIZONTAL_2 )
				{
					yDefault = (float)( gy - space - h );
				}
				else
				{
					throw new Error();
				}

				el.setLocation(	x, yDefault );
				final float yy = (float)el.getElementBounds().getY();
				y = yDefault + ( yDefault - yy );


				// set to variable
				pointArray[ii].setValues( x, y );

//System.out.println(ii+"  "+pointArray[ii]);
			}

//System.out.println();

			return true;

		}



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

			ElementGroupSetInSXYGraph groupSet
				= (ElementGroupSetInSXYGraph)this.mGroupSet;
			SGAxis axisX = groupSet.mXAxis;
			SGSXYData dataSXY = (SGSXYData)getData(groupSet);
			final SGTuple2d[] valueArray = dataSXY.getValueArray();

			//
			for( int ii=0; ii<pointArray.length; ii++ )
			{
				TickLabelStringElement el
					= (TickLabelStringElement)this.mDrawingElementArray[ii];
				el.setVisible( axisX.insideRange( valueArray[ii].x ) );
			}

			return true;
		}




		/**
		 * 
		 */
/*		protected boolean createDrawingElements( final SGSXYData data )
		{

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

//			this.mDrawingElementList.clear();


			final double gx = mGraphAreaX;
			final double gy = mGraphAreaY;
			final double gw = mGraphAreaWidth;
			final double gh = mGraphAreaHeight;


			final ElementGroupSetInSXYGraph groupSet
				= (ElementGroupSetInSXYGraph)this.mGroupSet;
			final SGAxis axis = groupSet.mXAxis;
			final double min = axis.getRange().x;
			final double max = axis.getRange().y;

			final int config = mAxisElement.getConfigurationInPlane(axis);

			final SGTuple2d[] valueArray = data.getValueArray();
			final String[] strArray = data.getStringArray();
			final ArrayList valueList = new ArrayList();
			final ArrayList strList = new ArrayList();
			for( int ii=0; ii<valueArray.length; ii++ )
			{
				final double x = valueArray[ii].x;
				if( min<x && x<max )
				{				
					valueList.add( new Double(x) );
					strList.add( strArray[ii] );
				}
			}

			final double[] xArray = new double[valueList.size()];
			final String[] strArrayNew = new String[strList.size()];
			for( int jj=0; jj<xArray.length; jj++ )
			{
				final double x = ((Double)valueList.get(jj)).doubleValue();
				xArray[jj] = calcLocation( x, axis, true );
				strArrayNew[jj] = (String)strList.get(jj);
			}

			final String familyName = this.getFontFamilyName();
			final int fontStyle = this.getFontStyle();
			final float fontSize = this.getFontSize();
			final ArrayList colorList = this.getColorList();
			final float angle = this.getAngle();
			final float space = this.mMagnification*mAxisElement.getSpaceAxisLineAndNumber();
			if( strArray!=null )
			{
				for( int jj=0; jj<xArray.length; jj++ )
				{
					final TickLabelStringElement el = new TickLabelStringElement(
						strArrayNew[jj], fontStyle, fontSize );
					el.setMagnification( mMagnification );
					el.setFontFamilyName( familyName );
					el.setFontStyle( fontStyle );
					el.setColorList( colorList );
					el.setAngle( angle );
					Rectangle2D rect = el.getElementBounds();
					final float w = (float)rect.getWidth();
					final float h = (float)rect.getHeight();

					Rectangle2D rect_ = el.getStringRect();
					final float w_ = (float)rect_.getWidth();
					final float h_ = (float)rect_.getHeight();

					float x = 0.0f;
					float y = 0.0f;
					float yDefault = 0.0f;


					// x-coordinates
					if( angle == SGElementGroupTickLabel.ANGLE_HORIZONTAL )
					{
						x = (float)xArray[jj] - 0.50f*w;
					}
					else if( angle == SGElementGroupTickLabel.ANGLE_INCLINED )
					{
						if( config == SGAxisElement.AXIS_HORIZONTAL_1 )
						{
							x = (float)xArray[jj] - w_*( (float)Math.cos(angle) );
						}
						else if( config == SGAxisElement.AXIS_HORIZONTAL_2 )
						{
							x = (float)xArray[jj] - h_*( (float)Math.sin(angle) );
						}
						else
						{
							throw new Error();
						}
					}
					else
					{
						throw new Error();
					}


					// y-cooordinates
					if( config == SGAxisElement.AXIS_HORIZONTAL_1 )
					{
						yDefault = (float)( gy + gh + space );
					}
					else if( config == SGAxisElement.AXIS_HORIZONTAL_2 )
					{
						yDefault = (float)( gy - space - h );
					}
					else
					{
						throw new Error();
					}

					el.setLocation(	x, yDefault );
					final float yy = (float)el.getElementBounds().getY();
					y = yDefault + ( yDefault - yy );


					// set the location
					el.setLocation(	x, y );


					// add to the list
//					this.mDrawingElementList.add(el);

				}

			}


			return true;

		}
*/


		/**
		 * 
		 */
		public boolean paintElement( final Graphics2D g2d )
		{
			super.paintElement(g2d);
/*
			for( int ii=0; ii<this.mDrawingElementList.size(); ii++ )
			{
				SGDrawingElementString2D el = (SGDrawingElementString2D)this.mDrawingElementList.get(ii);
				this.drawStringBounds(el,g2d);
			}
*/
			return true;
		}




	}




	/**
	 * 
	 */
	public static class TickLabelStringElement extends SGDrawingElementString2DExtended
	{

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

	}



}

