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

import java.util.*;
import java.io.*;
import java.awt.*;
import java.awt.font.*;
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;
		}


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


		// get axes list
		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 );
		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.createGroupSet( (SGSXYData)data, axisX, axisY );
		}
		else if( data instanceof SGSXYMultipleData )
		{
			groupSet = this.createMultipleGroupSet( (SGSXYMultipleData)data, axisX, axisY );
		}
		else
		{
			return false;
		}

		this.mGroupSetList.add( groupSet );

		repaint();

		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();

/*
System.out.println("length="+yArray.length);
for( int ii=0; ii<xArray.length; ii++ )
{
	System.out.println(ii+"  "+xArray[ii]+"  "+yArray[0][ii]);
}
System.out.println();
*/

		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.createPointList(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.addPropertiesHistory();


			groupSet.mElementGroupSetList.add(gs);
		}


		groupSet.addPropertiesHistory();

//System.out.println();

		return groupSet;

	}



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

		//
		// 新規データを作成
		//

		final ElementGroupSetInSXYGraph groupSet
			= new ElementGroupSetInSXYGraph();


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


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


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


		//
		// 新規描画要素の作成
		//

		groupSet.createPointList(data);

		groupSet.addDrawingElementGroup( SGElementGroup.POLYLINE_GROUP );
		groupSet.addDrawingElementGroup( SGElementGroup.SYMBOL_GROUP );
		groupSet.addDrawingElementGroup( SGElementGroup.RECTANGLE_GROUP );


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

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



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

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


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

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


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


		//
		groupSet.addPropertiesHistory();


		return groupSet;		
	}





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

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

		return true;
	}




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

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

		final ArrayList startRatioList = new ArrayList();
		final ArrayList endRatioList = new ArrayList();

		groupSet.mErrorBarGroup.calcErrorBarRatio(
			dataSXY, groupSet.mXAxis, groupSet.mYAxis,
			startRatioList, endRatioList );
		eGroup.createDrawingElement( startRatioList, endRatioList );

		return true;
	}



	/**
	 * 
	 */
	protected boolean synchronizeToLegendElement( final SGILegendElement lElement )
	{
		super.synchronizeToLegendElement(lElement);

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


		for( int ii=0; ii<mDataList.size(); ii++ )
		{
			final ElementGroupSetInGraph groupSet
				= (ElementGroupSetInGraph)this.mGroupSetList.get(ii);
			final ArrayList groupList = groupSet.mDrawingElementGroupList;
			groupList.clear();

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

			// name of the data
			final String name = lElement.getDataName(data);
			groupSet.setName(name);

			// visible
			groupSet.setVisible( lElement.isDataVisible(data) );


			//
			((IElementGroupSetInSXYGraph)groupSet).createPointList(data);

			// SGElementGroupオブジェクトの作成と追加
			final ArrayList dElementList = lElement.getDrawingElementList(data);
			for( int jj=0; jj<dElementList.size(); jj++ )
			{
				final SGDrawingElement dElement = (SGDrawingElement)dElementList.get(jj);
				groupSet.addDrawingElementGroup(dElement);
			}


			// list of visible flag
			final ArrayList bList = lElement.getVisibleFlagList(data);
//System.out.println(bList);
			final ArrayList groupList_ = groupSet.mDrawingElementGroupList;
			for( int jj=0; jj<groupList_.size(); jj++ )
			{
				final SGElementGroup group = (SGElementGroup)groupList_.get(jj);
				final Boolean b = (Boolean)bList.get(jj);
				group.setVisible(b.booleanValue());
			}


		}

		this.createAllDrawingElements();


		return flag;
	}



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

		super.paintGraphics2D(g2d);


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


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


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


		// グラフの描画
		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 int x, final int y, final int w, final int h, final float ratio )
	{

		super.onZoomed(x,y,w,h,ratio);

		for( int ii=0; ii<this.mGroupSetList.size(); ii++ )
		{
			final ElementGroupSetInGraph groupSet = (ElementGroupSetInGraph)this.mGroupSetList.get(ii);
			groupSet.zoom(w,h,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;

	}




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

		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).createPointList(data) == false )
			{
				return false;
			}

			// create drawing elements
			if( groupSet.createDrawingElements() == false )
			{
				return false;
			}

		}


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


		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);
//System.out.println(groupSet);
		if( groupSet==null )
		{
			return false;
		}


		//
		this.mGroupSetList.add( groupSet );


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

//System.out.println("$$$$$$$$$$$$$$$$$ "+this.mGroupSetList);

		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 = SGConstants.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_);
		}
		else if( data instanceof SGSXYSamplingData )
		{
			SGSXYSamplingData data_ = (SGSXYSamplingData)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==SGConstants.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 SGConstants.PROPERTY_FILE_INCORRECT;
			}

			gsArray[ii].createPointList(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 SGConstants.PROPERTY_FILE_INCORRECT;
			}

			gsArray[ii].addPropertiesHistory();

			gsList.add(gsArray[ii]);
		}
		

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

		groupSet.addPropertiesHistory();

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


		return SGConstants.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 SGConstants.PROPERTY_FILE_INCORRECT;
		}
		String name = SGUtilityText.getStringPropertyFromLine(line,SGIGraphElement.PF_DATA_NAME);
		if( name == null )
		{
			return SGConstants.PROPERTY_FILE_INCORRECT;
		}
//System.out.println(name);


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


		// configuration of Y-axis
		if( ( line = SGUtilityText.readLine(br) ) == null )
		{
			return SGConstants.PROPERTY_FILE_INCORRECT;
		}
		String strConfigY = SGUtilityText.getPropertyFromLine(line,SGIGraphElement.PF_LOCATION_Y_AXIS);
		if( strConfigY==null )
		{
			return SGConstants.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 );

//System.out.println(groupSet.mXAxis);
//System.out.println(groupSet.mYAxis);


		// error bar
		if( ( line = SGUtilityText.readLine(br) ) == null )
		{
			return SGConstants.PROPERTY_FILE_INCORRECT;
		}
//System.out.println(line);
		if( line.equals( SGElementGroupErrorBar.ERROR_BAR_TITLE ) )
		{
			ElementGroupErrorBar group = new ElementGroupErrorBar();
			group.readProperty(br);

			// 読み込まれたデータがエラーバー情報を持っているとは限らない！
			if( data.getErrorArray() != null )
			{
				group.setMagnification( this.mMagnification );
				groupSet.mErrorBarGroup = group;
				group.mGroupSet = groupSet;
			}
		}
		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 SGConstants.PROPERTY_FILE_INCORRECT;
		}
//System.out.println(line);
		if( line.equals( SGElementGroupTickLabel.PF_TICK_LABEL_TITLE ) )
		{
			ElementGroupTickLabelStringElement group = new ElementGroupTickLabelStringElement();
			group.readProperty(br);

			// 読み込まれたデータがデータ文字列情報を持っているとは限らない！
			if( data.getStringArray() != null )
			{
				group.setMagnification( this.mMagnification );
				groupSet.mTickLabels = group;
				group.mGroupSet = groupSet;
			}
		}
		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 )
			{
//System.out.println(line);
				break;
			}

			if( line.equals( SGElementGroupLine.PF_LINE_TITLE ) )
			{
				group = new ElementGroupLine();
			}
			else if( line.equals( SGElementGroupSymbol.PF_SYMBOL_TITLE ) )
			{
				group = new ElementGroupSymbol();
			}
			else if( line.equals( SGElementGroupBar.BAR_TITLE ) )
			{
				group = new ElementGroupBar();
			}
			else
			{
				br.reset();
				break;
			}


			group.mGroupSet = groupSet;
			groupSet.mDrawingElementGroupList.add( group );
			group.setMagnification( this.mMagnification );

			group.readProperty(br);


			br.mark(256);

		}


//System.out.println("*** return true ***");
//System.out.println(this.mTimingElementGroupSetList);


		return SGConstants.SUCCESSFUL_COMPLETION;

	}




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

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

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

	}




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

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



		/**
		 * 
		 */
		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 createPointList( final SGData data )
		{
//System.out.println("<< createPointList >>");

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

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

			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 contains( final int x, final int y )
		{
			for( int ii=0; ii<this.mElementGroupSetList.size(); ii++ )
			{
				SGElementGroupSet groupSet = (SGElementGroupSet)this.mElementGroupSetList.get(ii);
				if( groupSet.contains(x,y) )
				{
					return true;
				}
			}
			return false;
		}


		/**
		 * 
		 */
		public void paintGraphics2D( final Graphics2D g2d )
		{
			for( int ii=0; ii<this.mElementGroupSetList.size(); ii++ )
			{
				ElementGroupSetInGraph groupSet
					= (ElementGroupSetInGraph)this.mElementGroupSetList.get(ii);
				groupSet.paintGraphics2D(g2d);
			}
		}



		/**
		 * 
		 */
		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.show();

			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.createPopupMenu();
		}


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


			final String[] commandArray = {
				"Dialog"
			};


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

			return true;
		}



		/**
		 * 
		 */
		public boolean contains( final int x, final int y )
		{
			if( super.contains(x,y) )
			{
				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( final int w, final int h, final float ratio )
		{
			super.zoom(w,h,ratio);

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

			// tick labels
			if( this.mTickLabels != null )
			{
				this.mTickLabels.zoom(w,h,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;
			}

			group.setMagnification(this.mMagnification);

			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 ArrayList mPointsList = null;



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

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

			SGSXYData dataSXY = (SGSXYData)data;

			this.mPointsList = new ArrayList();
			boolean flag = calcLocationOfSXYData(
				dataSXY.getValueArray(),
				this.mXAxis,
				this.mYAxis,
				this.mPointsList
			);

			if( !flag )
			{
				return false;
			}

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

			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.createDrawingElement( this.mPointsList );
				}
			}


			SGSXYData dataSXY = (SGSXYData)getData(this);


			// エラーバー
//System.out.println("エラーバーの作成");
			if( this.mErrorBarGroup != null )
			{
				if( this.mErrorBarGroup.mVisibleFlag )
				{
					final ArrayList startRatioList = new ArrayList();
					final ArrayList endRatioList = new ArrayList();
					this.mErrorBarGroup.calcErrorBarRatio(
						dataSXY,
						this.mXAxis,
						this.mYAxis,
						startRatioList,
						endRatioList );
						this.mErrorBarGroup.createDrawingElement(
							startRatioList, endRatioList );
				}
			}

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


			return true;
		}



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

			group.mGroupSet = this;


			// 描画要素の作成
			if( mPointsList == null )
			{
				throw new Error();
			}
			group.createDrawingElement(mPointsList);


			// 倍率
			group.setMagnification( mMagnification );


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


			return true;

		}



		/**
		 * 
		 */
		private boolean createDataString( final SGSXYData data )
		{

			this.mTickLabels.createDrawingElements(data);

			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();
			}

			if( this.createDataString(dataSXY) == false )
			{
				return null;
			} 

			final ArrayList strList = group.mDrawingElementList;
			Rectangle2D rectAll = SGUtilityJava2D.getBoundingBox(strList);
			rectList.add(rectAll);
//System.out.println(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;
			}

			createAllDrawingElements();
			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.show();

			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.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 ArrayList pointList )
		{

//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( effectivePointList );

			return true;
		}



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

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

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

					PathIterator itr
						= this.mConnectedPath.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 ii=0; ii<num; ii++ )
						{
							Point2D pos = (Point2D)list.get(ii);
							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 getReferenceRatio( final double refValue )
		{
			final SGAxis axis = ((ElementGroupSetInSXYGraph)(this.mGroupSet)).getYAxis();
			final float ratio = calcLocation( refValue, axis, false );

//System.out.println(refValue+"  "+ratio);

			return ratio;
		}



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

			mDrawingElementList.clear();

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


			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] = ( gx < pointArray[ii].x ) & ( pointArray[ii].x < gx + gw );
			}


			//
			final ArrayList effectivePointList = new ArrayList();
			for( int ii=0; ii<num; ii++ )
			{
				if( insideFlagArray[ii] )
				{
					effectivePointList.add( pointArray[ii] );
				}
			}



			// 参照値から比に直す
			final float refRatio
				= this.getReferenceRatio( this.mBaselineValue );

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

//System.out.println("mX="+mGraphAreaX);
//System.out.println("mY="+mGraphAreaY);
//System.out.println("mWidth="+mGraphAreaWidth);
//System.out.println("mHeight="+mGraphAreaHeight);
//System.out.println();


			// 棒グラフの描画要素を作成
			for( int ii=0; ii<effectivePointList.size(); ii++ )
			{
//System.out.println("ii="+ii);

				SGTuple2f point = (SGTuple2f)effectivePointList.get(ii);
				final float ratioX = point.x-0.5f*this.mMagnification*mRectangleWidth;
				final float ratioW = this.mMagnification*this.mRectangleWidth;
				float ratioY = 0.0f;
				float ratioH = 0.0f;

				if( refRatio <= gy )
				{
//System.out.println("a");
					if( point.y <= gy )
					{
						continue;
					}
					else if( point.y >= gy + gh )
					{
						ratioY = gy;
						ratioH = gh;
					}
					else if( (point.y>gy) && (point.y<gy+gh) )
					{
						ratioY = gy;
						ratioH = point.y - gy;
					}
				}
				else if( refRatio >= gy + gh )
				{
//System.out.println("b");
					if( point.y <= gy )
					{
						ratioY = 0.0f;
						ratioH = gy + gh;
					}
					else if( point.y >= gy + gh )
					{
						continue;
					}
					else if( (point.y>gy) && (point.y<gy+gh) )
					{
						ratioY = point.y;
						ratioH = ( gy + gh ) - point.y;
					}
				}
				else if( (refRatio>gy) && (refRatio<gy+gh) )
				{
//System.out.println("c");
					if( point.y <= gy )
					{
						ratioY = gy;
						ratioH = refRatio - gy;
					}
					else if( point.y >= gy + gh )
					{
						ratioY = refRatio;
						ratioH = ( gy + gh ) - refRatio;
					}
					else if( (point.y>gy) && (point.y<gy+gh) )
					{
						if( refRatio >= point.y )
						{
							ratioY = point.y;
							ratioH = refRatio - point.y;
						}
						else
						{
							ratioY = refRatio;
							ratioH = point.y - refRatio;
						}
					}
				}

//System.out.println(ratioX+"  "+ratioY+"  "+ratioW+"  "+ratioH);


				final SGDrawingElementBar2D rect
					= new SGDrawingElementBar2D(
						ratioX, ratioY, ratioW, ratioH );
				rect.setColorList( mColorList );

				this.addDrawingElement(rect);
			}

//System.out.println();


			return true;
		}



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

			if( this.mGroupSet.mSelectedFlag )
			{

				final int num = this.mDrawingElementList.size();
		
				if( num <= MAX_NUMBER_EMPHASIS_SYMBOLS )
				{
					for( int ii=0; ii<num; ii++ )
					{
						SGDrawingElementBar2D bar
							= (SGDrawingElementBar2D)this.mDrawingElementList.get(ii);
						emphasisBar( bar, g2d );
					}
				}
				else
				{
					int div = num/MAX_NUMBER_EMPHASIS_SYMBOLS;
					int cnt = 0;
					while( true )
					{
						SGDrawingElementBar2D bar
							= (SGDrawingElementBar2D)this.mDrawingElementList.get(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*mRulerUnit ) );
			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 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.mGroupSet.mSelectedFlag )
			{
				ElementGroupSetInSXYGraph groupSet
					= (ElementGroupSetInSXYGraph)this.mGroupSet;
				if( !groupSet.isBarVisible() )
				{
					final int num = this.mDrawingElementList.size();

					if( num <= MAX_NUMBER_EMPHASIS_SYMBOLS )
					{
						for( int ii=0; ii<num; ii++ )
						{
							SGDrawingElementSymbol2D symbol
								= (SGDrawingElementSymbol2D)this.mDrawingElementList.get(ii);
							emphasisSymbol( symbol, g2d );
						}
					}
					else
					{
						int div = num/MAX_NUMBER_EMPHASIS_SYMBOLS;
						int cnt = 0;
						while( true )
						{
							SGDrawingElementSymbol2D symbol
								= (SGDrawingElementSymbol2D)this.mDrawingElementList.get(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*mRulerUnit ) );
			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 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.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 );
			this.setColor( SGDefaultValues.ERROR_BAR_COLOR );

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

			return true;
		}



		/**
		 * 
		 */
		private boolean calcErrorBarRatio(
			final SGSXYData dataSXY, final SGAxis axisX, final SGAxis axisY,
			final ArrayList startRatioList, final ArrayList endRatioList )
		{

			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, startRatioList, endRatioList
			);

			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*SGConstants.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
	{

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



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




	}




	/**
	 * 
	 */
	class TickLabelStringElement extends SGDrawingElementString2D
	{

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


		/**
		 * 
		 */
		protected TickLabelStringElement( final String str )
		{
			super(str);
		}


		/**
		 * 
		 */
		protected TickLabelStringElement(
			final SGDrawingElementString element )
		{
			super(element);
		}


		/**
		 *
		 */
		protected TickLabelStringElement(
			final String str,
			final int fontStyle,
			final float fontSize,
			final float x,
			final float y )
		{
			super(str,fontStyle,fontSize,x,y);
		}


		/**
		 *
		 */
		protected TickLabelStringElement(
			final String str,
			final int fontStyle,
			final float fontSize )
		{
			super(str,fontStyle,fontSize);
		}


	}



}

