
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 java.awt.font.*;
import java.math.*;
import javax.swing.*;
import jp.riken.brain.ni.samuraigraph.base.*;
import jp.riken.brain.ni.samuraigraph.data.*;
import jp.riken.brain.ni.samuraigraph.figure.*;


/**
 * 軸描画用パネルクラス
 */


public class SGAxisElement extends SGFigureElement
	implements SGIAxisElement, WindowListener
{


	/**
	 * 視点情報
	 */
	private int mViewDirection = VIEW_XY;


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


	/**
	 *
	 */
	private Color mLineColor = SGDefaultValues.AXIS_LINE_COLOR;


	/**
	 *
	 */
	private float mAxisLineWidth = SGDefaultValues.AXIS_LINE_WIDTH;


	/**
	 *
	 */
	private float mScaleLineWidth = SGDefaultValues.SCALE_LINE_WIDTH;


	/**
	 *
	 */
	private Color mStringColor = SGDefaultValues.AXIS_STRING_COLOR;


	/**
	 *
	 */
	private float mTitleFontSize = SGDefaultValues.AXIS_FONT_SIZE;


	/**
	 * 
	 */
	private int mTitleFontStyle = -1;


	/**
	 * 
	 */
	private String mTitleFontFamilyName = SGDefaultValues.AXIS_FONT_FAMILY_NAME;



	/**
	 *
	 */
	private float mScaleFontSize = SGDefaultValues.AXIS_FONT_SIZE;


	/**
	 * 
	 */
	private int mScaleFontStyle = -1;


	/**
	 * 
	 */
	private String mScaleFontFamilyName = SGDefaultValues.AXIS_FONT_FAMILY_NAME;


	/**
	 * 
	 */
	private float mScaleLineLength = SGDefaultValues.SCALE_LINE_LENGTH;


	/**
	 * 
	 */
	private float mSpaceAxisLineAndNumber = SGDefaultValues.SPACE_AXIS_LINE_AND_NUMBER;


	/**
	 * 
	 */
	private float mSpaceNumberAndTitle = SGDefaultValues.SPACE_NUMBER_AND_TITLE;


	/**
	 * 
	 */
	private SGDrawingElement mPressedElement = null;


	/**
	 * 
	 */
	private Point mPressedElementOrigin = null;



	/**
	 * ポップアップメニュー
	 */
	private JPopupMenu mPopupMenu = new JPopupMenu();


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


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


	/**
	 * 
	 */
	private boolean mFrameLinesVisibleFlag = true;


	/**
	 * 
	 */
	private Color mFrameLineColor = SGDefaultValues.AXIS_FRAME_LINE_COLOR;


	/**
	 * 
	 */
	private float mFrameLineWidth = SGDefaultValues.AXIS_FRAME_LINE_WIDTH;


	/**
	 * 
	 */
	private boolean mNotifyChangeOnDraggingFlag = true;


	/**
	 * The effective digit for the axis range.
	 */
	public static final int AXIS_SCALE_EFFECTIVE_DIGIT = 3;



	/**
	 * コンストラクタ
	 */
	public SGAxisElement()
	{
		super();
		if( this.init() == false )
		{
			throw new Error();
		}
	}



	/**
	 * 
	 */
	private boolean init()
	{
		this.setAxisLineWidth( SGDefaultValues.AXIS_LINE_WIDTH );
		this.setScaleLineWidth( SGDefaultValues.SCALE_LINE_WIDTH );
		this.setScaleLineLength( SGDefaultValues.SCALE_LINE_LENGTH );
		this.setLineColor( SGDefaultValues.AXIS_LINE_COLOR );
		this.setFrameLinesVisible( SGDefaultValues.AXIS_FRAME_LINE_VISIBLE );
		this.setFrameLineWidth( SGDefaultValues.AXIS_FRAME_LINE_WIDTH );
		this.setFrameLineColor( SGDefaultValues.AXIS_FRAME_LINE_COLOR );
		this.setFontFamilyName( SGDefaultValues.AXIS_FONT_FAMILY_NAME );
		this.setFontSize( SGDefaultValues.AXIS_FONT_SIZE );
		int style = SGUtilityText.getFontStyle( SGDefaultValues.AXIS_FONT_STYLE );
		if( style==-1 )
		{
			return false;
		}
		this.setFontStyle( style );
		this.setStringColor( SGDefaultValues.AXIS_STRING_COLOR );

		return true;
	}





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

		boolean flag = true;
		if( element instanceof SGIGraphElement )
		{
//System.out.println("SGIGraphElement");
		
			final SGIGraphElement gElement = (SGIGraphElement)element;
			flag = synchronizeToGraphElement( gElement );

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


		return flag;
	}



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

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


		//
		// タイミング要素の情報を取得し、タイミング要素を作成する
		//

		{
			// 情報の取得
			final ArrayList axisList = new ArrayList();
			final ArrayList elementListList = new ArrayList();
			final ArrayList valueList = new ArrayList();
			gElement.getTimingElementList(
				axisList, elementListList, valueList );

//System.out.println("axisList:"+axisList);
//System.out.println("elementListList:"+elementListList);
//System.out.println("valueList:"+valueList);
			

			// Axisから取得したvalueListに含まれていないvalueは、Graphのリストから削除
			for( int ii=this.mTimingElementGroupSetList.size()-1; ii>=0; ii-- )
			{
				final TimingElementGroupSetInAxis groupSet
					= (TimingElementGroupSetInAxis)this.mTimingElementGroupSetList.get(ii);
				final SGDouble value = groupSet.mValue;
				final boolean flag = valueList.contains(value);
				if( !flag )
				{
					this.mTimingElementGroupSetList.remove(ii);
				}
			}


			// 
			for( int ii=0; ii<valueList.size(); ii++ )
			{
				final SGDouble value = (SGDouble)valueList.get(ii);
				final SGAxis axis = (SGAxis)axisList.get(ii);
				final ArrayList elementList = (ArrayList)elementListList.get(ii);

				boolean flag = false;
				for( int jj=0; jj<this.mTimingElementGroupSetList.size(); jj++ )
				{
					final TimingElementGroupSetInAxis groupSet
						= (TimingElementGroupSetInAxis)this.mTimingElementGroupSetList.get(jj);
					final SGDouble value_ = groupSet.mValue;
					if( value_.equals(value) )
					{

						// 描画要素の同期を取る
						final ArrayList groupList = groupSet.mDrawingElementGroupList;
						for( int kk=0; kk<groupList.size(); kk++ )
						{
							final SGElementGroup group = (SGElementGroup)groupList.get(kk);
							final SGDrawingElement el = (SGDrawingElement)elementList.get(kk);
							group.setProperty(el);
						}

						flag = true;
						break;
					}
				}

				// valueが存在しない場合には作成
				if( !flag )
				{
					// タイミング要素群のセットを作成
					final TimingElementGroupSetInAxis groupSet
						= new TimingElementGroupSetInAxis();

					groupSet.mAxis = axis;
					groupSet.mValue = value;

					for( int jj=0; jj<elementList.size(); jj++ )
					{
//System.out.println(" jj="+jj);
						final SGDrawingElement el = (SGDrawingElement)elementList.get(jj);
						groupSet.addDrawingElementGroup(el);
					}

					this.mTimingElementGroupSetList.add( ii, groupSet );


					// groupSet内に出来たgroupオブジェクトに対して描画要素を作成させる
					final ArrayList groupList = groupSet.mDrawingElementGroupList;
					for( int jj=0; jj<groupList.size(); jj++ )
					{
						final SGElementGroup group = (SGElementGroup)groupList.get(jj);

						if( group instanceof SGElementGroupLine )
						{
							final SGElementGroupLine groupLine = (SGElementGroupLine)group;
							final ArrayList ratioList = new ArrayList();
							ratioList.add( new SGTuple2d() );
							ratioList.add( new SGTuple2d() );
							groupLine.createDrawingElement( ratioList );

						}
						else
						{
							throw new Error();
						}

					}

			
				}

			}

		}

//System.out.println();


		return true;

	}





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

		return false;
	}



	/**
	 * ズーム
	 */
	public boolean zoom( final int x, final int y, final int w, final int h, final float ratio )
	{
		super.zoom(x,y,w,h,ratio);

		// 全ての要素をzoom
		for( int ii=0; ii<mElementsGroupList.size(); ii++ )
		{
			final ElementsGroupOfAxis group = (ElementsGroupOfAxis)mElementsGroupList.get(ii);
			group.zoom(w,h,ratio);
		}


		// タイミング線
		for( int ii=0; ii<this.mTimingElementGroupSetList.size(); ii++ )
		{
			final SGElementGroupSet groupSet
				= (SGElementGroupSet)this.mTimingElementGroupSetList.get(ii);
			groupSet.zoom(w,h,ratio);
		}


		// 全ての描画要素の配置を設定し直す
		this.createAllDrawingElements();


		// フィギュアを通じてブロードキャストする
//		notifyToListener( SGFigure.NOTIFY_CHANGE );
		repaint();
		
		return true;
	}


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

		for( int ii=0; ii<mElementsGroupList.size(); ii++ )
		{
			final ElementsGroupOfAxis element = (ElementsGroupOfAxis)mElementsGroupList.get(ii);
			final boolean flag = element.onMouseClicked(e);
			if( flag )
			{
//System.out.println("mouse on axis");
				return true;
			}

		}

		return false;
	}



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

		for( int ii=0; ii<mElementsGroupList.size(); ii++ )
		{
			final ElementsGroupOfAxis element = (ElementsGroupOfAxis)mElementsGroupList.get(ii);
			final boolean flag = element.onMousePressed(e);
			if( flag )
			{
				this.createTempProperties();
				return true;
			}
		}


		return false;
	}



	/**
	 * 
	 * @param e
	 */
	public boolean onMouseDragged( final MouseEvent e )
	{
		for( int ii=0; ii<mElementsGroupList.size(); ii++ )
		{
			final ElementsGroupOfAxis element = (ElementsGroupOfAxis)mElementsGroupList.get(ii);
			final boolean flag = element.onMouseDragged(e);
			if( flag )
			{
				return true;
			}
		}

		return false;
	}



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


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


	/**
	 * 
	 */
	public boolean onKeyTyped( final KeyEvent e )
	{
/*
		char c = e.getKeyChar();

		if( c == '\n' )
		{
			if( this.mDialog.isShowing() )
			{
				this.mDialog.hide();
			}
		}
*/
		return true;
	}



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

		for( int ii=0; ii<mElementsGroupList.size(); ii++ )
		{
			final ElementsGroupOfAxis element = (ElementsGroupOfAxis)mElementsGroupList.get(ii);
			if( element.onMouseReleased(e) )
			{

				if( this.createAllDrawingElements() == false )
				{
					return false;
				}
				notifyChange();
				repaint();

				this.initializePressedElement();


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

				this.mTemporaryProperties = null;


				return true;
			}

		}

		this.initializePressedElement();


		return true;

	}



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




	/**
	 * 
	 */
	private void initializePressedElement()
	{
		this.mPressedElement = null;
		this.mPressedElementOrigin = null;
	}



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



	/**
	 * 
	 * @return
	 */
	private boolean createTempProperties()
	{
		this.mTemporaryProperties = this.getProperties();

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

		return true;
	}



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

		//
		final AxisDialog dg = (AxisDialog)this.mDialog;

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

		dg.setColorButtonBorder(true);

		this.setDialogProperty();

		this.createTempProperties();


		return this.mDialog;
	}




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

		final AxisDialog dg = (AxisDialog)this.mDialog;


		// axis
		dg.setLineWidth( this.mAxisLineWidth );
		dg.setScaleLineWidth( this.mScaleLineWidth );
		dg.setScaleLineLength( this.mScaleLineLength*SGConstants.CM_POINT_RATIO );
		dg.setLineColor( this.mLineColor );


		// font
		dg.setFontFamilyName( this.mTitleFontFamilyName );
		dg.setFontSize( this.mTitleFontSize );
		dg.setStringColor( this.mStringColor );
		dg.setFontStyle( this.mTitleFontStyle );


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


		// axes
		for( int ii=0; ii<this.mElementsGroupList.size(); ii++ )
		{
			final ElementsGroupOfAxis group
				= (ElementsGroupOfAxis)this.mElementsGroupList.get(ii);
			group.setDialogProperty();
		}


		return true;

	}



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

		final AxisDialog dg = new AxisDialog( this.mDialogOwner, true );


		//
		// set the axis group
		//

		ElementsGroupOfAxis groupX1 = this.getAxisGroupInPlane( SGAxisElement.AXIS_HORIZONTAL_1 );
		ElementsGroupOfAxis groupX2 = this.getAxisGroupInPlane( SGAxisElement.AXIS_HORIZONTAL_2 );
		ElementsGroupOfAxis groupY1 = this.getAxisGroupInPlane( SGAxisElement.AXIS_PERPENDICULAR_1 );
		ElementsGroupOfAxis groupY2 = this.getAxisGroupInPlane( SGAxisElement.AXIS_PERPENDICULAR_2 );

		dg.getBottomAxisPanel().add(groupX1.mAxisPanel);
		dg.getTopAxisPanel().add(groupX2.mAxisPanel);
		dg.getLeftAxisPanel().add(groupY1.mAxisPanel);
		dg.getRightAxisPanel().add(groupY2.mAxisPanel);
		dg.pack();



		//
		// add an action-listener
		//

		dg.setActionListener(this);



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



		this.mDialog = dg;


		return true;

	}




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

		super.addData(data);


		// 最初にデータを追加するときに軸を作成
		if( this.mElementsGroupList.size() == 0 )
		{

			// in case of two-dimensional data
			if( data instanceof SGITwoDimensionalData )
			{

				SGITwoDimensionalData tData = (SGITwoDimensionalData)data;

				// analyze the data
				final double xMin = tData.getMinValueX();
				final double xMax = tData.getMaxValueX();
				final double yMin = tData.getMinValueY();
				final double yMax = tData.getMaxValueY();


				//
				// creates ElementsGroupOfAxis object
				//
		
				final ElementsGroupOfAxis groupX1 = new ElementsGroupOfAxis();
				final ElementsGroupOfAxis groupX2 = new ElementsGroupOfAxis();
				final ElementsGroupOfAxis groupY1 = new ElementsGroupOfAxis();
				final ElementsGroupOfAxis groupY2 = new ElementsGroupOfAxis();


				// X1
				{
					final SGAxis xAxis = new SGAxis();
					xAxis.setRange( xMin, xMax );
					xAxis.setScaleType( SGAxis.LINEAR_TYPE );

					final ElementsGroupOfAxis group = groupX1;
					group.setConfigurationInPlane( SGAxisElement.AXIS_HORIZONTAL_1 );
					group.mAxis = xAxis;
					group.mAxisElement = this;
					group.mVisibleFlag = SGDefaultValues.BOTTOM_AXIS_VISIBLE;
					group.mTitle.setString( SGDefaultValues.BOTTOM_AXIS_TITLE );
					mElementsGroupList.add(group);
				}

				// X2
				{
					final SGAxis xAxis = new SGAxis();
					xAxis.setRange( xMin, xMax );
					xAxis.setScaleType( SGAxis.LINEAR_TYPE );

					final ElementsGroupOfAxis group = groupX2;
					group.setConfigurationInPlane( SGAxisElement.AXIS_HORIZONTAL_2 );
					group.mAxis = xAxis;
					group.mAxisElement = this;
					group.mVisibleFlag = SGDefaultValues.TOP_AXIS_VISIBLE;
					group.mTitle.setString( SGDefaultValues.TOP_AXIS_TITLE );
					mElementsGroupList.add(group);
				}

				// Y1
				{
					final SGAxis yAxis = new SGAxis();
					yAxis.setRange( yMin, yMax );
					yAxis.setScaleType( SGAxis.LINEAR_TYPE );

					final ElementsGroupOfAxis group = groupY1;
					group.setConfigurationInPlane( SGAxisElement.AXIS_PERPENDICULAR_1 );
					group.mAxis = yAxis;
					group.mAxisElement = this;
					group.mVisibleFlag = SGDefaultValues.LEFT_AXIS_VISIBLE;
					group.mTitle.setString( SGDefaultValues.LEFT_AXIS_TITLE );
					mElementsGroupList.add(group);
				}

				// Y2
				{
					final SGAxis yAxis = new SGAxis();
					yAxis.setRange( yMin, yMax );
					yAxis.setScaleType( SGAxis.LINEAR_TYPE );

					final ElementsGroupOfAxis group = groupY2;
					group.setConfigurationInPlane( SGAxisElement.AXIS_PERPENDICULAR_2 );
					group.mAxis = yAxis;
					group.mAxisElement = this;
					group.mVisibleFlag = SGDefaultValues.RIGHT_AXIS_VISIBLE;
					group.mTitle.setString( SGDefaultValues.RIGHT_AXIS_TITLE );
					mElementsGroupList.add(group);
				}



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


				// ダイアログの作成
				this.createDialog();

			}
			else
			{
				//
				// SXYZ型およびVXYZ型データの場合
				//

				// X・Y・Z軸の作成

				// モードがMAP、投影図の場合には、SXYやVXYと同じ
				// createAxisLineElements();
				// createTitleElement();
				// createCalibrationElements();
				// を呼ぶ。
				// 鳥瞰図の場合には、別のメソッドを用いる。
			
			
			}

		}


		//
		mDataList.add( data );


		return true;
	}




	/**
	 * 
	 */
	public boolean setGraphAreaRect(
		final float x, final float y, final float width, final float height )
	{
		super.setGraphAreaRect(x,y,width,height);
//System.out.println("Axis @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
//System.out.println(this.mGraphAreaX*SGConstants.CM_POINT_RATIO+"  "+this.mGraphAreaY*SGConstants.CM_POINT_RATIO);
		this.createAllDrawingElements();

		return true;
	}




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

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


		// 描画要素を作成
		if( this.createAllDrawingElements() == false )
		{
			return false;
		}


		//
		float lineWidth = 0.0f;
		{
			ArrayList list = new ArrayList();
			list.add( new Float(this.mAxisLineWidth*this.mMagnification) );
			list.add( new Float(this.mFrameLineWidth*this.mMagnification) );
			Number num = (Number)Collections.max(list);
			lineWidth = num.floatValue();
		}


		// groups
		final ElementsGroupOfAxis groupTop = this.getAxisGroupInPlane( AXIS_HORIZONTAL_2 );
		final ElementsGroupOfAxis groupBottom = this.getAxisGroupInPlane( AXIS_HORIZONTAL_1 );
		final ElementsGroupOfAxis groupLeft = this.getAxisGroupInPlane( AXIS_PERPENDICULAR_1 );
		final ElementsGroupOfAxis groupRight = this.getAxisGroupInPlane( AXIS_PERPENDICULAR_2 );


		final float titleHeight = (float)this.getTitleHeight();
		final float numberHeight = (float)this.getScaleHeight();
		final float space = this.mMagnification*this.mSpaceAxisLineAndNumber;



		// 全ての描画要素を包むBounding Boxを求める
		Rectangle2D rectAllTop = groupTop.getBoundingBox();
		Rectangle2D rectAllBottom = groupBottom.getBoundingBox();
		Rectangle2D rectAllLeft = groupLeft.getBoundingBox();
		Rectangle2D rectAllRight = groupRight.getBoundingBox();

/*
System.out.println(rectAllTop);
System.out.println(rectAllBottom);
System.out.println(rectAllLeft);
System.out.println(rectAllRight);
*/

		// top
		float widthTop = 0.0f;
		{
			float fromTop = 0.0f;
			if( groupTop.isVisible() )
			{
				fromTop = (float)( rectAllTop.getHeight() ) + space;
				if( !groupTop.mScaleNumbersVisibleFlag )
				{
					fromTop += this.mMagnification*this.mSpaceNumberAndTitle;
				}
			}
//System.out.println(fromTop);

			float fromLeft = 0.0f;
			if( groupLeft.isVisible() )
			{
				if( groupLeft.mTitleVisibleFlag || groupLeft.mScaleNumbersVisibleFlag )
				{
					fromLeft = this.mGraphAreaY
						- (float)rectAllLeft.getY();
				}
			}
//System.out.println(fromLeft);

			float fromRight = 0.0f;
			if( groupRight.isVisible() )
			{
				if( groupRight.mTitleVisibleFlag || groupRight.mScaleNumbersVisibleFlag )
				{
					fromRight = this.mGraphAreaY
						- (float)rectAllRight.getY();
				}
			}
//System.out.println(fromRight);

			ArrayList list = new ArrayList();
			list.add( new Float(fromTop) );
			list.add( new Float(fromLeft) );
			list.add( new Float(fromRight) );
			list.add( new Float(lineWidth) );

			final Number num = (Number)Collections.max(list);
			widthTop = num.floatValue();

		}
//System.out.println("widthTop="+widthTop);



		// bottom
		float	widthBottom = 0.0f;
		{
			float fromBottom = 0.0f;
			if( groupBottom.isVisible() )
			{
				fromBottom = (float)( rectAllBottom.getHeight() ) + space;
				if( !groupBottom.mScaleNumbersVisibleFlag )
				{
					fromBottom += this.mMagnification*this.mSpaceNumberAndTitle;
				}
			}

			float fromLeft = 0.0f;
			if( groupLeft.isVisible() )
			{
				if( groupLeft.mTitleVisibleFlag || groupLeft.mScaleNumbersVisibleFlag )
				{
					fromLeft = (float)( rectAllLeft.getY() + rectAllLeft.getHeight() )
						- ( this.mGraphAreaY + this.mGraphAreaHeight );
				}
			}

			float fromRight = 0.0f;
			if( groupRight.isVisible() )
			{
				if( groupRight.mTitleVisibleFlag || groupRight.mScaleNumbersVisibleFlag )
				{
					fromRight = (float)( rectAllRight.getY() + rectAllRight.getHeight() )
						- ( this.mGraphAreaY + this.mGraphAreaHeight );
				}
			}

			ArrayList list = new ArrayList();
			list.add( new Float(fromBottom) );
			list.add( new Float(fromLeft) );
			list.add( new Float(fromRight) );
			list.add( new Float(lineWidth) );

			Number num = (Number)Collections.max(list);
			widthBottom = num.floatValue();

		}
//System.out.println("widthBottom="+widthBottom);


		// left
		final float maxLengthOfScaleNumberLeft
			= this.getMaxLengthOfScaleNumbers( groupLeft );
		float widthLeft = 0.0f;
		{
			float fromLeft = 0.0f;
			if( groupLeft.isVisible() )
			{
				fromLeft = (float)( rectAllLeft.getWidth() ) + space;
				if( !groupLeft.mScaleNumbersVisibleFlag )
				{
					fromLeft += this.mMagnification*this.mSpaceNumberAndTitle;
				}
			}

			float fromTop = 0.0f;
			if( groupTop.isVisible() )
			{
				if( groupTop.mTitleVisibleFlag || groupTop.mScaleNumbersVisibleFlag )
				{
					fromTop = - (float)rectAllTop.getX()
						+ this.mGraphAreaX;
				}
			}

			float fromBottom = 0.0f;
			if( groupBottom.isVisible() )
			{
				if( groupBottom.mTitleVisibleFlag || groupBottom.mScaleNumbersVisibleFlag )
				{
					fromBottom = - (float)rectAllBottom.getX()
						+ this.mGraphAreaX;
				}
			}

			ArrayList list = new ArrayList();
			list.add( new Float(fromLeft) );
			list.add( new Float(fromTop) );
			list.add( new Float(fromBottom) );
			list.add( new Float(lineWidth) );

			Number num = (Number)Collections.max(list);
			widthLeft = num.floatValue();

		}


		// right
		final float maxLengthOfScaleNumberRight
			= this.getMaxLengthOfScaleNumbers( groupRight );
		float widthRight = 0.0f;
		{
			float fromRight = 0.0f;
			if( groupRight.isVisible() )
			{
				fromRight = (float)( rectAllRight.getWidth() ) + space;
				if( !groupRight.mScaleNumbersVisibleFlag )
				{
					fromRight += this.mMagnification*this.mSpaceNumberAndTitle;
				}
			}
//System.out.println("fromRight="+fromRight);

			float fromTop = 0.0f;
			if( groupTop.isVisible() )
			{
				if( groupTop.mTitleVisibleFlag || groupTop.mScaleNumbersVisibleFlag )
				{
					fromTop = (float)( rectAllTop.getX() + rectAllTop.getWidth() )
						- ( this.mGraphAreaX + this.mGraphAreaWidth );
				}
			}
//System.out.println("fromTop="+fromTop);


			float fromBottom = 0.0f;
			if( groupBottom.isVisible() )
			{
				if( groupBottom.mTitleVisibleFlag || groupBottom.mScaleNumbersVisibleFlag )
				{
					fromBottom = (float)( rectAllBottom.getX() + rectAllBottom.getWidth() )
						- ( this.mGraphAreaX + this.mGraphAreaWidth );
				}
			}
//System.out.println("fromBottom="+fromBottom);


			ArrayList list = new ArrayList();
			list.add( new Float(fromRight) );
			list.add( new Float(fromTop) );
			list.add( new Float(fromBottom) );
			list.add( new Float(lineWidth) );

			Number num = (Number)Collections.max(list);
			widthRight = num.floatValue();
		}


//System.out.println();


		// 引数に渡す
		final float top = widthTop;
		final float bottom = widthBottom;
		final float left = widthLeft;
		final float right = widthRight;

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

/*
final float t = top*SGConstants.CM_POINT_RATIO/this.mMagnification;
final float b = bottom*SGConstants.CM_POINT_RATIO/this.mMagnification;
final float l = left*SGConstants.CM_POINT_RATIO/this.mMagnification;
final float h = right*SGConstants.CM_POINT_RATIO/this.mMagnification;

System.out.println("***** "+t+"  "+b+"  "+l+"  "+h);
System.out.println();
*/

		return true;

	}




	/**
	 *
	 */
	public boolean removeAllElements()
	{
		super.removeAllElements();

		this.mElementsGroupList.clear();
		this.mTimingElementGroupSetList.clear();

		return true;
	}



	/**
	 * 
	 */
	public boolean setViewDirection( final int direction )
	{
		this.mViewDirection = direction;
		return true;
	}



	/**
	 * 
	 * @return
	 */
	public boolean setTitleFontSize( final float size )
	{
		this.mTitleFontSize = size;
		return true;
	}


	/**
	 * 
	 * @return
	 */
	public boolean setTitleFontStyle( final int style )
	{
		this.mTitleFontStyle = style;
		return true;
	}


	/**
	 * 
	 * @return
	 */
	public boolean setTitleFontFamilyName( final String name )
	{
		this.mTitleFontFamilyName = name;
		return true;
	}



	/**
	 * 
	 * @return
	 */
	public boolean setLineColor( final Color color )
	{
		this.mLineColor = color;
		return true;
	}


	/**
	 * 
	 * @return
	 */
	public boolean setAxisLineWidth( final float width )
	{
		this.mAxisLineWidth = width;
		return true;
	}


	/**
	 * 
	 * @return
	 */
	public boolean setScaleLineWidth( final float width )
	{
		this.mScaleLineWidth = width;
		return true;
	}


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



	/**
	 * 
	 * @return
	 */
	public boolean setFontSize( float size )
	{
		this.setTitleFontSize( size );
		this.setScaleFontSize( size );
		return true;
	}


	/**
	 * 
	 * @return
	 */
	public boolean setFontStyle( int style )
	{
		this.setTitleFontStyle( style );
		this.setScaleFontStyle( style );
		return true;
	}


	/**
	 * 
	 * @return
	 */
	public boolean setFontFamilyName( String name )
	{
		this.setTitleFontFamilyName( name );
		this.setScaleFontFamilyName( name );
		return true;
	}



	/**
	 * 
	 * @return
	 */
	public boolean setScaleFontSize( final float size )
	{
		this.mScaleFontSize = size;
		return true;
	}


	/**
	 * 
	 * @return
	 */
	public boolean setScaleFontStyle( final int style )
	{
		this.mScaleFontStyle = style;
		return true;
	}


	/**
	 * 
	 * @return
	 */
	public boolean setScaleFontFamilyName( final String name )
	{
		this.mScaleFontFamilyName = name;
		return true;
	}


	/**
	 * 
	 * @return
	 */
	public boolean setScaleLineLength( final float margin )
	{
		this.mScaleLineLength = margin;
		return true;
	}


	/**
	 * 
	 */
	public boolean setFrameLinesVisible( final boolean b )
	{
		this.mFrameLinesVisibleFlag = b;
		return true;
	}


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


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


	/**
	 * 
	 * @return
	 */
	public boolean setSpaceAxisLineAndNumber( final float margin )
	{
		this.mSpaceAxisLineAndNumber = margin;
		return true;
	}


	/**
	 * 
	 * @return
	 */
	public boolean setSpaceNumberAndTitle( final float margin )
	{
		this.mSpaceNumberAndTitle = margin;
		return true;
	}



	/**
	 * 
	 */
	public float getSpaceAxisLineAndNumber()
	{
		return this.mSpaceAxisLineAndNumber;
	}


	/**
	 * 
	 */
	public float getSpaceNumberAndTitle()
	{
		return this.mSpaceNumberAndTitle;
	}


	/**
	 * 
	 */
	public float getNumberFontSize()
	{
		return this.mScaleFontSize;
	}


	/**
	 * 
	 */
	public float getTitleFontSize()
	{
		return this.mTitleFontSize;
	}



	/**
	 * 
	 */
	public boolean getTimingElementList(
		final ArrayList axisList, final ArrayList elementListList, final ArrayList valueList )
	{

//System.out.println("[SGIAxisElement]");
		for( int ii=0; ii<this.mTimingElementGroupSetList.size(); ii++ )
		{
//System.out.println("ii="+ii);

			final TimingElementGroupSetInAxis groupSet
				= (TimingElementGroupSetInAxis)mTimingElementGroupSetList.get(ii);

			final SGAxis axis = groupSet.mAxis;
			final ArrayList elementList = groupSet.getDrawingElementList();
			final SGDouble value = groupSet.mValue;

			axisList.add( axis );
			elementListList.add( elementList );
			valueList.add( value );

//System.out.println(" "+axis+"  "+value);

		}
//System.out.println();

		return true;
	}




	/**
	 * 
	 */
	public boolean addTimingLine( final int x, final int y )
	{
//System.out.println("add");

		for( int ii=0; ii<this.mElementsGroupList.size(); ii++ )
		{
			final ElementsGroupOfAxis group
				= (ElementsGroupOfAxis)this.mElementsGroupList.get(ii);

			final boolean flag = group.contains(x,y);
			if( flag )
			{
				// add a timing line
				group.addTimingLine( x, y );

				notifyChange();
				repaint();

				return true;
			}

		}


		return true;
	}




	/**
	 * 新しい軸のグループを追加する
	 */
	private ElementsGroupOfAxis addAxisGroup(
		final int configInCube, final SGTuple2d range, final int scaleType )
	{

//System.out.println(configInCube);

		final ElementsGroupOfAxis group = new ElementsGroupOfAxis();
		final SGAxis axis = new SGAxis();
		axis.setRange( new SGTuple2d(range) );
		axis.setScaleType( scaleType );
		group.mAxis = axis;
		group.setConfigurationInCube( configInCube );
		group.mAxisElement = this;
		mElementsGroupList.add(group);

		return group;
	}



	/**
	 * 新しい軸のグループを追加する
	 */
	private ElementsGroupOfAxis addAxisGroup( final int configInCube )
	{
		return this.addAxisGroup( configInCube, new SGTuple2d(), SGAxis.LINEAR_TYPE );
	}





	/**
	 * 10のorder乗の桁の数字で四捨五入を行う
	 * 例：value=8715.61, order=2　→　9000.0
	 *     value=213.17, order=-1　→　213.0
	 */
	private double roundOffNumber( final double value, final int order )
	{

		final double pow = Math.pow(10.0,-(double)(order));
		final double pow2 = pow/10.0;
		final double div = value*pow;
		final double div2 = value*pow2;
		final int num = ((int)div)%10;
		double roundedOffValue;
		if( num < 5 )
		{
			roundedOffValue = Math.ceil(div2)/pow2;
		}
		else
		{
			roundedOffValue = Math.floor(div2)/pow2;
		}

		return roundedOffValue;
	}



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

		super.paintGraphics2D(g2d);


		// フレームの線を描画
		if( mFrameLinesVisibleFlag )
		{
			this.drawGraphAreaBoundsLines(g2d);
		}


		//
		// 描画
		//

		for( int ii=0; ii<mElementsGroupList.size(); ii++ )
		{
			final ElementsGroupOfAxis group = (ElementsGroupOfAxis)mElementsGroupList.get(ii);
			group.paintGraphics2D(g2d);
		}

/*
{
	// groups
	final ElementsGroupOfAxis groupTop = this.getAxisGroupInPlane( AXIS_HORIZONTAL_2 );
	final ElementsGroupOfAxis groupBottom = this.getAxisGroupInPlane( AXIS_HORIZONTAL_1 );
	final ElementsGroupOfAxis groupLeft = this.getAxisGroupInPlane( AXIS_PERPENDICULAR_1 );
	final ElementsGroupOfAxis groupRight = this.getAxisGroupInPlane( AXIS_PERPENDICULAR_2 );

	// 全ての描画要素を包むBounding Boxを求める
	Rectangle2D rectAllTop = groupTop.getBoundingBox();
	Rectangle2D rectAllBottom = groupBottom.getBoundingBox();
	Rectangle2D rectAllLeft = groupLeft.getBoundingBox();
	Rectangle2D rectAllRight = groupRight.getBoundingBox();

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

	g2d.draw( rectAllTop );
	g2d.draw( rectAllBottom );
	g2d.draw( rectAllLeft );
	g2d.draw( rectAllRight );
}
*/


/*
{
	SGTuple2f tb = new SGTuple2f();
	SGTuple2f lr = new SGTuple2f();
	this.getMarginAroundGraphAreaRect( tb, lr );
//System.out.println(tb+"  "+lr);
	Rectangle2D graphAreaRect = this.getGraphAreaRect();
	Rectangle2D rect = new Rectangle2D.Float(
		(float)graphAreaRect.getX() - lr.x,
		(float)graphAreaRect.getY() - tb.x,
		(float)graphAreaRect.getWidth() + lr.x + lr.y,
		(float)graphAreaRect.getHeight() + tb.x + tb.y
	);
	g2d.setPaint( Color.RED );
	g2d.setStroke( new BasicStroke(3) );
	g2d.draw( rect );
}
*/


	}



	/**
	 * 
	 */
	public boolean chkBoundsVisible()
	{
		return true;
	}



	/**
	 * フレームの線を作成する
	 */
	private boolean drawGraphAreaBoundsLines( final Graphics2D g2d )
	{
		if( g2d == null )
		{
			return false;
		}

		g2d.setPaint(this.mFrameLineColor);
		g2d.setStroke( new BasicStroke( (float)(this.mMagnification*mFrameLineWidth) ) );

		g2d.drawRect(
			(int)(mGraphAreaX),
			(int)(mGraphAreaY),
			(int)(mGraphAreaWidth),
			(int)(mGraphAreaHeight)
		);


		return true;
	}



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

		if( element==null || g2d==null )
		{
			return false;
		}


		final double strRectLineWidth = 1.0;
		final Color strRectLineColor = Color.BLACK;
		g2d.setPaint(strRectLineColor);
		g2d.setStroke( new BasicStroke( (float)strRectLineWidth ) );

		final Rectangle2D rect = element.getElementBounds();

		g2d.drawRect(
			(int)rect.getX(),
			(int)rect.getY(),
			(int)rect.getWidth(),
			(int)rect.getHeight()
		);


		return true;

	}






	/**
	 * 
	 */
	private boolean drawString( final SGDrawingElementString2D element, final Graphics2D g2d )
	{

		if( element==null || g2d==null )
		{
			return false;
		}


		//
		element.drawString(g2d);


		return true;
	}



	/**
	 * 
	 */
	private boolean drawLine( final SGDrawingElementLine2D element, final Graphics2D g2d )
	{
		if( element==null || g2d==null )
		{
			return false;
		}

		g2d.setPaint(element.getColor(0));
		g2d.setStroke(
			new BasicStroke
			(
				(float)(mMagnification*element.getLineWidth())
			)
		);
		
		SGTuple2f start = element.getStart();
		SGTuple2f end = element.getEnd();
		final Line2D line = new Line2D.Float(
			start.x, start.y,
			end.x, end.y );
		g2d.draw(line);

		return true;
	}



	/**
	 * flagは、直線がX軸に垂直であればtrue
	 */
	private boolean drawLine( final double value, final boolean flag, final Graphics2D g2d )
	{
		if( g2d==null )
		{
			return false;
		}

		Point2D start = null;
		Point2D end = null;
		if( flag )
		{
			final double x = value;
			start = new Point2D.Double( x, 0.0 );
			end = new Point2D.Double( x, (double)this.getHeight() );
		}
		else
		{
			final double y = value;			
			start = new Point2D.Double( 0.0, y );
			end = new Point2D.Double( (double)this.getWidth(), y );
		}

		final Line2D line = new Line2D.Double( start, end );
		g2d.draw(line);

		return true;
	}



	/**
	 * 
	 */
	private boolean drawBreakingSymbol( final Graphics2D g2d )
	{

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

		g2d.setStroke( new BasicStroke(4.0f) );

		for( int ii=0; ii<this.mElementsGroupList.size(); ii++ )
		{
			final ElementsGroupOfAxis group = (ElementsGroupOfAxis)this.mElementsGroupList.get(ii);
			final ArrayList list = group.mBreakingSymbolList;
			for( int jj=0; jj<list.size(); jj++ )
			{
				final AxisBreakingSymbol bSymbol = (AxisBreakingSymbol)list.get(jj);
				final Shape[] array = bSymbol.getShapeArray();

				g2d.setPaint( Color.BLACK );
				g2d.draw( array[0] );
				g2d.draw( array[2] );

				final GeneralPath gp = new GeneralPath();
				for( int kk=0; kk<array.length; kk++ )
				{
					gp.append( array[kk], true );
				}
				g2d.setPaint( Color.WHITE );
				g2d.fill( gp );
			}
		}

		return true;
	}




	/**
	 * 
	 */
	private double getTitleHeight()
	{
		final Font font = new Font(
			this.mTitleFontFamilyName,
			this.mTitleFontStyle,
			(int)(this.mMagnification*this.mTitleFontSize) );
		final Rectangle2D rect = font.getStringBounds(
			"",	new FontRenderContext( null, false, false ) );
		return rect.getHeight();
	}



	/**
	 * 
	 */
	private double getScaleHeight()
	{
		final Font font = new Font(
			this.mScaleFontFamilyName,
			this.mScaleFontStyle,
			(int)(this.mMagnification*this.mScaleFontSize) );
		final Rectangle2D rect = font.getStringBounds(
			"",	new FontRenderContext( null, false, false ) );
		return rect.getHeight();
	}



	/**
	 * 全ての軸を入れたリストを返す
	 * @return
	 */
	public ArrayList getAxisList()
	{
		final ArrayList list = new ArrayList();

		for( int ii=0; ii<this.mElementsGroupList.size(); ii++ )
		{
			final ElementsGroupOfAxis group = (ElementsGroupOfAxis)this.mElementsGroupList.get(ii);
			list.add( group.mAxis );
		}

		return list;
	}



	/**
	 * 
	 * @return
	 */
	public ArrayList getXAxisList()
	{
		ArrayList list = new ArrayList();

		switch( this.mViewDirection )
		{
			case VIEW_XY :
			{
				list = this.getHorizontalAxisList();
				break;
			}

			case VIEW_XZ :
			{
				list = this.getHorizontalAxisList();
				break;
			}

			case VIEW_YZ :
			{
				list = this.getNormalAxisList();
				break;
			}

			default :
			{
				
			}

		}

		return list;
	}



	/**
	 * 
	 * @return
	 */
	public ArrayList getYAxisList()
	{
		ArrayList list = new ArrayList();

		switch( this.mViewDirection )
		{
			case VIEW_XY :
			{
				list = this.getPerpendicularAxisList();
				break;
			}

			case VIEW_XZ :
			{
				list = this.getNormalAxisList();
				break;
			}

			case VIEW_YZ :
			{
				list = this.getHorizontalAxisList();
				break;
			}

			default :
			{
				
			}

		}

		return list;
	}



	/**
	 * 
	 */
	public ArrayList getZAxisList()
	{
		ArrayList list = new ArrayList();

		switch( this.mViewDirection )
		{
			case VIEW_XY :
			{
				list = this.getNormalAxisList();
				break;
			}

			case VIEW_XZ :
			{
				list = this.getPerpendicularAxisList();
				break;
			}

			case VIEW_YZ :
			{
				list = this.getPerpendicularAxisList();
				break;
			}

			default :
			{
				throw new Error("not defined");
			}

		}

		return list;
	}




	/**
	 * 
	 */
	public ArrayList getHorizontalAxisList()
	{
		final ArrayList list = new ArrayList();
		
		for( int ii=0; ii<this.mElementsGroupList.size(); ii++ )
		{
			final ElementsGroupOfAxis group = (ElementsGroupOfAxis)this.mElementsGroupList.get(ii);
			final int config = this.getConfigurationInPlaneByCube( group.getConfigurationInCube() );
			if( config==AXIS_HORIZONTAL_1 || config==AXIS_HORIZONTAL_2 )
			{
				list.add(group.mAxis);
			}
		}
		
		return list;
	}


	/**
	 * 
	 */
	public ArrayList getPerpendicularAxisList()
	{
		final ArrayList list = new ArrayList();
		
		for( int ii=0; ii<this.mElementsGroupList.size(); ii++ )
		{
			final ElementsGroupOfAxis group = (ElementsGroupOfAxis)this.mElementsGroupList.get(ii);
			final int config = this.getConfigurationInPlaneByCube( group.getConfigurationInCube() );
			if( config==AXIS_PERPENDICULAR_1 || config==AXIS_PERPENDICULAR_2 )
			{
				list.add(group.mAxis);
			}
		}
		
		return list;
	}


	/**
	 * 
	 */
	public ArrayList getNormalAxisList()
	{
		final ArrayList hList = this.getHorizontalAxisList();
		final ArrayList pList = this.getPerpendicularAxisList();

		final ArrayList list = this.getAxisList();
		for( int ii=list.size()-1; ii>=0; ii-- )
		{
			final SGAxis axis = (SGAxis)list.get(ii);
			if( hList.contains(axis) || pList.contains(axis) )
			{
				list.remove(axis);
			}
		}

		return list;
	}


	/**
	 * 
	 */
	public SGAxis getAxisInCube( final int configInCube )
	{
		final ElementsGroupOfAxis group = this.getAxisGroupInCube( configInCube );

//System.out.println(group);

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

		final SGAxis axis = group.mAxis;

//System.out.println(axis);

		return axis;
	}



	/**
	 * 
	 */
	public SGAxis getAxisInPlane( final int configInPlane )
	{
		final ElementsGroupOfAxis group = this.getAxisGroupInPlane( configInPlane );

//System.out.println(group);

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

		SGAxis axis = group.mAxis;

//System.out.println(axis);

		return axis;
	}



	/**
	 * 
	 */
	private ElementsGroupOfAxis getAxisGroupInCube( final int configInCube )
	{
		for( int ii=0; ii<mElementsGroupList.size(); ii++ )
		{
			final ElementsGroupOfAxis group
				= (ElementsGroupOfAxis)mElementsGroupList.get(ii);
			if( group.getConfigurationInCube() == configInCube )
			{
				return group;
			}
		}
		
		return null;		
	}


	/**
	 * 
	 */
	private ElementsGroupOfAxis getAxisGroupInPlane( final int configInPlane )
	{
		for( int ii=0; ii<mElementsGroupList.size(); ii++ )
		{
			final ElementsGroupOfAxis group
				= (ElementsGroupOfAxis)mElementsGroupList.get(ii);
//System.out.println("ii="+ii+"  "+group.getConfigurationInPlane());
			if( group.getConfigurationInPlane() == configInPlane )
			{
				return group;
			}
		}
		
		return null;		
	}



	/**
	 * 
	 */
	public int getConfigurationInCube( final SGAxis axis )
	{
		if( axis == null )
		{
			return 0;
		}

		int config = 0;
		for( int ii=0; ii<this.mElementsGroupList.size(); ii++ )
		{
			final ElementsGroupOfAxis group = (ElementsGroupOfAxis)this.mElementsGroupList.get(ii);
			final SGAxis axis_ = group.mAxis;
			if( axis_.equals(axis) )
			{
				config = group.getConfigurationInCube();
				return config;
			}

		}

		return config;
	}



	/**
	 * 
	 */
	public int getConfigurationInPlane( final SGAxis axis )
	{
		if( axis == null )
		{
			return 0;
		}

		int config = 0;
		for( int ii=0; ii<this.mElementsGroupList.size(); ii++ )
		{
			final ElementsGroupOfAxis group = (ElementsGroupOfAxis)this.mElementsGroupList.get(ii);
			final SGAxis axis_ = group.mAxis;
			if( axis_.equals(axis) )
			{
				config = group.getConfigurationInPlane();
				return config;
			}

		}

		return config;
	}


	/**
	 * 
	 * @return
	 */
	public int getConfigurationInPlaneByCube( final int configurationInCube )
	{

		int config=0;

		switch( mViewDirection )
		{
			case VIEW_XY :
			{

				switch( configurationInCube )
				{
					
					case LOCATION_XAXIS_1 :
					{
						config = AXIS_HORIZONTAL_1;
						break;
					}
					case LOCATION_XAXIS_2 :
					{
						config = AXIS_HORIZONTAL_2;
						break;
					}
					case LOCATION_XAXIS_3 :
					{
						config = AXIS_HORIZONTAL_2;
						break;
					}
					case LOCATION_XAXIS_4 :
					{
						config = AXIS_HORIZONTAL_1;
						break;
					}
					case LOCATION_YAXIS_1 :
					{
						config = AXIS_PERPENDICULAR_1;
						break;
					}
					case LOCATION_YAXIS_2 :
					{
						config = AXIS_PERPENDICULAR_1;
						break;
					}
					case LOCATION_YAXIS_3 :
					{
						config = AXIS_PERPENDICULAR_2;
						break;
					}
					case LOCATION_YAXIS_4 :
					{
						config = AXIS_PERPENDICULAR_2;
						break;
					}
					default :
					{
						config = -1;
					}
						
				}

				break;

			}
			case VIEW_XZ :
			{

				break;
			}
			case VIEW_YZ :
			{

				break;
			}
			default :
			{
				throw new Error("not defined");
			}

		}


		return config;

	}



	/**
	 * 
	 * @return
	 */
	private int getConfigurationInCubeByPlane( final int configurationInPlane )
	{

		int config = 0;

		switch( mViewDirection )
		{
			case VIEW_XY :
			{

				switch( configurationInPlane )
				{
					
					case AXIS_HORIZONTAL_1 :
					{
						config = LOCATION_XAXIS_1;
						break;
					}
					case AXIS_HORIZONTAL_2 :
					{
						config = LOCATION_XAXIS_2;
						break;
					}
					case AXIS_PERPENDICULAR_1 :
					{
						config = LOCATION_YAXIS_1;
						break;
					}
					case AXIS_PERPENDICULAR_2 :
					{
						config = LOCATION_YAXIS_4;
						break;
					}
					default :
					{
						config = -1;
					}
						
				}

				break;

			}
			case VIEW_XZ :
			{

				break;
			}
			case VIEW_YZ :
			{

				break;
			}
			default :
			{
				throw new Error("not defined");
			}

		}

		return config;
	}




	/**
	 * 
	 */
	public String getConfigurationStringInPlaneByCube( final int configInCube )
	{

		int config = this.getConfigurationInPlaneByCube( configInCube );


		String str = null;
		switch( config )
		{
			case AXIS_HORIZONTAL_1 :
			{
				str = AXIS_BOTTOM;
				break;
			}
			
			case AXIS_HORIZONTAL_2 :
			{
				str = AXIS_TOP;
				break;
			}
			
			case AXIS_PERPENDICULAR_1 :
			{
				str = AXIS_LEFT;
				break;
			}

			case AXIS_PERPENDICULAR_2 :
			{
				str = AXIS_RIGHT;
				break;
			}
			
			default :
			{
				throw new Error();
			}
		}

		return str;
	}



	/**
	 * 
	 */
	public int getConfigurationInCubeFromStringInPlane( final String str )
	{
		int config;
		if( str.equals(AXIS_BOTTOM) )
		{
			config = AXIS_HORIZONTAL_1;
		}
		else if( str.equals(AXIS_TOP) )
		{
			config = AXIS_HORIZONTAL_2;
		}
		else if( str.equals(AXIS_LEFT) )
		{
			config = AXIS_PERPENDICULAR_1;
		}
		else if( str.equals(AXIS_RIGHT) )
		{
			config = AXIS_PERPENDICULAR_2;
		}
		else
		{
			throw new Error();
		}


		int configInCube = this.getConfigurationInCubeByPlane( config );
		
		return configInCube;
	}



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



	/**
	 * 
	 */
	public void actionPerformed(final ActionEvent e)
	{

//System.out.println("<< actionPerformed >>");
//System.out.println(e);

		final String command = e.getActionCommand();
		final Object source = e.getSource();


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

	}



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

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

		if( this.setPropertyWithDialog() == false )
		{
			return false;
		}


		// ダイアログを出す前後でプロパティが変更されている場合のみ、
		// 履歴を更新する
		SGProperties pTemp = this.mTemporaryProperties;
		SGProperties pPresent = this.getProperties();
//System.out.println("pTemp="+pTemp);
//System.out.println("pPresent="+pPresent);
//System.out.println();
		if( pTemp.equals(pPresent) == false )
		{
			// オブジェクト履歴を更新
			this.updateHistory();
		}

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


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

		repaint();


		return true;
	}


	/**
	 * 
	 */
	private boolean onCanceled()
	{

		boolean flag = this.recover();
		if(!flag)
		{
			return false;
		}

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

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

		repaint();

		return true;
	}


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

		if( this.createAllDrawingElements() == false )
		{
			return false;
		}

		if( this.setDialogProperty() == false )
		{
			return false;
		}


		this.notifyChange();

		repaint();

		return true;
	}



	/**
	 * 
	 */
	public boolean recover()
	{

		if( this.setProperties( this.mTemporaryProperties ) == false )
		{
			return false;
		}

		return true;
	}



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

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

		repaint();

		return true;
	}


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

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

		repaint();

		return true;
	}



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

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

		boolean flag = super.addPropertiesHistory(p);		

		return flag;
	}



	/**
	 * 
	 */
	private AxisCommonProperties getCommonPropertiesFromDialog()
	{
		final AxisDialog dg = (AxisDialog)this.mDialog;
		final AxisCommonProperties p = dg.getCommonProperties();

/*
		p.axisLineWidth = dg.getAxisLineWidth();
		p.scaleLineWidth = dg.getScaleLineWidth();
		p.scaleLineLength = dg.getScaleLineLength()/SGConstants.CM_POINT_RATIO;
		p.lineColor = dg.getLineColor();

		p.fontFamilyName = dg.getFontFamilyName();
		p.fontSize = dg.getFontSize();
		p.fontStyle = dg.getFontStyle();
		p.stringColor = dg.getStringColor();

		p.frameLinesVisibleFlag = dg.getFrameLinesVisibleFlag();
		p.frameLineWidth = dg.getFrameLineWidth();
		p.frameLineColor = dg.getFrameLineColor();
*/

		return p;

	}



	/**
	 * 
	 */
	private AxisProperties getPropertiesFromDialog()
	{
		AxisProperties wp = new AxisProperties();
		AxisCommonProperties cp = this.getCommonPropertiesFromDialog();
		if( cp==null )
		{
			return null;
		}
		wp.cp = cp;

		wp.ipArray = new AxisIndividualProperties[this.mElementsGroupList.size()];
		for( int ii=0; ii<wp.ipArray.length; ii++ )
		{
			ElementsGroupOfAxis group
				= (ElementsGroupOfAxis)this.mElementsGroupList.get(ii);
			AxisIndividualProperties ip = group.getPropertiesFromDialog();
			if( ip==null )
			{
				return null;
			}
			wp.ipArray[ii] = ip;
		}

		return wp;
	}




	/**
	 * 
	 */
	private boolean setPropertyWithDialog()
	{
		AxisProperties wp = this.getPropertiesFromDialog();

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

		if( this.setProperties(wp) == false )
		{
			return false;
		}
		return true;
	}





	/**
	 * 
	 */
	private float getMaxLengthOfScaleNumbers( final ElementsGroupOfAxis group )
	{

		final ArrayList numberList = group.mScaleNumberList;
		double maxLength = Double.MIN_VALUE;
		for( int ii=0; ii<numberList.size(); ii++ )
		{
			final SGDrawingElementString2D str = (SGDrawingElementString2D)numberList.get(ii);
			final Rectangle2D rect = str.getElementBounds();
			final double width = rect.getWidth();
//System.out.println(ii+"  "+width);
			if( width > maxLength )
			{
				maxLength = width;
			}
		}

		return (float)maxLength;
	}




	/**
	 * 
	 */
	private boolean createAllDrawingElements()
	{

		for( int ii=0; ii<mElementsGroupList.size(); ii++ )
		{
//System.out.println("ii="+ii);
			final ElementsGroupOfAxis element = (ElementsGroupOfAxis)mElementsGroupList.get(ii);
			if( element.createDrawingElements() == false )
			{
				return false;
			}
		}

		return true;
	}



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

		if( super.createDataObject( reader, data ) == false )
		{
			return false;
		}

		return true;
	}




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


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

//		SGUtilityForPropertyFile.writePropertyLine( writer, PF_CLASS_NAME, this.getClass().getName() );
//		SGUtilityForPropertyFile.writePropertyLine( writer, PF_VIEW_DIRECTION, new Integer( this.mViewDirection ) );

		SGUtilityText.writePropertyLine( writer, PF_AXIS_LINE_WIDTH, new Float( this.mAxisLineWidth ) );
		SGUtilityText.writePropertyLine( writer, PF_SCALE_LINE_WIDTH, new Float( this.mScaleLineWidth ) );
		SGUtilityText.writePropertyLine( writer, PF_SCALE_LINE_LENGTH, new Float( this.mScaleLineLength*SGConstants.CM_POINT_RATIO ) );
		SGUtilityText.writeColorPropertyLine( writer, PF_LINE_COLOR, this.mLineColor );

		SGUtilityText.writePropertyLine( writer, PF_FONT_FAMILY_NAME, this.mTitleFontFamilyName );
		SGUtilityText.writePropertyLine( writer, PF_FONT_SIZE, new Float( this.mTitleFontSize ) );
		SGUtilityText.writePropertyLine( writer, PF_FONT_STYLE, SGUtilityText.getFontStyleName( this.mTitleFontStyle ) );
		SGUtilityText.writeColorPropertyLine( writer, PF_STRING_COLOR, this.mStringColor );

		SGUtilityText.writePropertyLine( writer, PF_FRAME_LINE_VISIBLE, new Boolean( this.mFrameLinesVisibleFlag ) );
		SGUtilityText.writePropertyLine( writer, PF_FRAME_LINE_WIDTH, new Float( this.mFrameLineWidth ) );
		SGUtilityText.writeColorPropertyLine( writer, PF_FRAME_LINE_COLOR, this.mFrameLineColor );
		writer.write( "\n" );


		for( int ii=0; ii<this.mElementsGroupList.size(); ii++ )
		{
			final ElementsGroupOfAxis group = (ElementsGroupOfAxis)this.mElementsGroupList.get(ii);
			group.writeProperty( writer );
		}


		for( int ii=0; ii<this.mTimingElementGroupSetList.size(); ii++ )
		{
			final TimingElementGroupSetInAxis groupSet
				= (TimingElementGroupSetInAxis)this.mTimingElementGroupSetList.get(ii);
			groupSet.writeProperty( writer );
		}


		return true;

	}




	/**
	 * 
	 */
	public boolean readProperty( final BufferedReader br ) throws IOException
	{
//System.out.println("*** readProperty : SGAxisElement ***");

		// add axis groups
		ElementsGroupOfAxis group = null;
		group = this.addAxisGroup( SGAxisElement.LOCATION_XAXIS_1 );
		if( group==null )
		{
			return false;
		}
		group = this.addAxisGroup( SGAxisElement.LOCATION_XAXIS_2 );
		if( group==null )
		{
			return false;
		}
		group = this.addAxisGroup( SGAxisElement.LOCATION_YAXIS_1 );
		if( group==null )
		{
			return false;
		}
		group = this.addAxisGroup( SGAxisElement.LOCATION_YAXIS_4 );
		if( group==null )
		{
			return false;
		}


		// create the property dialog
		boolean flag = this.createDialog();
		if( !flag )
		{
			return false;
		}
//System.out.println("createDialog");


		flag = this.setProperty( br );
		if( !flag )
		{
			return false;
		}


		return true;

	}




	/**
	 * 
	 */
	private AxisCommonProperties readCommonProperties(  final BufferedReader br )
	{

		AxisCommonProperties p = new AxisCommonProperties();

		String line = null;

		try
		{

/*
			// view direction
			if( ( line = SGUtilityText.readLine(br) ) == null )
			{
				return null;
			}
			Integer nViewDirection = SGUtilityText.getIntegerPropertyFromLine(line,SGAxisElement.PF_VIEW_DIRECTION);
			if( nViewDirection == null )
			{
				return null;
			}
			p.viewDirection = nViewDirection.intValue();
*/


			//
			// axis
			//

			// set the width of axis lines
			if( ( line = SGUtilityText.readLine(br) ) == null )
			{
				return null;
			}
			Double dAxisLineWidth = SGUtilityText.getDoublePropertyFromLine(line,SGAxisElement.PF_AXIS_LINE_WIDTH);
			if( dAxisLineWidth == null )
			{
				return null;
			}
			p.axisLineWidth = dAxisLineWidth.floatValue();


			// set the width of scale lines
			if( ( line = SGUtilityText.readLine(br) ) == null )
			{
				return null;
			}
			Double dScaleLineWidth = SGUtilityText.getDoublePropertyFromLine(line,SGAxisElement.PF_SCALE_LINE_WIDTH);
			p.scaleLineWidth = dScaleLineWidth.floatValue();


			// set the length of scale lines
			if( ( line = SGUtilityText.readLine(br) ) == null )
			{
				return null;
			}
			Double dScaleLineLength = SGUtilityText.getDoublePropertyFromLine(line,SGAxisElement.PF_SCALE_LINE_LENGTH);
			if( dScaleLineLength==null )
			{
				return null;
			}
			p.scaleLineLength = dScaleLineLength.floatValue()/SGConstants.CM_POINT_RATIO;


			// set the line color
			if( ( line = SGUtilityText.readLine(br) ) == null )
			{
				return null;
			}
			Color lineColor = SGUtilityText.getColorPropertyFromLine(line,SGAxisElement.PF_LINE_COLOR);
			if( lineColor == null )
			{
				return null;
			}
			p.lineColor = lineColor;



			//
			// font
			//

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


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



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


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



			//
			// frame
			//

			// draw frame lines
			if( ( line = SGUtilityText.readLine(br) ) == null )
			{
				return null;
			}
			Boolean bFrameLineVisible = SGUtilityText.getBooleanPropertyFromLine(line,SGAxisElement.PF_FRAME_LINE_VISIBLE);
			if( bFrameLineVisible == null )
			{
				return null;
			}
			p.frameLinesVisibleFlag = bFrameLineVisible.booleanValue();


			// frame line width
			if( ( line = SGUtilityText.readLine(br) ) == null )
			{
				return null;
			}
			Double dFrameLineWidth = SGUtilityText.getDoublePropertyFromLine(line,SGAxisElement.PF_FRAME_LINE_WIDTH);
			if( dFrameLineWidth == null )
			{
				return null;
			}
			p.frameLineWidth  = dFrameLineWidth.floatValue();


			// frame lines color
			if( ( line = SGUtilityText.readLine(br) ) == null )
			{
				return null;
			}
			Color frameLineColor = SGUtilityText.getColorPropertyFromLine(line,SGAxisElement.PF_FRAME_LINE_COLOR);
			if( frameLineColor == null )
			{
				return null;
			}
			p.frameLineColor = frameLineColor;
			
		}
		catch( Exception ex )
		{
			ex.printStackTrace();
		}

		return p;

	}




	/**
	 * 
	 */
	private AxisIndividualProperties readIndividualProperties(  final BufferedReader br )
	{

		AxisIndividualProperties p = new AxisIndividualProperties();

		String line = null;			

		try
		{

			// configuration
			if( ( line = SGUtilityText.readLine(br) ) == null )
			{
				return null;
			}
			String strConfig = SGUtilityText.getPropertyFromLine(line,SGAxisElement.PF_AXIS_LOCATION);
			if( strConfig == null )
			{
				return null;
			}
			p.configuration = getConfigurationInCubeFromStringInPlane( strConfig );


			// axis scale-type
			if( ( line = SGUtilityText.readLine(br) ) == null )
			{
				return null;
			}
			Integer nScaleType = SGUtilityText.getScaleTypeFromLine(line,SGAxisElement.PF_AXIS_SCALE_TYPE);
			if( nScaleType == null )
			{
				return null;
			}
			p.scaleType = nScaleType.intValue();
				


			// axis min value
			if( ( line = SGUtilityText.readLine(br) ) == null )
			{
				return null;
			}
			Double dMinValue = SGUtilityText.getDoublePropertyFromLine(line,SGAxisElement.PF_AXIS_MIN_VALUE);
			if( dMinValue == null )
			{
				return null;
			}
			p.minValue = dMinValue.doubleValue();


			// axis max value
			if( ( line = SGUtilityText.readLine(br) ) == null )
			{
				return null;
			}
			Double dMaxValue = SGUtilityText.getDoublePropertyFromLine(line,SGAxisElement.PF_AXIS_MAX_VALUE);
			if( dMaxValue == null )
			{
				return null;
			}
			p.maxValue = dMaxValue.doubleValue();


			// auto calc axis number
			if( ( line = SGUtilityText.readLine(br) ) == null )
			{
				return null;
			}
			Boolean bAutoCalcNumberFlag = SGUtilityText.getBooleanPropertyFromLine(line,SGAxisElement.PF_AUTO_CALC_SCALE_NUMBERS);
			if( bAutoCalcNumberFlag == null )
			{
				return null;
			}
			boolean autoCalcAxisNumberFlag = bAutoCalcNumberFlag.booleanValue();
			p.autoCalcAxisNumberFlag = autoCalcAxisNumberFlag;


			// increment value
			if( ( line = SGUtilityText.readLine(br) ) == null )
			{
				return null;
			}
			Double dIncrementValue = SGUtilityText.getDoublePropertyFromLine(line,SGAxisElement.PF_INCREMENT_VALUE);
			if( dIncrementValue != null )
			{
				p.incrementValue = dIncrementValue.doubleValue();
			}


			// increment reference value
			if( ( line = SGUtilityText.readLine(br) ) == null )
			{
				return null;
			}
			Double dIncrementReferenceValue = SGUtilityText.getDoublePropertyFromLine(line,SGAxisElement.PF_INCREMENT_REFERECE_VALUE);
			if( dIncrementReferenceValue != null )
			{
				p.baseTickValue = dIncrementReferenceValue.doubleValue();
			}


			// axis visible flag
			if( ( line = SGUtilityText.readLine(br) ) == null )
			{
				return null;
			}
			Boolean dAxisGroupVisible = SGUtilityText.getBooleanPropertyFromLine(line,SGAxisElement.PF_AXIS_VISIBLE);
			if( dAxisGroupVisible == null )
			{
				return null;
			}
			boolean axisGroupVisible = dAxisGroupVisible.booleanValue();
			p.axisVisibleFlag = axisGroupVisible;


			// axis title visible
			if( ( line = SGUtilityText.readLine(br) ) == null )
			{
				return null;
			}
			Boolean bTitleVisible = SGUtilityText.getBooleanPropertyFromLine(line,SGAxisElement.PF_TITLE_VISIBLE);
			if( bTitleVisible == null )
			{
				return null;
			}
			boolean titleVisible = bTitleVisible.booleanValue();
			p.titleVisibleFlag = titleVisible;


			// title string
			if( ( line = SGUtilityText.readLine(br) ) == null )
			{
				return null;
			}
			String title = SGUtilityText.getStringPropertyFromLine(line,SGAxisElement.PF_TITLE_STRING);
			if( title == null )
			{
				return null;
			}
			p.titleString = title;


			// scale numbers visible
			if( ( line = SGUtilityText.readLine(br) ) == null )
			{
				return null;
			}
			Boolean bScaleNumbersVisible = SGUtilityText.getBooleanPropertyFromLine(line,SGAxisElement.PF_SCALE_NUMBERS_VISIBLE);
			if( bScaleNumbersVisible == null )
			{
				return null;
			}
			p.scaleNumbersVisibleFlag = bScaleNumbersVisible.booleanValue();


			// integral scale numbers
			if( ( line = SGUtilityText.readLine(br) ) == null )
			{
				return null;
			}
			Boolean bScaleNumberInteger = SGUtilityText.getBooleanPropertyFromLine(line,SGAxisElement.PF_SCALE_NUMBERS_INTEGER);
			if( bScaleNumberInteger == null )
			{
				return null;
			}
			p.scaleNumbersIntegerFlag = bScaleNumberInteger.booleanValue();


			// scale lines visible
			if( ( line = SGUtilityText.readLine(br) ) == null )
			{
				return null;
			}
			Boolean bScaleLinesVisible = SGUtilityText.getBooleanPropertyFromLine(line,SGAxisElement.PF_SCALE_LINES_VISIBLE);
			if( bScaleLinesVisible == null )
			{
				return null;
			}
			p.scaleLinesVisibleFlag = bScaleLinesVisible.booleanValue();


			// scale lines inside
			if( ( line = SGUtilityText.readLine(br) ) == null )
			{
				return null;
			}
			Boolean bScaleLinesInside = SGUtilityText.getBooleanPropertyFromLine(line,SGAxisElement.PF_SCALE_LINES_INSIDE);
			if( bScaleLinesInside == null )
			{
				return null;
			}
			p.scaleLinesInsideFlag = bScaleLinesInside.booleanValue();


			// exponent flag
			if( ( line = SGUtilityText.readLine(br) ) == null )
			{
				return null;
			}
			Boolean bExponent = SGUtilityText.getBooleanPropertyFromLine(line,SGAxisElement.PF_EXPONENT_FLAG );
			if( bExponent == null )
			{
				return null;
			}
			p.exponentFlag = bExponent.booleanValue();


			// exponent value
			if( ( line = SGUtilityText.readLine(br) ) == null )
			{
				return null;
			}
			Integer nExponent = SGUtilityText.getIntegerPropertyFromLine(line,SGAxisElement.PF_EXPONENT_VALUE );
			if( nExponent == null )
			{
				return null;
			}
			p.exponentValue = nExponent.intValue();
			
				
		}
		catch( Exception ex )
		{
			ex.printStackTrace();
		}


		return p;

	}




	/**
	 * 
	 * @return
	 */
	private boolean setProperty( final BufferedReader br ) throws IOException
	{
//System.out.println("setProperty");

		AxisCommonProperties cp = this.readCommonProperties(br);
		if( cp==null )
		{
			return false;
		}


		boolean flag = this.setCommonProperties(cp);
		if( !flag )
		{
			return false;
		}



		//
		// loop for axis_group
		//

		br.mark(256);

		while( true )
		{


			String line = null;
			if( ( line = SGUtilityText.readLine(br) ) == null )
			{
				br.reset();
				break;
			}
			if( line.equals(SGAxisElement.PF_INDIVIDUAL_AXIS_TITLE) == false )
			{
				br.reset();
				break;
			}


			AxisIndividualProperties ip = this.readIndividualProperties(br);



			// get the axis-group
			ElementsGroupOfAxis group = this.getAxisGroupInCube( ip.configuration );
			flag = group.setProperties(ip);
			if( !flag )
			{
				return false;
			}

			if( group.createDrawingElements() == false )
			{
				return false;
			}


			br.mark(256);

		}



		//
		// timing elements
		//

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

		// mark
		br.mark(256);

		while( true )
		{

			String line = null;
			if( ( line = SGUtilityText.readLine(br) ) == null )
			{
				br.reset();
				break;
			}
//System.out.println(line);

			if( line.equals( PF_TIMING_ELEMENTS_TITLE ) )
			{
				TimingElementGroupSetInAxis groupSet = new TimingElementGroupSetInAxis();
				groupSet.readProperty(br);
				this.mTimingElementGroupSetList.add(groupSet);
//System.out.println(this.mTimingElementGroupSetList);
			}
			else
			{
//System.out.println("********************************");
//System.out.println(line);
				br.reset();
				break;
			}


			// mark
			br.mark(256);

		}


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


		return true;
	}




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


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


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


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


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


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


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

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

	}





	/**
	 * 軸の線のクラス
	 */
	class ElementLineOfAxis extends SGDrawingElementLine2D
	{

		/**
		 * 
		 */
		private ElementsGroupOfAxis mGroup = null;


		/**
		 * 
		 * @param start
		 * @param end
		 * @param lineWidth
		 * @param sizeX
		 * @param sizeY
		 */
		protected ElementLineOfAxis( SGTuple2f start, SGTuple2f end, float lineWidth )
		{
			super( start, end, lineWidth );
		}
		

	}

	
	

	/**
	 * タイトル文字列のクラス
	 */
	class ElementStringOfTitle extends SGDrawingElementString2D
	{

		/**
		 * 
		 */
		private ElementsGroupOfAxis mGroup = null;

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

		/**
		 * 
		 */
		private JDialog mDialog = new JDialog();

		/**
		 * 
		 */
		private JTextField mTFString = new JTextField(10);

		/**
		 * 
		 */
		private JTextField mFontSizeField = new JTextField(10);

		/**
		 * 
		 */
		private JComboBox mFontFamilyNameBox = new JComboBox();

		/**
		 * 
		 */
		private final String SET_STRING ="Set the title string";


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


		/**
		 *
		 */
		protected ElementStringOfTitle()
		{
			super();
			this.setFontFamilyName( mTitleFontFamilyName );
		}


		/**
		 * 
		 * @param str
		 * @param fontStyle
		 * @param fontSize
		 */
		protected ElementStringOfTitle(
			final String str,
			final int fontStyle,
			final float fontSize )
		{
			super( str, fontStyle, fontSize );
			this.setFontFamilyName( mTitleFontFamilyName );
		}

	}




	/**
	 * 目盛りの線のクラス
	 */
	class ElementLineOfScale extends SGDrawingElementLine2D
	{
		/**
		 * 
		 */
		private double mValue;


		/**
		 * 
		 * @param start
		 * @param end
		 * @param lineWidth
		 * @param sizeX
		 * @param sizeY
		 */
		protected ElementLineOfScale( final SGTuple2f start, final SGTuple2f end, final float lineWidth, final double sizeX, final double sizeY )
		{
			super(start,end,lineWidth);
		}



		/**
		 * 
		 * @param el
		 */
		protected ElementLineOfScale( final ElementLineOfScale el )
		{
			super();
			this.mValue = el.mValue;
		}

	
	}




	/**
	 * 目盛りの数字のクラス
	 */
	class ElementStringOfScale extends SGDrawingElementString2D
	{

		/**
		 * 
		 */
		private double mValue;


		/**
		 * 
		 * @param str
		 * @param fontStyle
		 * @param fontSize
		 */
		protected ElementStringOfScale(
			final String str,
			final int fontStyle,
			final float fontSize )
		{
			super( str, fontStyle, fontSize );
			this.setFontFamilyName( mScaleFontFamilyName );
		}


		/**
		 * 
		 * @param el
		 */
		private ElementStringOfScale( final ElementStringOfScale el )
		{
			super(el);
			this.mValue = el.mValue;
		}


	}




	/**
	 * タイミング描画要素のインタフェース
	 */
	interface ITimingElement
	{

		/**
		 * 
		 */
		public boolean createDrawingElement();

	}



	/**
	 * タイミング線のクラス
	 */
	class TimingElementGroupLine extends SGElementGroupLine implements ITimingElement
	{

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


		/**
		 * 
		 */
		private boolean init()
		{
			this.setLineWidth( SGDefaultValues.TIMING_LINE_WIDTH );
			Integer n = SGDrawingElementLine.getLineTypeFromName( SGDefaultValues.TIMING_LINE_TYPE );
			if( n==null )
			{
				return false;
			}
			this.setLineType( n.intValue() );
			this.setColor( SGDefaultValues.TIMING_LINE_COLOR );

			return true;
		}


		/**
		 * 
		 */
		public boolean createDrawingElement()
		{

			final SGTuple2f start = new SGTuple2f();
			final SGTuple2f end = new SGTuple2f();

			final ArrayList ratioList = new ArrayList();
			ratioList.add( start );
			ratioList.add( end );
			this.createDrawingElement( ratioList );


			return true;
		}




		/**
		 * 
		 */
		public void actionPerformed(final ActionEvent e)
		{
			super.actionPerformed(e);

//			createAllDrawingElements();

			notifyChange();

			repaint();

		}



		/**
		 * 
		 */
		public boolean setPropertyWithDialog()
		{
			return true;
		}


	}




	/**
	 * 
	 */
	class ElementsGroupOfAxis implements ActionListener
	{

		/**
		 * 
		 */
		private int mConfigurationInCube = -1;


		/**
		 * 
		 */
		private SGAxisElement mAxisElement = null;


		/**
		 * 
		 */
		private SGAxis mAxis = null;


		/**
		 * 
		 */
		private ElementLineOfAxis mAxisLine = null;


		/**
		 * 
		 */
		private ElementStringOfTitle mTitle = new ElementStringOfTitle();;


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


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


		/**
		 * 
		 */
		private boolean mVisibleFlag = true;


		/**
		 * 
		 */
		private boolean mAxisLineVisibleFlag = true;


		/**
		 * 
		 */
		private boolean mTitleVisibleFlag = true;


		/**
		 * 
		 */
		private boolean mScaleNumbersVisibleFlag = true;


		/**
		 * 
		 */
		private boolean mScaleLinesVisibleFlag = true;


		/**
		 * 目盛り線を内側に描くかどうか
		 */
		private boolean mScaleLinesInsideFlag = true;


		/**
		 * 目盛りの数値の配列
		 */
		private double[] mAxisValueArray = null;


		/**
		 * 
		 */
		private boolean mAutoCalcAxisNumberFlag = true;



		/**
		 * 
		 */
		private SGAxisPanel mAxisPanel = new SGAxisPanel();



		/**
		 * 
		 */
		private double mIncrementValue = 0.0;


		/**
		 * 
		 */
		private double mBaseTickValue = 0.0;


		/**
		 * 
		 */
		private boolean mScaleNumbersIntegerFlag = false;


		/**
		 * 
		 */
		private boolean mExponentFlag = false;


		/**
		 * 
		 */
		private int mExponentValue = 0;


		/**
		 * 
		 */
		private SGDrawingElementString2D mExponentDrawingElement = null;


		/**
		 * 
		 */
		private boolean mAxisNumberDraggingFlag = false;



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


		/**
		 * 
		 */
		private SGDrawingElement mDraggingElement = null;



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


		/**
		 * 
		 */
		private boolean init()
		{
			this.mScaleNumbersVisibleFlag = SGDefaultValues.NUMBER_VISIBLE;
			this.mScaleNumbersIntegerFlag = SGDefaultValues.NUMBER_INTEGER;
			this.mScaleLinesVisibleFlag = SGDefaultValues.SCALE_LINE_VISIBLE;
			this.mScaleLinesInsideFlag = SGDefaultValues.SCALE_LINE_INNER;

			return true;
		}


		/**
		 * 
		 */
		private boolean setDialogProperty()
		{
			final SGAxisPanel ap = this.mAxisPanel;

			ap.setTitleTextField( new String( this.mTitle.getString() ) );
			ap.setRange( this.mAxis.getRange() );
			ap.setAutoCalcFlag( this.mAutoCalcAxisNumberFlag );
			ap.setIncrementValue( this.mIncrementValue );
			ap.setBaseTickValue( this.mBaseTickValue );
			ap.setScaleType( this.mAxis.getScaleType() );
			ap.setAxisVisible( this.mVisibleFlag );
			ap.setTitleVisible( this.mTitleVisibleFlag );
			ap.setScaleLinesVisible( this.mScaleLinesVisibleFlag );
			ap.setScaleLinesInside( this.mScaleLinesInsideFlag );
			ap.setScaleNumbersVisible( this.mScaleNumbersVisibleFlag );
			ap.setScaleNumbersInteger( this.mScaleNumbersIntegerFlag );
			ap.setExponentFlag( this.mExponentFlag );
			ap.setExponentValue( this.mExponentValue );
			ap.setAxisPanelComponentsEnables( this.isVisible() );

			return true;
		}



		/**
		 * 
		 */
		private SGTuple2d getScaleFromDialog()
		{

			SGTuple2d range = this.mAxisPanel.getScale();
			if( range==null )
			{
				SGTuple2d pRange = this.mAxis.getRange();
				this.mAxisPanel.setRange( pRange );
				range = pRange;
			}

			return range;
		}


		/**
		 * 
		 */
/*		private double getIncrementValueFromDialog()
		{
			double value = this.mAxisPanel.getIncrementValue();

			double value_ = 0.0;
			if( Double.isNaN(value) )
			{
				value_ = this.mIncrementValue;
System.out.println("Please input a number.");
				this.mAxisPanel.setIncrementValue( value_ );
			}
			else if( value <= Double.MIN_VALUE )
			{
				value_ = this.mIncrementValue;
System.out.println("Inputed value is too small.");
				this.mAxisPanel.setIncrementValue( value_ );
			}
			else
			{
				value_ = value;
			}

			return value_;
		}
*/

		/**
		 * 
		 */
/*		private double getBaseTickValueFromDialog()
		{
			double value = this.mAxisPanel.getBaseTickValue();

			double value_ = 0.0;
			if( Double.isNaN(value) )
			{
				value_ = this.mBaseTickValue;
System.out.println("数字を入力して下さい。");
				this.mAxisPanel.setIncrementValue( value_ );
			}
			else
			{
				value_ = value;
			}

			return value_;
		}
*/


		/**
		 * 
		 * @return
		 */
		private boolean addTimingLine( final int x, final int y )
		{

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

			double value = 0.0;
			if( getHorizontalAxisList().contains(this.mAxis) )
			{
				value = calcValue( x, this.mAxis, true );
			}
			else if( getPerpendicularAxisList().contains(this.mAxis) )
			{
				value = calcValue( y, this.mAxis, false );
			}
			else
			{
				throw new Error();
			}
//System.out.println(value);

			value = this.cutoffNumberInRangeOrder(value);

//System.out.println(value);
//System.out.println();


			TimingElementGroupSetInAxis groupSet = new TimingElementGroupSetInAxis();
			groupSet.mAxis = this.mAxis;
			groupSet.mValue = new SGDouble( value );

			groupSet.addDrawingElementGroup(SGElementGroup.POLYLINE_GROUP);
			mTimingElementGroupSetList.add( groupSet );

			return true;
		}



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

			if( this.mVisibleFlag )
			{
				// axis line
				if( this.mAxisLineVisibleFlag )
				{
					drawLine( this.mAxisLine, g2d );
				}

				// title
				if( this.mTitleVisibleFlag )
				{
					drawString( this.mTitle, g2d );
/*					if( this.mTitle.equals( mPressedElement ) )
					{
						drawStringBounds( this.mTitle, g2d );
					}
*/				}

				// scale numbers
				if( this.mScaleNumbersVisibleFlag )
				{
					final ArrayList nList = this.mScaleNumberList;
					for( int jj=0; jj<nList.size(); jj++ )
					{
						final ElementStringOfScale el
							= (ElementStringOfScale)nList.get(jj);
						drawString( el, g2d );
					}

					// draw temporary number
					if( this.mDraggingElement != null )
					{
						if( this.mDraggingElement instanceof ElementStringOfScale )
						{
							ElementStringOfScale el
								= (ElementStringOfScale)this.mDraggingElement;
							drawString(el,g2d);
							drawStringBounds(el,g2d);
						}
					}

					// exponent
					if( mExponentFlag )
					{
						drawString( this.mExponentDrawingElement, g2d );
					}

				}

				// scale lines
				if( this.mScaleLinesVisibleFlag )
				{
					final ArrayList lList = this.mScaleLineList;
					final boolean flag
						= ( this.mDraggingElement != null )
							&& ( this.mDraggingElement instanceof ElementLineOfScale );

					if( flag )
					{
						for( int jj=0; jj<lList.size(); jj++ )
						{
							final ElementLineOfScale el
								= (ElementLineOfScale)lList.get(jj);
							el.setLineWidth(2.0f*mScaleLineWidth);
						}
					}

					for( int jj=0; jj<lList.size(); jj++ )
					{
						final ElementLineOfScale el
							= (ElementLineOfScale)lList.get(jj);
						drawLine( el, g2d );
					}

					if( flag )
					{
						for( int jj=0; jj<lList.size(); jj++ )
						{
							final ElementLineOfScale el
								= (ElementLineOfScale)lList.get(jj);
							el.setLineWidth( mScaleLineWidth );
						}
					}

				}

			}

		}



		/**
		 * 
		 */
		public void actionPerformed(final ActionEvent e)
		{

			String command = e.getActionCommand();
			Object source = e.getSource();

		
		}


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


		/**
		 * 
		 */
		private int getConfigurationInPlane()
		{
			return getConfigurationInPlaneByCube( this.mConfigurationInCube );
		}


		/**
		 * 
		 */
		private int getConfigurationInCube()
		{
			return this.mConfigurationInCube;
		}


		/**
		 * 
		 */
		private boolean setConfigurationInPlane( final int configurationInPlane )
		{
			this.mConfigurationInCube = getConfigurationInCubeByPlane( configurationInPlane );

			return true;
		}


		/**
		 * 
		 */
		private boolean setConfigurationInCube( final int configurationInCube )
		{
			this.mConfigurationInCube = configurationInCube;

			return true;
		}


		/**
		 * ズーム
		 */
		public boolean zoom( final int w, final int h, final float ratio )
		{
			// 全ての描画要素に対してズーム

			this.mAxisLine.zoom(w,h,ratio);
			this.mTitle.zoom(w,h,ratio);
			for( int jj=0; jj<this.mScaleNumberList.size(); jj++ )
			{
				ElementStringOfScale el = (ElementStringOfScale)this.mScaleNumberList.get(jj);
				el.zoom(w,h,ratio);
			}
			for( int jj=0; jj<this.mScaleLineList.size(); jj++ )
			{
				ElementLineOfScale el = (ElementLineOfScale)this.mScaleLineList.get(jj);
				el.zoom(w,h,ratio);
			}

			return true;
		}



		/**
		 * 
		 * @return
		 */
		private Rectangle2D getBoundingBox()
		{
			Rectangle2D rect = new Rectangle2D.Float();
			if( this.isVisible() )
			{
				ArrayList list = new ArrayList();

				if( this.mTitleVisibleFlag )
				{
					list.add( this.mTitle );
				}

				if( this.mScaleNumbersVisibleFlag )
				{
					for( int ii=0; ii<this.mScaleNumberList.size(); ii++ )
					{
						list.add( this.mScaleNumberList.get(ii) );
					}

					if( this.mExponentFlag )
					{
						list.add( this.mExponentDrawingElement );
					}
				}

				if( list.size()!=0 )
				{
					rect.setRect( SGUtilityJava2D.getBoundingBox(list) );
				}
			}

			return rect;
		}





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

			if( !this.mVisibleFlag )
			{
				return false;
			}

//System.out.println("*** onMouseClicked ***");


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

			boolean flag;

			
			// axis line
			flag = this.mAxisLine.contains(x,y);
			if( flag )
			{
//System.out.println("axis line");
				return this.clicked(e);
			}

			// title
			flag = this.mTitle.contains(x,y);
			if( flag )
			{
//System.out.println("axis title");
				return this.clicked(e);
			}


			// numbers of axis
			for( int jj=0; jj<this.mScaleNumberList.size(); jj++ )
			{
				ElementStringOfScale el = (ElementStringOfScale)(this.mScaleNumberList).get(jj);
				flag = el.contains(x,y);
				if( flag )
				{
//System.out.println("numbers of axis");
					return this.clicked(e);
				}
			}

			// calibration lines of axis
			for( int jj=0; jj<this.mScaleLineList.size(); jj++ )
			{
				ElementLineOfScale el = (ElementLineOfScale)(this.mScaleLineList).get(jj);
				flag = el.contains(x,y);
				if( flag )
				{
//System.out.println("calibration lines of axis");
					return this.clicked(e);
				}
			}

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

			return false;
		}



		/**
		 * 
		 */
		public boolean contains( final int x, final int y )
		{
			if( !this.mVisibleFlag )
			{
				return false;
			}


			boolean flag;

			
			// axis line
			flag = this.mAxisLine.contains(x,y);
			if( flag )
			{
//System.out.println("axis line");
				return true;
			}

			// title
			flag = this.mTitle.contains(x,y);
			if( flag )
			{
//System.out.println("axis title");
				return true;
			}


			// numbers of axis
			for( int jj=0; jj<this.mScaleNumberList.size(); jj++ )
			{
				ElementStringOfScale el = (ElementStringOfScale)(this.mScaleNumberList).get(jj);
				flag = el.contains(x,y);
				if( flag )
				{
//System.out.println("numbers of axis");
					return true;
				}
			}

			// calibration lines of axis
			for( int jj=0; jj<this.mScaleLineList.size(); jj++ )
			{
				ElementLineOfScale el = (ElementLineOfScale)(this.mScaleLineList).get(jj);
				flag = el.contains(x,y);
				if( flag )
				{
//System.out.println("calibration lines of axis");
					return true;
				}
			}


			return false;

		}



		/**
		 * 
		 */
		private boolean clicked( final MouseEvent e )
		{
			int x = e.getX();
			int y = e.getY();

			if( (SwingUtilities.isRightMouseButton(e) )
				&& ( e.getClickCount() == 1 ) )
			{
//				JPopupMenu menu = mPopupMenu;
//				menu.show( mAxisElement, x, y );
			}
			else if( (SwingUtilities.isLeftMouseButton(e) )
			&& ( e.getClickCount() == 2 ) )
			{
				SGAxisDialog dg = (SGAxisDialog)getDialog();
				dg.setSelectedPanel(this.mAxisPanel);
				dg.show();
			}

			return true;
		}



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

//System.out.println("$$ onMousePressed $$");

			// If this axis-group is invisible, return false
			if( !this.mVisibleFlag )
			{
				return false;
			}


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

			boolean flag;

			
			// axis line
			if( this.mAxisLine == null )
			{
				return false;
			}
			flag = this.mAxisLine.contains(x,y);
			if( flag )
			{
				return true;
			}


			// title
			flag = this.mTitle.contains(x,y);
			if( flag )
			{
				mPressedElement = this.mTitle;
				mPressedElementOrigin = new Point(
					(int)(e.getX()-this.mTitle.getX()),
					(int)(e.getY()-this.mTitle.getY())
				);
				return true;
			}


			// numbers for axis
			for( int ii=0; ii<this.mScaleNumberList.size(); ii++ )
			{
				ElementStringOfScale el
					= (ElementStringOfScale)(this.mScaleNumberList).get(ii);
				if( el.contains(x,y) )
				{
					mPressedElement = el;
					mPressedElementOrigin = new Point(
						(int)(e.getX()-el.getX()),
						(int)(e.getY()-el.getY())
					);
					this.mTempRange = this.mAxis.getRange();
					this.mDraggingElement = new ElementStringOfScale(el);
					this.mDraggingElement.setMagnification( el.getMagnification() );


					//
					this.mAxisNumberDraggingFlag = true;


					return true;
				}
			}

			// scale lines for axis
			for( int ii=0; ii<this.mScaleLineList.size(); ii++ )
			{
				ElementLineOfScale el
					= (ElementLineOfScale)(this.mScaleLineList).get(ii);
				if( el.contains(x,y) )
				{
					mPressedElement = el;
					mPressedElementOrigin = e.getPoint();
					this.mTempRange = this.mAxis.getRange();
					this.mDraggingElement = new ElementLineOfScale(el);
					this.mDraggingElement.setMagnification( el.getMagnification() );
					return true;
				}
			}


			return false;
		}



		/**
		 * 
		 */
		private SGTuple2d mTempRange = null;



		/**
		 * 
		 */
		public boolean onMouseDragged( final MouseEvent e )
		{
//System.out.println("<< ElementGroupOfAxis::onMouseDragged >>");

			if( this.mDraggingElement==null || this.mTempRange==null )
			{
				return false;
			}


			final int scaleType = this.mAxis.getScaleType();


			//
			// ElementStringOfScale
			//

			if( this.mDraggingElement instanceof ElementStringOfScale )
			{

				final ElementStringOfScale el
					= (ElementStringOfScale)this.mDraggingElement;
				final Rectangle2D rect = el.getStringRect();

				double minValueTempInScale;
				double maxValueTempInScale;
				double oldValueInScale;
				if( scaleType==SGAxis.LINEAR_TYPE )
				{
					minValueTempInScale = this.mTempRange.x;
					maxValueTempInScale = this.mTempRange.y;
					oldValueInScale = el.mValue;
				}
				else if( scaleType==SGAxis.LOG_TYPE )
				{
					minValueTempInScale = Math.log(this.mTempRange.x)/Math.log(10.0);
					maxValueTempInScale = Math.log(this.mTempRange.y)/Math.log(10.0);
					oldValueInScale = Math.log(el.mValue)/Math.log(10.0);
				}
				else
				{
					throw new Error();
				}

//System.out.println("temp: ( "+minValueTempInScale+", "+maxValueTempInScale+" )  "+oldValueInScale);


				double minValueInScale;
				double maxValueInScale;

				// horizontal axes
				if( (this.getConfigurationInPlane()==AXIS_HORIZONTAL_1)
					|| (this.getConfigurationInPlane()==AXIS_HORIZONTAL_2) )
				{

					double draggedCoordinate = (double)(e.getX()-mPressedElementOrigin.x)+rect.getWidth()/2.0;
					final float minCoordinate = mAxisLine.getStart().x;
					final float maxCoordinate = mAxisLine.getEnd().x;
					final float width = maxCoordinate - minCoordinate;

//System.out.println(draggedCoordinate+"  "+minCoordinate+"  "+maxCoordinate);

					if( draggedCoordinate > maxCoordinate )
					{
						draggedCoordinate = maxCoordinate;
					}
					if( draggedCoordinate <= minCoordinate )
					{
//System.out.println("最小値より小さくは出来ません");
						return false;
					}
					final double valueInScale = minValueTempInScale
						+ ( maxValueTempInScale - minValueTempInScale )
							*( draggedCoordinate - minCoordinate )
							/( maxCoordinate - minCoordinate );

					// 新しいレンジの取得
					minValueInScale = minValueTempInScale;
					maxValueInScale = minValueTempInScale
						+ (maxValueTempInScale-minValueTempInScale)
							*(oldValueInScale-minValueTempInScale)/(valueInScale-minValueTempInScale);

					if( scaleType==SGAxis.LINEAR_TYPE )
					{
						maxValueInScale = this.cutoffNumberInRangeOrder(maxValueInScale);
					}

					final float x = (float)(draggedCoordinate-rect.getWidth()/2.0);
					el.setX(x);

					if( ( maxValueInScale - minValueInScale ) < 0.05*( maxValueTempInScale - minValueTempInScale ) )
					{
						return false;
					}


				}
				// perpendicular axes
				else if( (this.getConfigurationInPlane()==AXIS_PERPENDICULAR_1)
					|| (this.getConfigurationInPlane()==AXIS_PERPENDICULAR_2) )
				{

					double draggedCoordinate = (double)(e.getY()-mPressedElementOrigin.y)+rect.getHeight()/2.0;
					final float minCoordinate = mAxisLine.getEnd().y;
					final float maxCoordinate = mAxisLine.getStart().y;
					final float width = maxCoordinate - minCoordinate;

					if( draggedCoordinate >= maxCoordinate )
					{
//System.out.println("最小値より小さくは出来ません");
						return false;
					}
					if( draggedCoordinate < minCoordinate )
					{
						draggedCoordinate = minCoordinate;
					}
					final double valueInScale = minValueTempInScale
						+ ( maxValueTempInScale - minValueTempInScale )
							*( 1.0 - ( draggedCoordinate - minCoordinate )/( maxCoordinate - minCoordinate ) );

					// 新しいレンジの取得
					minValueInScale = minValueTempInScale;
					maxValueInScale = minValueTempInScale
						+ (maxValueTempInScale-minValueTempInScale)
							*(oldValueInScale-minValueTempInScale)/(valueInScale-minValueTempInScale);

					if( scaleType==SGAxis.LINEAR_TYPE )
					{
						maxValueInScale = this.cutoffNumberInRangeOrder(maxValueInScale);
					}

					final float y = (float)(draggedCoordinate-rect.getHeight()/2.0);
					el.setY(y);

					if( ( maxValueInScale - minValueInScale ) < 0.05*( maxValueTempInScale - minValueTempInScale ) )
					{
						return false;
					}

				}
				else
				{
					throw new Error();
				}


				// 軸にレンジを設定
				double minValue;
				double maxValue;
				if( scaleType==SGAxis.LINEAR_TYPE )
				{
					minValue = minValueInScale;
					maxValue = maxValueInScale;
				}
				else if( scaleType==SGAxis.LOG_TYPE )
				{
					minValue = Math.pow( 10.0, minValueInScale );
					maxValue = Math.pow( 10.0, maxValueInScale );
				}
				else
				{
					throw new Error();
				}

				mAxis.setRange( minValue, maxValue );


			}
			//
			// ElementLineOfScale
			//
			else if( this.mDraggingElement instanceof ElementLineOfScale )
			{

				final ElementLineOfScale el = (ElementLineOfScale)this.mDraggingElement;

				double minValueTempInScale;
				double maxValueTempInScale;
				double oldValueInScale;
				if( scaleType==SGAxis.LINEAR_TYPE )
				{
					minValueTempInScale = this.mTempRange.x;
					maxValueTempInScale = this.mTempRange.y;
					oldValueInScale = el.mValue;
				}
				else if( scaleType==SGAxis.LOG_TYPE )
				{
					minValueTempInScale = Math.log(this.mTempRange.x)/Math.log(10.0);
					maxValueTempInScale = Math.log(this.mTempRange.y)/Math.log(10.0);
					oldValueInScale = Math.log(el.mValue)/Math.log(10.0);
				}
				else
				{
					throw new Error();
				}


				double minValueInScale;
				double maxValueInScale;

				// horizontal axes
				if( (this.getConfigurationInPlane()==AXIS_HORIZONTAL_1)
					|| (this.getConfigurationInPlane()==AXIS_HORIZONTAL_2) )
				{

					// マウスボタンをリリースした位置の座標値の計算
					double releasedCoordinate = (double)e.getX();
					if( mPressedElementOrigin.x == releasedCoordinate )
					{
						return false;
					}

					double minCoordinate = mAxisLine.getStart().x;
					double maxCoordinate = mAxisLine.getEnd().x;
					if( releasedCoordinate > maxCoordinate )
					{
						releasedCoordinate = maxCoordinate;
					}
					if( releasedCoordinate < minCoordinate )
					{
						releasedCoordinate = minCoordinate;
					}
					double releasedValue = minValueTempInScale
						+ ( maxValueTempInScale - minValueTempInScale )
							*( releasedCoordinate - minCoordinate )/( maxCoordinate - minCoordinate );
					double diff = Math.abs( releasedValue - oldValueInScale );


					// 新しいレンジの取得
					if( releasedValue > oldValueInScale )
					{
						minValueInScale = minValueTempInScale - diff;
						maxValueInScale = maxValueTempInScale - diff;
					}
					else
					{
						minValueInScale = minValueTempInScale + diff;
						maxValueInScale = maxValueTempInScale + diff;
					}


					if( scaleType == SGAxis.LINEAR_TYPE )
					{
						minValueInScale = this.cutoffNumberInRangeOrder(minValueInScale);
						maxValueInScale = this.cutoffNumberInRangeOrder(maxValueInScale);
					}

				}
				else if( (this.getConfigurationInPlane()==AXIS_PERPENDICULAR_1)
					|| (this.getConfigurationInPlane()==AXIS_PERPENDICULAR_2) )
				{

					// マウスボタンをリリースした位置の座標値の計算
					double releasedCoordinate = (double)e.getY();
					if( mPressedElementOrigin.y == releasedCoordinate )
					{
						return false;
					}

					double minCoordinate = mAxisLine.getEnd().y;
					double maxCoordinate = mAxisLine.getStart().y;
					if( releasedCoordinate > maxCoordinate )
					{
						releasedCoordinate = maxCoordinate;
					}
					if( releasedCoordinate < minCoordinate )
					{
						releasedCoordinate = minCoordinate;
					}
					double releasedValue
						= minValueTempInScale
							+ ( maxValueTempInScale - minValueTempInScale )
								*( 1.0 - ( releasedCoordinate - minCoordinate )/( maxCoordinate - minCoordinate ) );
					double diff = Math.abs( releasedValue - oldValueInScale );

					// 新しいレンジの取得
					double min;
					double max;
					if( releasedValue > oldValueInScale )
					{
						minValueInScale = minValueTempInScale - diff;
						maxValueInScale = maxValueTempInScale - diff;
					}
					else
					{
						minValueInScale = minValueTempInScale + diff;
						maxValueInScale = maxValueTempInScale + diff;
					}


					if( scaleType == SGAxis.LINEAR_TYPE )
					{
						minValueInScale = this.cutoffNumberInRangeOrder(minValueInScale);
						maxValueInScale = this.cutoffNumberInRangeOrder(maxValueInScale);
					}

				}
				else
				{
					throw new Error();
				}



				// 軸にレンジを設定
				double minValue;
				double maxValue;
				if( scaleType==SGAxis.LINEAR_TYPE )
				{
					minValue = minValueInScale;
					maxValue = maxValueInScale;
				}
				else if( scaleType==SGAxis.LOG_TYPE )
				{
					minValue = Math.pow( 10.0, minValueInScale );
					maxValue = Math.pow( 10.0, maxValueInScale );
				}
				else
				{
					throw new Error();
				}

				mAxis.setRange( minValue, maxValue );

			}



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

			// notify to listeners
			if( mNotifyChangeOnDraggingFlag )
			{
				notifyChange();
			}

			repaint();


			return true;
		}



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

			if( this.mTempRange!=null || this.mDraggingElement!=null )
			{
//System.out.println("$$ onMouseReleased $$");

				this.mTempRange = null;
				this.mDraggingElement = null;

				// horizontal axes
				if( (this.getConfigurationInPlane()==AXIS_HORIZONTAL_1)
					|| (this.getConfigurationInPlane()==AXIS_HORIZONTAL_2) )
				{
					ElementsGroupOfAxis group = getAxisGroupInPlane( AXIS_PERPENDICULAR_1 );
					group.mAxisNumberDraggingFlag = false;
				}
				// perpendicular axes
				else if( (this.getConfigurationInPlane()==AXIS_PERPENDICULAR_1)
					|| (this.getConfigurationInPlane()==AXIS_PERPENDICULAR_2) )
				{
					ElementsGroupOfAxis group = getAxisGroupInPlane( AXIS_HORIZONTAL_1 );
					group.mAxisNumberDraggingFlag = false;
				}

				return true;
			}

			return false;
		}



		/**
		 * 
		 */
		private double cutoffNumberInRangeOrder( final double value )
		{
			final int order = this.getRangeOrder() - SGAxisElement.AXIS_SCALE_EFFECTIVE_DIGIT + 1;
			BigDecimal bd = new BigDecimal(value);
			bd = bd.movePointLeft(order);
			bd = bd.setScale(0,BigDecimal.ROUND_HALF_UP);
			bd = bd.movePointRight(order);
			return bd.doubleValue();
		}



		/**
		 * 
		 */
		private boolean createDrawingElements()
		{

// The order of calling these methods are important.

			// axis line
			if( this.createAxisLineElements() == false )
			{
				return false;
			}
//System.out.println("axis line");

			// numbers and scale lines
			if( this.createScaleDrawingElements() == false )
			{
				return false;
			}
//System.out.println("numbers and scale lines");

			// title
			if( this.createTitleElement() == false )
			{
				return false;
			}
//System.out.println("title");

			return true;
		}



		/**
		 * 
		 * @return
		 */
		private boolean createScaleDrawingElements()
		{

			// 目盛り数字の計算
			if( this.calcValueArrayInScale() == false )
			{
				return false;
			}
//System.out.println("calcValueArrayInScale");


			// 数字の描画要素を作成する
			if( this.createScaleNumberInstances() == false )
			{
				return false;
			}
//System.out.println("createScaleNumberInstances");


			// 数字の描画要素に位置を指定する
			if( this.setLocationOfScaleNumbers() == false )
			{
				return false;
			}
//System.out.println("createScaleLines");


			// 目盛り線の作成
			if( this.createScaleLines() == false )
			{
				return false;
			}
//System.out.println("createScaleLines");


			return true;

		}



		/**
		 * 
		 */
		private boolean createAxisLineElements()
		{

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

			SGTuple2f start = null;
			SGTuple2f end = null;

			final float x = mGraphAreaX;
			final float y = mGraphAreaY;
			final float w = mGraphAreaWidth;
			final float h = mGraphAreaHeight;

			switch( this.getConfigurationInPlane() )
			{

				case AXIS_HORIZONTAL_1 :
				{
					start = new SGTuple2f( x, y+h );
					end = new SGTuple2f( x+w, y+h );
					break;
				}

				case AXIS_HORIZONTAL_2 :
				{
					start = new SGTuple2f( x, y );
					end = new SGTuple2f( x+w, y );
					break;
				}

				case AXIS_PERPENDICULAR_1 :
				{
					start = new SGTuple2f( x, y+h );
					end = new SGTuple2f( x, y );
					break;
				}

				case AXIS_PERPENDICULAR_2 :
				{
					start = new SGTuple2f( x+w, y+h );
					end = new SGTuple2f( x+w, y );
					break;
				}

				default :
				{
				
				}

			}


			if( mAxisLine == null )
			{
				mAxisLine = new ElementLineOfAxis( start, end, mAxisLineWidth );
				mAxisLine.mGroup = this;
			}
	
			mAxisLine.setTermPoints( start, end );
			mAxisLine.setLineWidth( mAxisLineWidth );
			mAxisLine.setColor( mLineColor );


//System.out.println(start+"  "+end);
//System.out.println();


			return true;
		}



		/**
		 * 
		 */
		private boolean createTitleElement()
		{
			final float gx = mGraphAreaX;
			final float gy = mGraphAreaY;
			final float gw = mGraphAreaWidth;
			final float gh = mGraphAreaHeight;


			//
			// title of axes
			//

			mTitle.mGroup = this;
			mTitle.setColor( mStringColor );
			mTitle.setFontSize( mTitleFontSize );
			mTitle.setFontStyle( mTitleFontStyle );
			mTitle.setFontFamilyName( mTitleFontFamilyName );

			float scaleNumberHeight = 0.0f;
			float maxWidth = 0.0f;
			if( this.mScaleNumbersVisibleFlag )
			{
				scaleNumberHeight = (float)getScaleHeight();
				maxWidth = (float)getMaxLengthOfScaleNumbers(this);
			}

			switch( this.getConfigurationInPlane() )
			{
				case SGAxisElement.AXIS_HORIZONTAL_1 :
				{
					Rectangle2D rectTitle = mTitle.getElementBounds();
					mTitle.setLocation(
						gx + gw/2.0f - (float)rectTitle.getWidth()/2.0f,
						gy + gh + scaleNumberHeight
							+ ( mSpaceAxisLineAndNumber + mSpaceNumberAndTitle )*mMagnification
					);

					break;
				}

				case SGAxisElement.AXIS_HORIZONTAL_2 :
				{
					Rectangle2D rectTitle = mTitle.getElementBounds();
					mTitle.setLocation(
						gx + gw/2.0f - (float)rectTitle.getWidth()/2.0f,
						gy - scaleNumberHeight - (float)rectTitle.getHeight()
							- ( mSpaceAxisLineAndNumber + mSpaceNumberAndTitle )*mMagnification
					);
					break;
				}

				case SGAxisElement.AXIS_PERPENDICULAR_1 :
				{
					mTitle.setAngle( 90.0f*(float)Math.PI/180.0f );	// 90度回転
					Rectangle2D rectTitle = mTitle.getElementBounds();
					mTitle.setLocation(
						gx - maxWidth - (float)rectTitle.getWidth()
							- ( mSpaceNumberAndTitle + mSpaceAxisLineAndNumber )*mMagnification,
						gy + 0.5f*gh + 0.5f*(float)rectTitle.getHeight()
					);
					break;
				}

				case SGAxisElement.AXIS_PERPENDICULAR_2 :
				{
					mTitle.setAngle( 90.0f*(float)Math.PI/180.0f );	// 90度回転
					Rectangle2D rectTitle = mTitle.getElementBounds();
					mTitle.setLocation(
						gx + gw + maxWidth
							+ ( mSpaceAxisLineAndNumber + mSpaceNumberAndTitle )*mMagnification,
						gy + 0.5f*gh + 0.5f*(float)rectTitle.getHeight()
					);
					break;
				}

				default :
				{
				
				}

			}

//System.out.println(mTitle.getElementBounds().getBounds2D());

			return true;

		}



		/**
		 * 
		 * @return
		 */
		private boolean createScaleNumberInstances()
		{

			// clear
			this.mScaleNumberList.clear();
			this.mExponentDrawingElement = null;


			// scale type
			final int scaleType = this.mAxis.getScaleType();


			// exponent
			double[] valueArray = null;
			if( this.mExponentFlag )
			{
				valueArray = new double[this.mAxisValueArray.length];
				for( int ii=0; ii<valueArray.length; ii++ )
				{
					BigDecimal db = new BigDecimal( this.mAxisValueArray[ii] );
					db = db.movePointLeft( this.mExponentValue );
					valueArray[ii] = db.doubleValue();
				}
			}
			else
			{
				valueArray = this.mAxisValueArray;
			}


			// create string array
			String[] strArray = new String[valueArray.length];
			if( scaleType == SGAxis.LINEAR_TYPE )
			{
				if( this.mScaleNumbersIntegerFlag )
				{
					for( int ii=0; ii<strArray.length; ii++ )
					{
						strArray[ii] = ( new Integer( (int)valueArray[ii] ) ).toString();
					}
				}
				else
				{
					for( int ii=0; ii<strArray.length; ii++ )
					{
						strArray[ii] = ( new Double( valueArray[ii] ) ).toString();
					}
				}
			}
			else if( scaleType == SGAxis.LOG_TYPE )
			{
				for( int ii=0; ii<strArray.length; ii++ )
				{
					final int order = SGUtilityNumber.getOrder( valueArray[ii] );
					strArray[ii] = SGUtilityText.getSuperscriptString(
						"10", new Integer(order).toString() );
				}
			}


			// create drawing elements of the scale numbers
			for( int ii=0; ii<this.mAxisValueArray.length; ii++ )
			{
				ElementStringOfScale el = new ElementStringOfScale(
					strArray[ii], mScaleFontStyle, mScaleFontSize );
				el.mValue = mAxisValueArray[ii];
				el.setMagnification( mMagnification );
				el.setColor( mStringColor );
				this.mScaleNumberList.add(el);
			}


			// create the exponent drawing element
			if( this.mExponentFlag )
			{
				this.createExponentDrawingElement();
			}


			return true;

		}



		/**
		 * 
		 * @return
		 */
		private boolean createExponentDrawingElement()
		{

			String str = "x10";
			str = SGUtilityText.getSuperscriptString(
				str, new Integer( this.mExponentValue ).toString() );
			SGDrawingElementString2D el = new SGDrawingElementString2D(
				str, mScaleFontStyle, mScaleFontSize );
			el.setMagnification( mMagnification );
			el.setColor( mStringColor );

			final Rectangle2D rect = el.getElementBounds();

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

			final float spaceLN = mMagnification*mSpaceAxisLineAndNumber;
			final float spaceNT = mMagnification*mSpaceNumberAndTitle;

			float x = 0.0f;
			float y = 0.0f;
			switch( this.getConfigurationInPlane() )
			{

				case AXIS_HORIZONTAL_1 :
				{
					x = gx + gw - 0*(float)rect.getWidth();
					y = gy + gh + (float)( spaceLN + getScaleHeight() + spaceNT );
					break;
				}

				case AXIS_HORIZONTAL_2 :
				{
					x = gx + gw - 0*(float)rect.getWidth();
					y = gy - (float)( spaceLN + getScaleHeight() + spaceNT + getTitleHeight() );
					break;
				}

				case AXIS_PERPENDICULAR_1 :
				{
					x = gx - (float)( spaceLN + getMaxLengthOfScaleNumbers(this) + spaceNT + rect.getWidth() );
					y = gy - (float)rect.getHeight();
					break;
				}

				case AXIS_PERPENDICULAR_2 :
				{
					x = gx + gw + (float)( spaceLN + getMaxLengthOfScaleNumbers(this) + spaceNT );
					y = gy - (float)rect.getHeight();
					break;
				}

				default :
				{
				
				}

			}

			el.setLocation(x,y);

			this.mExponentDrawingElement = el;


			return true;
		}




		/**
		 * 
		 */
		private boolean setLocationOfScaleNumbers()
		{

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


			int scaleType = this.mAxis.getScaleType();

			double[] valueArrayInScale = null;
			if( scaleType == SGAxis.LINEAR_TYPE )
			{
				valueArrayInScale = this.mAxisValueArray;
			}
			else if( scaleType == SGAxis.LOG_TYPE )
			{
				valueArrayInScale = new double[this.mAxisValueArray.length];
				for( int ii=0; ii<valueArrayInScale.length; ii++ )
				{
					valueArrayInScale[ii] = Math.log( this.mAxisValueArray[ii] );
				}
			}

			double axisMinInScale = 0.0;
			double axisMaxInScale = 0.0;
			if( scaleType == SGAxis.LINEAR_TYPE )
			{
				axisMinInScale = this.mAxis.getMinValue();
				axisMaxInScale = this.mAxis.getMaxValue();
			}
			else if( scaleType == SGAxis.LOG_TYPE )
			{
				axisMinInScale = Math.log(this.mAxis.getMinValue());
				axisMaxInScale = Math.log(this.mAxis.getMaxValue());
			}


			double maxWidth = Double.MIN_VALUE;
			for( int ii=0; ii<valueArrayInScale.length; ii++ )
			{
				ElementStringOfScale el
					= (ElementStringOfScale)mScaleNumberList.get(ii);

				Rectangle2D rect = el.getElementBounds();
				double width = rect.getWidth();
				if( width > maxWidth )
				{
					maxWidth = width;
				}
			}


			double maxWidthRatio = maxWidth;

			for( int ii=0; ii<this.mScaleNumberList.size(); ii++ )
			{
				ElementStringOfScale el
					= (ElementStringOfScale)mScaleNumberList.get(ii);

				Rectangle2D rect = el.getElementBounds();
				final float ratioWidth = (float)rect.getWidth();
				final float ratioHeight = (float)rect.getHeight();

				final float spaceRatioCalibrationAndTitle
					= mMagnification*mSpaceNumberAndTitle;

				final float spaceAxisLineAndNumber = mMagnification*mSpaceAxisLineAndNumber;

				switch( this.getConfigurationInPlane() )
				{
					case AXIS_HORIZONTAL_1 :
					{
						final float xRatio = (float)( gx
							+ gw*(valueArrayInScale[ii]-axisMinInScale)/(axisMaxInScale-axisMinInScale) );
						final float yRatio = (float)( ( gy + gh ) + spaceAxisLineAndNumber );
						el.setLocation( ( xRatio-0.50f*ratioWidth ), yRatio );
						break;
					}

					case AXIS_HORIZONTAL_2 :
					{
						final float xRatio = (float)( gx + gw*(valueArrayInScale[ii]-axisMinInScale)/(axisMaxInScale-axisMinInScale) );
						final float yRatio = (float)( gy - spaceAxisLineAndNumber - rect.getHeight() );
						el.setLocation( ( xRatio-0.50f*ratioWidth ), yRatio );
						break;
					}

					// 目盛り数字のうち、最も長いものの左端を（タイトルの右端＋スペース）に合わせる
					case AXIS_PERPENDICULAR_1 :
					{
						final float yRatio = (float)( gy + gh*(1.0-(valueArrayInScale[ii]-axisMinInScale)/(axisMaxInScale-axisMinInScale)) );
						final float titleWidth = (float)getTitleHeight();
						final float xRatio = (float)( gx - spaceAxisLineAndNumber - rect.getWidth() );
						el.setLocation( xRatio, ( yRatio - 0.5f*ratioHeight ) );
						break;
					}

					case AXIS_PERPENDICULAR_2 :
					{
						final float yRatio = (float)( gy + gh*(1.0-(valueArrayInScale[ii]-axisMinInScale)/(axisMaxInScale-axisMinInScale)) );
						final float xRatio = (float)( gx + gw + spaceAxisLineAndNumber );
						el.setLocation( xRatio, ( yRatio - 0.5f*ratioHeight ) );

						break;
					}

					default :
					{
						throw new Error();
					}

				}

				
			}
//System.out.println();


			return true;
		}



		/**
		 * 
		 */
		private boolean createScaleLines()
		{
			// clear the list
			mScaleLineList.clear();


			boolean flag = true;
			switch( this.mAxis.getScaleType() )
			{
				case SGAxis.LINEAR_TYPE :
				{
					flag = this.createScaleLinesInLinearScale();
					break;
				}
				
				case SGAxis.LOG_TYPE :
				{
					flag = this.createScaleLinesInLogScale();
					break;
				}
				
				default :
				{
					throw new Error();
				}
				
			}

			return flag;
		}



		/**
		 * 
		 */
		private boolean createScaleLinesInLinearScale()
		{

			final float length = mMagnification*mScaleLineLength;


			//
			// 目盛り線の描画要素の作成
			//

			for( int ii=0; ii<this.mAxisValueArray.length; ii++ )
			{
				final double value = this.mAxisValueArray[ii];

				ElementLineOfScale el = this.createSingleScaleLine( value, length );
				if( el!=null )
				{
					el.mValue = value;
					el.setMagnification( mMagnification );
					el.setColor( mLineColor );

					this.mScaleLineList.add(el);
				}
			}



			//
			// 目盛り線の間に目盛り線を作成する
			//

			for( int ii=0; ii<this.mAxisValueArray.length; ii++ )
			{

				if( ii==this.mAxisValueArray.length-1 )
				{
					break;
				}

				final double value = (
					this.mAxisValueArray[ii] + this.mAxisValueArray[ii+1] )/2.0;

				ElementLineOfScale el = this.createSingleScaleLine( value, length );
				if( el!=null )
				{
					el.mValue = value;
					el.setMagnification( mMagnification );
					el.setColor( mLineColor );

					this.mScaleLineList.add(el);
				}
			}


			// 一つ前
			{
				final double value = this.mAxisValueArray[0] - this.mIncrementValue/2.0;
				if( this.mAxis.insideRange( value ) )
				{
					ElementLineOfScale el = this.createSingleScaleLine( value, length );
					if( el!=null )
					{
						el.mValue = value;
						el.setMagnification( mMagnification );
						el.setColor( mLineColor );

						this.mScaleLineList.add(el);
					}
				}
			}



			// 一つ後
			{
				final double value = this.mAxisValueArray[this.mAxisValueArray.length-1] + this.mIncrementValue/2.0;
				if( this.mAxis.insideRange( value ) )
				{
					ElementLineOfScale el = this.createSingleScaleLine( value, length );
					if( el!=null )
					{
						el.mValue = value;
						el.setMagnification( mMagnification );
						el.setColor( mLineColor );

						this.mScaleLineList.add(el);
					}
				}
			}

			return true;
		}



		/**
		 * 
		 */
		private boolean createScaleLinesInLogScale()
		{
//System.out.println("<< createScaleLinesInLogScale >>");

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


			// create the main scale lines
			final float length = mMagnification*mScaleLineLength;
			for( int ii=0; ii<this.mAxisValueArray.length; ii++ )
			{
				final double value = this.mAxisValueArray[ii];

				ElementLineOfScale el = this.createSingleScaleLine(
					value, length );
				if( el!=null )
				{
					el.mValue = value;
					el.setMagnification( mMagnification );
					el.setColor( mLineColor );

					this.mScaleLineList.add(el);
				}
			}

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

			// create the sub scale lines
			final float ratio = 1.0f;
			for( int ii=0; ii<this.mAxisValueArray.length; ii++ )
			{
				for( int jj=2; jj<10; jj++ )
				{
					final double value = this.mAxisValueArray[ii]*0.10*(double)jj;

					ElementLineOfScale el = this.createSingleScaleLine(
						value, ratio*length );
					if( el!=null )
					{
						el.mValue = value;
						el.setMagnification( mMagnification );
						el.setColor( mLineColor );

						this.mScaleLineList.add(el);
					}
				}
			}


			//
			if( this.mAxisValueArray.length >= 1 )
			{
				for( int jj=2; jj<10; jj++ )
				{
					final double value
						= this.mAxisValueArray[this.mAxisValueArray.length-1]*(double)jj;
					ElementLineOfScale el = this.createSingleScaleLine(
						value, ratio*length );
					if( el!=null )
					{
						el.mValue = value;
						el.setMagnification( mMagnification );
						el.setColor( mLineColor );

						this.mScaleLineList.add(el);
					}
				}
			}


			return true;
		}




		/**
		 * 
		 * @param value
		 * @param length
		 * @return
		 */
		private ElementLineOfScale createSingleScaleLine(
			final double value, final float length )
		{
//System.out.println("<< createSingleScaleLine >>");

			if( this.mAxis.insideRange(value) == false )
			{
				return null;
			}


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

			double min;
			double max;
			double valueInScale;
			switch( this.mAxis.getScaleType() )
			{
				case SGAxis.LINEAR_TYPE :
				{
					min = this.mAxis.getMinValue();
					max = this.mAxis.getMaxValue();
					valueInScale = value;
					break;
				}
				
				case SGAxis.LOG_TYPE :
				{
					min = Math.log( this.mAxis.getMinValue() );
					max = Math.log( this.mAxis.getMaxValue() );
					valueInScale = Math.log(value);
					break;
				}
				
				default :
				{
					throw new Error();
				}
			}


			ElementLineOfScale el = null;

			switch( this.getConfigurationInPlane() )
			{
				case AXIS_HORIZONTAL_1 :
				{
					final double x = gx + gw*(valueInScale-min)/(max-min);
					final double yStart = gy+gh;
					double yEnd = 0.0;
					if( this.mScaleLinesInsideFlag )
					{
						yEnd = yStart - length;
					}
					else
					{
						yEnd = yStart + length;
					}

					final SGTuple2f start = new SGTuple2f( (float)x, (float)yStart );
					final SGTuple2f end = new SGTuple2f( (float)x, (float)yEnd );
					el = new ElementLineOfScale(
						start, end, mScaleLineWidth, mAxisElement.getWidth(), mAxisElement.getHeight() );
					break;
				}

				case AXIS_HORIZONTAL_2 :
				{
					final double x = gx + gw*(valueInScale-min)/(max-min);
					final double yStart = gy;
					double yEnd = 0.0;
					if( this.mScaleLinesInsideFlag )
					{
						yEnd = yStart + length;
					}
					else
					{
						yEnd = yStart - length;
					}

					SGTuple2f start = new SGTuple2f( (float)x, (float)yStart );
					SGTuple2f end = new SGTuple2f( (float)x, (float)yEnd );
					el = new ElementLineOfScale(
						start, end, mScaleLineWidth, mAxisElement.getWidth(), mAxisElement.getHeight() );
					break;
				}

				case AXIS_PERPENDICULAR_1 :
				{
					final double y = gy + gh*(1.0-(valueInScale-min)/(max-min));
					final double xStart = gx;
					double xEnd = 0.0;
					if( this.mScaleLinesInsideFlag )
					{
						xEnd = xStart + length;
					}
					else
					{
						xEnd = xStart - length;
					}

					final SGTuple2f start = new SGTuple2f( (float)xStart, (float)y );
					final SGTuple2f end = new SGTuple2f( (float)xEnd, (float)y );
					el = new ElementLineOfScale(
						start, end, mScaleLineWidth, mAxisElement.getWidth(), mAxisElement.getHeight() );
					break;
				}

				case AXIS_PERPENDICULAR_2 :
				{
					final double y = gy + gh*(1.0-(valueInScale-min)/(max-min));
					final double xStart = gx+gw;
					double xEnd = 0.0;
					if( this.mScaleLinesInsideFlag )
					{
						xEnd = xStart - length;
					}
					else
					{
						xEnd = xStart + length;
					}

					final SGTuple2f start = new SGTuple2f( (float)xStart, (float)y );
					final SGTuple2f end = new SGTuple2f( (float)xEnd, (float)y );
					el = new ElementLineOfScale(
						start, end, mScaleLineWidth, mAxisElement.getWidth(), mAxisElement.getHeight() );
					break;
				}

				default :
				{
					throw new Error();
				}

			}

//System.out.println(el);
//System.out.println();

			return el;
		}







		/**
		 * 軸のスケールタイプに合わせて数列を作り直す
		 */
		private boolean calcValueArrayInScale()
		{

			// 目盛りの数値を計算する
			double[] array = null;
			switch( this.mAxis.getScaleType() )
			{
				case SGAxis.LINEAR_TYPE :
				{
					array = this.calcScaleValuesInLinearScale();
					break;
				}
				
				case SGAxis.LOG_TYPE :
				{
					array = this.calcScaleValuesInLogScale();
					break;
				}
				
				default :
				{
					throw new Error();
				}
				
			}


			// 属性に設定
			this.mAxisValueArray = array;


			return true;
		}



		/**
		 * 
		 */
		private int getRangeOrder()
		{
			final double min = this.mAxis.getRange().x;
			final double max = this.mAxis.getRange().y;
			final int order = SGUtilityNumber.getOrder( max - min );
			return order;
		}



		/**
		 * Calculate the numbers of scale in for the linear scale.
		 * @return
		 */
		private double[] calcScaleValuesInLinearScale()
		{
//System.out.println("<< calcScaleValues >> "+getConfigurationInPlane());

			// minimum and maximum values of axis range
			final double min = this.mAxis.getRange().x;
			final double max = this.mAxis.getRange().y;
			final double range = max - min;

			// array of values for scale
			double[] axisValueArray = null;

			// get the order of axis range
			final int order = SGUtilityNumber.getOrder(range);
			final double power = SGUtilityNumber.getPowersOfTen( order );

			// get reference value and increment value
			if( this.mAutoCalcAxisNumberFlag )
			{
				double baseTick = 0.0;

				final double value = range - 0.10*power;
				final int order_ = SGUtilityNumber.getOrder(value);
				final double power_ = SGUtilityNumber.getPowersOfTen( order_ );
				final double ratio = value/power_;

				double increment = 0.0;
				if( ratio<=1.1 )
				{
					increment = 0.20*power_;
				}
				else if( 1.1<ratio && ratio<=2.0 )
				{
					increment = 0.50*power_;
				}
				else if( 2.0<ratio && ratio<=6.0 )
				{
					increment = 1.0*power_;
				}
				else if( 6.0<ratio )
				{
					increment = 2.0*power_;
				}

//System.out.println("before:"+increment);
				increment = this.cutoffNumberInRangeOrder(increment);
//System.out.println("after:"+increment);

				this.mBaseTickValue = baseTick;
				this.mIncrementValue = increment;
			}
			final double reference = this.mBaseTickValue;
			final double increment = this.mIncrementValue;

//System.out.println("range:"+min+" "+max);
//System.out.println("b:"+reference+"  "+"i:"+increment);

			// get an array of numbers
			final ArrayList valueList = new ArrayList();
			int cnt = 0;
			while( true )
			{
				final double value = reference + (double)cnt*increment;
				if( value > max )
				{
					break;
				}

				if( this.mAxis.insideRange( value ) == false )
				{
					cnt++;
					continue;
				}

				final double tValue = SGUtilityNumber.truncateNumber( value, order-5 );
//System.out.println(tValue);

				valueList.add(new Double(tValue));
				cnt++;					
			}
//System.out.println();

			cnt = 1;
			while( true )
			{
				final double value = reference - (double)cnt*increment;
				if( value < min )
				{
					break;
				}

				if( this.mAxis.insideRange( value ) == false )
				{
					cnt++;
					continue;
				}

				final double tValue = SGUtilityNumber.truncateNumber( value, order-5 );
//System.out.println(tValue);

				valueList.add(0,new Double(tValue));
				cnt++;					
			}
//System.out.println();

			axisValueArray = new double[valueList.size()];
			for( int ii=0; ii<axisValueArray.length; ii++ )
			{
				axisValueArray[ii] = ((Double)valueList.get(ii)).doubleValue();
			}
				


			// cast to integer
			if( this.mScaleNumbersIntegerFlag )
			{
//System.out.println("Integer");

				final ArrayList numList = new ArrayList();
				for( int ii=0; ii<axisValueArray.length; ii++ )
				{
					final int num = (int)axisValueArray[ii];
					numList.add( new Integer(num) );
				}

//System.out.println(numList);

				// 同じ数字を除く
				for( int ii=numList.size()-1; ii>=1; ii-- )
				{
					final Integer n1 = (Integer)numList.get(ii);
//System.out.println("ii="+ii+"  "+n1);

					for( int jj=ii-1; jj>=0; jj-- )
					{
						final Integer n2 = (Integer)numList.get(jj);
//System.out.println(" jj="+jj+"  "+n2);

						if( n2.intValue() == n1.intValue() )
						{
//System.out.println(n1+"  "+n2+"  "+numList);
							numList.remove(ii);
//System.out.println("removed"+"  "+numList);
//System.out.println();
							break;
						}
					}
				}

//System.out.println(numList);
//System.out.println();


				final double[] valueArray = new double[numList.size()];
				for( int ii=0; ii<valueArray.length; ii++ )
				{
					valueArray[ii] = (double)(((Integer)numList.get(ii)).intValue());
				}
				axisValueArray = valueArray;

			}

			return axisValueArray;

		}



		/**
		 * Calculate the numbers of scale in for the linear scale.
		 * @return
		 */
		private double[] calcScaleValuesInLogScale()
		{
//System.out.println("<< calcScaleValuesInLogScale >>");

			// minimum and maximum values of axis range
			final double min = this.mAxis.getRange().x;
			final double max = this.mAxis.getRange().y;

			// array of values for scale
			double[] axisValueArray = null;

			final int minOrder = SGUtilityNumber.getOrder( (1.0-1.0E-14)*min );
			final int maxOrder = SGUtilityNumber.getOrder(max);

//System.out.println(min+"  "+minOrder);
//System.out.println(max+"  "+maxOrder);

//final double diff = max - min;
//final int diffOrder = SGUtility.getOrder( (1.0-1.0E-14)*diff );

			ArrayList list = new ArrayList();
			for( int ii=minOrder+1; ii<=maxOrder; ii++ )
			{
				list.add( new Integer(ii) );
			}

//System.out.println(list);

			axisValueArray = new double[list.size()];
			for( int ii=0; ii<axisValueArray.length; ii++ )
			{
				final int num = ((Integer)list.get(ii)).intValue();
				axisValueArray[ii] = SGUtilityNumber.getPowersOfTen( num );
			}

//System.out.println();

			return axisValueArray;
		}



		/**
		 * 
		 */
		private ArrayList getTimingElementsList()
		{
			final ArrayList list = new ArrayList();

			for( int ii=0; ii<mTimingElementGroupSetList.size(); ii++ )
			{
				final TimingElementGroupSetInAxis groupSet
					= (TimingElementGroupSetInAxis)mTimingElementGroupSetList.get(ii);
				final SGAxis axis = groupSet.mAxis;
				if( axis.equals(this.mAxis) )
				{
					list.add( groupSet );
				}
			}
			
			return list;
		}



		/**
		 * 
		 */
		private boolean addBreakingSymbol()
		{

			final AxisBreakingSymbol bSymbol = new AxisBreakingSymbol();
			bSymbol.setColor(Color.WHITE);
			bSymbol.setSize(100.0f);
			bSymbol.setMagnification( mMagnification );

			bSymbol.setLocation( 0.50f, 0.50f );

			this.mBreakingSymbolList.add( bSymbol );

			return true;
		}




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

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

			SGTuple2d range = this.mAxis.getRange();

			int config = this.getConfigurationInCube();
			String str = getConfigurationStringInPlaneByCube(config);
			SGUtilityText.writePropertyLine( writer, PF_AXIS_LOCATION, str );

			SGUtilityText.writePropertyLine( writer, PF_AXIS_SCALE_TYPE, SGUtilityText.getScaleTypeName( this.mAxis.getScaleType() ) );
			SGUtilityText.writePropertyLine( writer, PF_AXIS_MIN_VALUE, new Double( range.x ) );
			SGUtilityText.writePropertyLine( writer, PF_AXIS_MAX_VALUE, new Double( range.y ) );

			SGUtilityText.writePropertyLine( writer, PF_AUTO_CALC_SCALE_NUMBERS, new Boolean( this.mAutoCalcAxisNumberFlag ) );
			SGUtilityText.writePropertyLine( writer, PF_INCREMENT_VALUE, new Double( this.mIncrementValue ) );
			SGUtilityText.writePropertyLine( writer, PF_INCREMENT_REFERECE_VALUE, new Double( this.mBaseTickValue ) );

			SGUtilityText.writePropertyLine( writer, PF_AXIS_VISIBLE, new Boolean( this.mVisibleFlag ) );

			SGUtilityText.writePropertyLine( writer, PF_TITLE_VISIBLE, new Boolean( this.mTitleVisibleFlag) );
			SGUtilityText.writeStringPropertyLine( writer, PF_TITLE_STRING, this.mTitle.getString() );

			SGUtilityText.writePropertyLine( writer, PF_SCALE_NUMBERS_VISIBLE, new Boolean( this.mScaleNumbersVisibleFlag ) );
			SGUtilityText.writePropertyLine( writer, PF_SCALE_NUMBERS_INTEGER, new Boolean( this.mScaleNumbersIntegerFlag ) );

			SGUtilityText.writePropertyLine( writer, PF_SCALE_LINES_VISIBLE, new Boolean( this.mScaleLinesVisibleFlag ) );
			SGUtilityText.writePropertyLine( writer, PF_SCALE_LINES_INSIDE, new Boolean( this.mScaleLinesInsideFlag ) );

			SGUtilityText.writePropertyLine( writer, PF_EXPONENT_FLAG, new Boolean( this.mExponentFlag ) );
			SGUtilityText.writePropertyLine( writer, PF_EXPONENT_VALUE, new Integer( this.mExponentValue ) );

			writer.write( "\n" );


			return true;

		}



		/**
		 * 
		 */
		private AxisIndividualProperties getPropertiesFromDialog()
		{


			AxisIndividualProperties p = this.mAxisPanel.getProperties();

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

			p.configuration = this.getConfigurationInCube();

/*
			final int scaleType = this.mAxisPanel.getScaleType();
			SGTuple2d range = this.getScaleFromDialog();
			if( scaleType == SGAxis.LOG_TYPE )
			{
				if( range.x < Double.MIN_VALUE )
				{
//					SGUtility.showMessageDialog(
//						mDialog,
//						"range.x < Double.MIN_VALUE : inappropriate range for the log scale",
//						"Illegal input to the dilaog.",
//						JOptionPane.ERROR_MESSAGE
//					);
System.out.println("Inappropriate range for the log scale");
					this.mAxisPanel.setScaleType( SGAxis.LINEAR_TYPE );
					return null;
				}
			}
			p.scaleType = scaleType;
			p.minValue = range.x;
			p.maxValue = range.y;

			p.autoCalcAxisNumberFlag = this.mAxisPanel.getAutoCalcFlag();
			p.incrementValue = this.getIncrementValueFromDialog();
			p.incrementReferenceValue = this.getBaseTickValueFromDialog();
			p.titleString = this.mAxisPanel.getTitleString();
			p.axisVisibleFlag = this.mAxisPanel.getAxisGroupVisible();
			p.titleVisibleFlag = this.mAxisPanel.getTitleVisible();
			p.scaleLinesVisibleFlag = this.mAxisPanel.getScaleLineVisible();
			p.scaleNumbersVisibleFlag = this.mAxisPanel.getScaleNumbersVisible();
			p.scaleLinesInsideFlag = this.mAxisPanel.getScaleLineDirection();
			p.scaleNumbersIntegerFlag = this.mAxisPanel.getScaleNumbersInteger();
			p.exponentFlag = this.mAxisPanel.getExponentFlag();
			p.exponentValue = this.mAxisPanel.getExponentValue();
*/

			return p;
		}



		/**
		 * 
		 */
		private AxisIndividualProperties getProperties()
		{
			AxisIndividualProperties p = new AxisIndividualProperties();

			p.configuration = this.getConfigurationInCube();

			p.scaleType = this.mAxis.getScaleType();

			SGTuple2d range = this.mAxis.getRange();
			p.minValue = range.x;
			p.maxValue = range.y;
			
			p.autoCalcAxisNumberFlag = this.mAutoCalcAxisNumberFlag;
			p.incrementValue = this.mIncrementValue;
			p.baseTickValue = this.mBaseTickValue;
			p.titleString = this.mTitle.getString();
			p.axisVisibleFlag = this.mVisibleFlag;
			p.titleVisibleFlag = this.mTitleVisibleFlag;
			p.scaleLinesVisibleFlag = this.mScaleLinesVisibleFlag;
			p.scaleNumbersVisibleFlag = this.mScaleNumbersVisibleFlag;
			p.scaleLinesInsideFlag = this.mScaleLinesInsideFlag;
			p.scaleNumbersIntegerFlag = this.mScaleNumbersIntegerFlag;
			p.exponentFlag = this.mExponentFlag;
			p.exponentValue = this.mExponentValue;

			return p;
		}



		/**
		 * 
		 */
		private boolean setProperties( AxisIndividualProperties p )
		{

			this.mConfigurationInCube = p.configuration;
			this.mAxis.setScaleType( p.scaleType );
			this.mAxis.setRange( p.minValue, p.maxValue );
			this.mAutoCalcAxisNumberFlag = p.autoCalcAxisNumberFlag;
			this.mIncrementValue = p.incrementValue;
			this.mBaseTickValue = p.baseTickValue;
			this.mTitle.setString( p.titleString );
			this.mVisibleFlag = p.axisVisibleFlag;
			this.mTitleVisibleFlag = p.titleVisibleFlag;
			this.mScaleLinesVisibleFlag = p.scaleLinesVisibleFlag;
			this.mScaleNumbersVisibleFlag = p.scaleNumbersVisibleFlag;
			this.mScaleLinesInsideFlag = p.scaleLinesInsideFlag;
			this.mScaleNumbersIntegerFlag = p.scaleNumbersIntegerFlag;
			this.mExponentFlag = p.exponentFlag;
			this.mExponentValue = p.exponentValue;

			return true;
		}


	}






	/**
	 * タイミング描画要素群のクラス
	 */
	class TimingElementGroupSetInAxis extends SGTimingElementGroupSet
	{

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


		/**
		 * 
		 */
		protected SGElementGroup createDrawingElementGroup(
			final int type )
		{

			SGElementGroup group = null;
			if( type == SGElementGroup.POLYLINE_GROUP )
			{
				group = new TimingElementGroupLine();
			}
			else
			{
				throw new Error("");
			}

			group.mGroupSet = this;


			return group;
		}


		/**
		 * 
		 */
		protected SGElementGroup createDrawingElementGroup(
			final SGDrawingElement element )
		{

			SGElementGroup group = null;
			if( element instanceof SGDrawingElementLine )
			{
				group = new TimingElementGroupLine();
			}
			else
			{
				throw new Error("");
			}

			group.setProperty( element );

			group.mGroupSet = this;


			return group;
		}


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


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



		/**
		 * 
		 */
		public boolean onDrawingElement( final int x, final int y )
		{
			return false;
		}


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

			writer.write(PF_TIMING_ELEMENTS_TITLE+"\n");
		
			final int config = getConfigurationInCube( this.mAxis );

			SGUtilityText.writePropertyLine( writer, PF_AXIS_LOCATION, new Integer( config ) );
			SGUtilityText.writePropertyLine( writer, PF_TIMING_VALUE, new Double( this.mValue.mValue ) );

			this.writePropertyOfData(writer);

			writer.write( "\n" );


			return true;

		}



		/**
		 * 
		 */
		protected boolean readProperty( final BufferedReader br ) throws IOException
		{

			this.mDrawingElementGroupList.clear();


			String line = null;

			// configuration of axis
			if( ( line = SGUtilityText.readLine(br) ) == null )
			{
				return false;
			}
			Integer nConfiguration = SGUtilityText.getIntegerPropertyFromLine( line, PF_AXIS_LOCATION );
			if( nConfiguration == null )
			{
				return false;
			}
			int configuration = nConfiguration.intValue();
			SGAxis axis = getAxisInCube(configuration);
			this.mAxis = axis;
//System.out.println(configuration);


			// value
			if( ( line = SGUtilityText.readLine(br) ) == null )
			{
				return false;
			}
			Double dValue = SGUtilityText.getDoublePropertyFromLine( line, PF_TIMING_VALUE );
			if( dValue == null )
			{
				return false;
			}
			double value = dValue.doubleValue();
			if( this.mValue == null )
			{
				this.mValue = new SGDouble( value );
			}
			else
			{
				this.mValue.mValue = value;
			}
//System.out.println(value);


			br.mark(256);

			while( true )
			{
				
				SGElementGroup group = null;

				if( ( line = SGUtilityText.readLine(br) ) == null )
				{
					return false;
				}
//System.out.println(line);

				if( line.equals( SGElementGroupLine.PF_LINE_TITLE ) )
				{
					group = new TimingElementGroupLine();
				}
				else
				{
					br.reset();
					break;
				}

				group.mGroupSet = this;
				group.readProperty(br);
				this.mDrawingElementGroupList.add( group );

				br.mark(256);
				
			}

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

			return true;

		}


	}



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

		wp.cp = this.getCommonProperties();
		wp.ipArray = new AxisIndividualProperties[this.mElementsGroupList.size()];
		for( int ii=0; ii<wp.ipArray.length; ii++ )
		{
			ElementsGroupOfAxis group
				= (ElementsGroupOfAxis)this.mElementsGroupList.get(ii);
			wp.ipArray[ii] = group.getProperties();
		}

		return wp;
	}



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

		AxisProperties wp = (AxisProperties)p;

//System.out.println(wp);
//System.out.println(wp.cp);
		this.setCommonProperties( wp.cp );

		AxisIndividualProperties[] array = wp.ipArray;
		for( int ii=0; ii<array.length; ii++ )
		{
//System.out.println(ii+"  "+array[ii]);
			ElementsGroupOfAxis group = this.getAxisGroupInCube( array[ii].configuration );
			group.setProperties( array[ii] );
		}

		return true;
	}




	/**
	 * 
	 */
	private AxisCommonProperties getCommonProperties()
	{
		AxisCommonProperties p = new AxisCommonProperties();

		p.viewDirection = this.mViewDirection;
		p.frameLinesVisibleFlag = this.mFrameLinesVisibleFlag;
		p.frameLineWidth = this.mFrameLineWidth;
		p.frameLineColor = this.mFrameLineColor;
		p.lineColor = this.mLineColor;
		p.stringColor = this.mStringColor;
		p.axisLineWidth = this.mAxisLineWidth;
		p.scaleLineWidth = this.mScaleLineWidth;
		p.scaleLineLength = this.mScaleLineLength;
		p.fontSize = this.mTitleFontSize;
		p.fontFamilyName = this.mTitleFontFamilyName;
		p.fontStyle = this.mTitleFontStyle;

		return p;
	}



	/**
	 * 
	 */
	private boolean setCommonProperties( AxisCommonProperties p )
	{
		
		this.mViewDirection = p.viewDirection;
		this.setFrameLinesVisible( p.frameLinesVisibleFlag );
		this.setFrameLineWidth( p.frameLineWidth );
		this.setFrameLineColor( p.frameLineColor );
		this.setLineColor( p.lineColor );
		this.setStringColor( p.stringColor );
		this.setAxisLineWidth( p.axisLineWidth );
		this.setScaleLineWidth( p.scaleLineWidth );
		this.setScaleLineLength( p.scaleLineLength );
		this.setFontSize( p.fontSize );
		this.setFontFamilyName( p.fontFamilyName );
		this.setFontStyle( p.fontStyle );

		return true;
	}




	/**
	 * 
	 */
	class AxisProperties extends SGProperties
	{
		AxisCommonProperties cp;
		AxisIndividualProperties[] ipArray;

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

			if( (p.cp).equals(this.cp) == false ) return false;
			if( p.ipArray.length != this.ipArray.length ) return false;
			for( int ii=0; ii<this.ipArray.length; ii++ )
			{
				if( p.ipArray[ii].equals( this.ipArray[ii] ) == false )
				{
					return false;
				}
			}

		
			return true;
		}
	}



	/**
	 * 
	 */
	public static class AxisCommonProperties extends SGProperties
	{
		int viewDirection;
		boolean frameLinesVisibleFlag;
		float frameLineWidth;
		Color frameLineColor;
		Color lineColor;
		Color stringColor;
		float axisLineWidth;
		float scaleLineWidth;
		float scaleLineLength;
		float fontSize;
		String fontFamilyName;
		int fontStyle;



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

			AxisCommonProperties p = (AxisCommonProperties)obj;

			if( p.viewDirection!=this.viewDirection ) return false;
			if( p.frameLinesVisibleFlag!=this.frameLinesVisibleFlag ) return false;
			if( p.frameLineWidth!=this.frameLineWidth ) return false;
			if( p.frameLineColor.equals(this.frameLineColor) == false ) return false;
			if( p.lineColor.equals(this.lineColor) == false ) return false;
			if( p.stringColor.equals(this.stringColor) == false ) return false;
			if( p.axisLineWidth!=this.axisLineWidth ) return false;
			if( p.scaleLineWidth!=this.scaleLineWidth ) return false;
			if( p.scaleLineLength!=this.scaleLineLength ) return false;
			if( p.fontSize!=this.fontSize ) return false;
			if( p.fontFamilyName.equals(this.fontFamilyName) == false ) return false;
			if( p.fontStyle!=this.fontStyle ) return false;

			return true;
		}


	}



	/**
	 * 
	 */
	public static class AxisIndividualProperties extends SGProperties
	{
		int configuration;
		int scaleType;
		double minValue;
		double maxValue;
		boolean autoCalcAxisNumberFlag;
		double incrementValue;
		double baseTickValue;
		String titleString;
		boolean axisVisibleFlag;
		boolean titleVisibleFlag;
		boolean scaleLinesVisibleFlag;
		boolean scaleNumbersVisibleFlag;
		boolean scaleLinesInsideFlag;
		boolean scaleNumbersIntegerFlag;
		boolean exponentFlag;
		int exponentValue;

		/**
		 * 
		 */
		public boolean equals( final Object obj )
		{
			if( ( obj instanceof AxisIndividualProperties) == false )
			{
				return false;
			}
			
			AxisIndividualProperties p = (AxisIndividualProperties)obj;
			
			if( p.configuration!=this.configuration ) return false;
			if( p.scaleType!=this.scaleType ) return false;
			if( p.minValue!=this.minValue ) return false;
			if( p.maxValue!=this.maxValue ) return false;
			if( p.autoCalcAxisNumberFlag!=this.autoCalcAxisNumberFlag ) return false;
			if( p.incrementValue!=this.incrementValue ) return false;
			if( p.baseTickValue!=this.baseTickValue ) return false;
			if( p.titleString.equals(this.titleString) == false ) return false;
			if( p.axisVisibleFlag!=this.axisVisibleFlag ) return false;
			if( p.titleVisibleFlag!=this.titleVisibleFlag ) return false;
			if( p.scaleLinesVisibleFlag!=this.scaleLinesVisibleFlag ) return false;
			if( p.scaleNumbersVisibleFlag!=this.scaleNumbersVisibleFlag ) return false;
			if( p.scaleLinesInsideFlag!=this.scaleLinesInsideFlag ) return false;
			if( p.scaleNumbersIntegerFlag!=this.scaleNumbersIntegerFlag ) return false;
			if( p.exponentFlag!=this.exponentFlag ) return false;
			if( p.exponentValue!=this.exponentValue ) return false;

			return true;
		}



	}









	/**
	 * 
	 */
	class AxisBreakingSymbol extends SGDrawingElementSymbol2D
	{

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


		/**
		 * 
		 */
		private Point2D[] getCtrlPointsArray()
		{

			Point2D[] points = new Point2D.Double[8];

			points[0] = new Point2D.Double( -0.50, 0.25 );
			points[1] = new Point2D.Double( -0.250, 0.50 );
			points[2] = new Point2D.Double( 0.250, 0.0 );
			points[3] = new Point2D.Double( 0.50, 0.25 );

			points[4] = new Point2D.Double( 0.50, -0.25 );
			points[5] = new Point2D.Double( 0.250, -0.50 );
			points[6] = new Point2D.Double( -0.250, 0.0 );
			points[7] = new Point2D.Double( -0.50, -0.25 );


			SGTuple2d pos = this.getLocation();
			double size = this.getSize();
			Point2D[] ctrlPointsArray = new Point2D[points.length];
			for( int ii=0; ii<ctrlPointsArray.length; ii++ )
			{
				double x = pos.x + points[ii].getX()*size;
				double y = pos.y + points[ii].getY()*size;
				ctrlPointsArray[ii] = new Point2D.Double(x,y);
			}

			return ctrlPointsArray;
		}


		/**
		 * 
		 */
		private Shape[] getShapeArray()
		{

			ArrayList list = new ArrayList();

			Point2D[] points = this.getCtrlPointsArray();

			Shape[] shapeArray = new Shape[4];

			shapeArray[0]
				= new CubicCurve2D.Double(
					points[0].getX(), points[0].getY(),
					points[1].getX(), points[1].getY(),
					points[2].getX(), points[2].getY(),
					points[3].getX(), points[3].getY() );

			shapeArray[1]
				= new Line2D.Double(
					points[3], points[4] );

			shapeArray[2]
				= new CubicCurve2D.Double(
					points[4].getX(), points[4].getY(),
					points[5].getX(), points[5].getY(),
					points[6].getX(), points[6].getY(),
					points[7].getX(), points[7].getY() );

			shapeArray[3]
				= new Line2D.Double(
					points[7], points[0] );

			return shapeArray;
		}

	}



	/**
	 * 
	 */
	class AxisDialog extends SGAxisDialog
	{

		/** Creates new form SGAxisDialog */
		protected AxisDialog(java.awt.Frame parent, boolean modal)
		{
			super(parent, modal);
		}
    

		/**
		 * 
		 */
		public ArrayList getActiveComponentList()
		{
			final ArrayList list = super.getActiveComponentList();
			for( int ii=0; ii<mElementsGroupList.size(); ii++ )
			{
				final ElementsGroupOfAxis group
					= (ElementsGroupOfAxis)mElementsGroupList.get(ii);
				final SGAxisPanel ap = group.mAxisPanel;
				ArrayList aList = ap.getActiveComponentList();
				for( int jj=0; jj<aList.size(); jj++ )
				{
					list.add( aList.get(jj) );
				}
			}

			return list;
		}


		/**
		 * 
		 */
/*		public ArrayList getSpinnerList()
		{
			ArrayList list = super.getSpinnerList();
			for( int ii=0; ii<mElementsGroupList.size(); ii++ )
			{
				ElementsGroupOfAxis group = (ElementsGroupOfAxis)mElementsGroupList.get(ii);
				ArrayList gl = group.mAxisPanel.getSpinnerList();
				for( int jj=0; jj<gl.size(); jj++ )
				{
					list.add( gl.get(jj) );
				}
			}

			return list;
		}
*/

		/**
		 * 
		 */
		public boolean setActionListener( final ActionListener listener )
		{
			super.setActionListener( listener );

			for( int ii=0; ii<mElementsGroupList.size(); ii++ )
			{
				ElementsGroupOfAxis group = (ElementsGroupOfAxis)mElementsGroupList.get(ii);
				group.mAxisPanel.setActionListener( listener );
			}

			return true;
		}


		/**
		 * 
		 */
		public boolean removeActionListener()
		{
			super.removeActionListener();

			for( int ii=0; ii<mElementsGroupList.size(); ii++ )
			{
				ElementsGroupOfAxis group = (ElementsGroupOfAxis)mElementsGroupList.get(ii);
				group.mAxisPanel.removeActionListener();
			}

			return true;
		}




	}


}


