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

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Cursor;
import java.awt.Font;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.font.FontRenderContext;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JPopupMenu;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.event.CaretEvent;
import javax.swing.event.CaretListener;
import jp.riken.brain.ni.samuraigraph.base.SGAxis;
import jp.riken.brain.ni.samuraigraph.base.SGData;
import jp.riken.brain.ni.samuraigraph.base.SGDrawingElement;
import jp.riken.brain.ni.samuraigraph.base.SGIFigureElementAxisBreak;
import jp.riken.brain.ni.samuraigraph.base.SGIFigureElementAxis;
import jp.riken.brain.ni.samuraigraph.base.SGIConstants;
import jp.riken.brain.ni.samuraigraph.base.SGIFigureElement;
import jp.riken.brain.ni.samuraigraph.base.SGIFigureElementGraph;
import jp.riken.brain.ni.samuraigraph.base.SGIFigureElementGrid;
import jp.riken.brain.ni.samuraigraph.base.SGIFigureElementLegend;
import jp.riken.brain.ni.samuraigraph.base.SGIMovable;
import jp.riken.brain.ni.samuraigraph.base.SGISelectable;
import jp.riken.brain.ni.samuraigraph.base.SGIFigureElementShape;
import jp.riken.brain.ni.samuraigraph.base.SGIFigureElementSignificantDifference;
import jp.riken.brain.ni.samuraigraph.base.SGIFigureElementString;
import jp.riken.brain.ni.samuraigraph.base.SGIFigureElementTimingLine;
import jp.riken.brain.ni.samuraigraph.base.SGIUndoable;
import jp.riken.brain.ni.samuraigraph.base.SGProperties;
import jp.riken.brain.ni.samuraigraph.base.SGPropertyDialog;
import jp.riken.brain.ni.samuraigraph.base.SGTuple2f;
import jp.riken.brain.ni.samuraigraph.base.SGUtility;
import jp.riken.brain.ni.samuraigraph.base.SGUtilityNumber;
import jp.riken.brain.ni.samuraigraph.base.SGUtilityText;
import jp.riken.brain.ni.samuraigraph.data.SGISXYTypeData;
import jp.riken.brain.ni.samuraigraph.data.SGISXYTypeMultipleData;
import jp.riken.brain.ni.samuraigraph.data.SGITwoDimensionalData;
import jp.riken.brain.ni.samuraigraph.data.SGIVXYTypeData;
import jp.riken.brain.ni.samuraigraph.figure.SGDrawingElementArrow;
import jp.riken.brain.ni.samuraigraph.figure.SGDrawingElementBar;
import jp.riken.brain.ni.samuraigraph.figure.SGDrawingElementErrorBar;
import jp.riken.brain.ni.samuraigraph.figure.SGDrawingElementLine;
import jp.riken.brain.ni.samuraigraph.figure.SGDrawingElementRectangle;
import jp.riken.brain.ni.samuraigraph.figure.SGDrawingElementString;
import jp.riken.brain.ni.samuraigraph.figure.SGDrawingElementSymbol;
import jp.riken.brain.ni.samuraigraph.figure.SGElementGroup;
import jp.riken.brain.ni.samuraigraph.figure.SGElementGroupSet;
import jp.riken.brain.ni.samuraigraph.figure.SGFigureElement;
import jp.riken.brain.ni.samuraigraph.figure.SGIArrowConstants;
import jp.riken.brain.ni.samuraigraph.figure.SGIBarConstants;
import jp.riken.brain.ni.samuraigraph.figure.SGIErrorBarConstants;
import jp.riken.brain.ni.samuraigraph.figure.SGIFigureDrawingElementConstants;
import jp.riken.brain.ni.samuraigraph.figure.SGILegendConstants;
import jp.riken.brain.ni.samuraigraph.figure.SGILineConstants;
import jp.riken.brain.ni.samuraigraph.figure.SGISXYDataConstants;
import jp.riken.brain.ni.samuraigraph.figure.SGIStringConstants;
import jp.riken.brain.ni.samuraigraph.figure.SGISymbolConstants;
import jp.riken.brain.ni.samuraigraph.figure.SGITickLabelConstants;
import jp.riken.brain.ni.samuraigraph.figure.SGIVXYDataConstants;
import jp.riken.brain.ni.samuraigraph.figure.SGUtilityForFigureElement;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;



/**
 * The legend which displays symbols of data objects.
 */
public class SGFigureElementLegend extends SGFigureElement
	implements SGIFigureElementLegend, SGIStringConstants,
		CaretListener, ActionListener, SGILegendConstants,
		SGIFigureDrawingElementConstants,
		SGIMovable, SGISelectable, SGILegendDialogObserver
{

	/**
	 *
	 */
	private SGIFigureElementGraph mGraphElement = null;

	
	/**
	 * 
	 */
	private SGIFigureElementAxis mAxisElement = null;
	

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


	
	/**
	 * 
	 */
	private SGAxis mXAxis = null;

	
	
	/**
	 * 
	 */
	private SGAxis mYAxis = null;

	

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


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


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


	/**
	 * 
	 */
	private float mFontSize;


	/**
	 * 
	 */
	private int mFontStyle;


	/**
	 * 
	 */
	private String mFontName;


	/**
	 * 
	 */
	private Color mFontColor;



	/**
	 * 
	 */
	private float mSymbolSpan;


	/**
	 * 
	 */
	private float mFrameLineWidth;


	/**
	 * 
	 */
	private Color mFrameLineColor;


	/**
	 * 
	 */
	private Color mBackgroundColor;



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


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


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


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


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


	/**
	 * A dialog to set properties of legend.
	 */
	private SGLegendDialog mLegendDialog;


	/**
	 * A dialog to set properties of data.
	 */
	private SGPropertyDialogSXYData mSXYDataDialog;
	private SGPropertyDialogVXYData mVXYDataDialog;


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


	/**
	 * 
	 */
	public static final String MENUCMD_HIDE = "Hide";


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

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



	/**
	 * 
	 */
	private boolean init()
	{
		this.setLegendVisible( DEFAULT_LEGEND_VISIBLE );
		this.setFontName( DEFAULT_LEGEND_FONT_NAME );
		this.setFontSize( DEFAULT_LEGEND_FONT_SIZE, FONT_SIZE_UNIT );
		this.setFontStyle( DEFAULT_LEGEND_FONT_STYLE );
		this.setFontColor( DEFAULT_LEGEND_FONT_COLOR );
		this.setFrameVisible( DEFAULT_LEGEND_FRAME_VISIBLE );
		this.setFrameLineWidth( DEFAULT_LEGEND_FRAME_WIDTH, LINE_WIDTH_UNIT );
		this.setFrameLineColor( DEFAULT_LEGEND_FRAME_COLOR );
		this.setBackgroundColor( DEFAULT_LEGEND_BACKGROUND_COLOR );
		this.setBackgroundTransparent( DEFAULT_LEGEND_TRANSPARENT );
		this.setSymbolSpan( DEFAULT_LEGEND_SYMBOL_SPAN, SYMBOL_SPAN_UNIT );

		//
		this.createPopupMenu();

		return true;
	}



	public void dispose()
	{
		super.dispose();

		this.mLegendDialog.dispose();
		this.mLegendDialog = null;
		this.mAxisElement = null;
		this.mFocusedGroup = null;
		this.mGraphElement = null;
		if( this.mSXYDataDialog!=null )
		{
			this.mSXYDataDialog.dispose();
			this.mSXYDataDialog = null;
		}
		if( this.mVXYDataDialog!=null )
		{
			this.mVXYDataDialog.dispose();
			this.mVXYDataDialog = null;
		}
		this.mTextField = null;
		this.mPopupMenu = null;
		this.mBackgroundColor = null;
		this.mFontName = null;
		this.mFrameLineColor = null;


		this.mLegendList.clear();
		this.mLegendList = null;
	}



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

		p.add( new JLabel( "  -- Legend --" ) );
		p.addSeparator();

		SGUtility.addItem( p, this, MENUCMD_HIDE );

		p.addSeparator();

		SGUtility.addItem( p, this, MENUCMD_PROPERTY );

		return true;
	}



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


	/**
	 * 
	 * @return
	 */
	public String getClassDescription()
	{
		return "Legend";
	}


	/**
	 *
	 */
	public boolean addData( final SGData data, final String name )
	{

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

		if( super.addData( data, name ) == false )
		{
			return false;
		}

		// create legend
		ElementGroupSetInLegend legend = this.createGroupSet( data, name );
		this.updateAllDrawingElements();

		// call one more time
		this.updateAllDrawingElements();

		// set properties on start-up
		if( this.mStartFlag )
		{
			this.onStartup(data);
		}

		this.updateSymbolsVisibleAroundFocusedObjects();

		return true;
	}



	/**
	 *
	 */
	public boolean addData(
		final SGData data, final String name, final SGProperties p )
	{

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

		if( super.addData( data, name, p ) == false )
		{
			return false;
		}

		// create legend
		ElementGroupSetInLegend legend = this.createGroupSet( data, name );
		if( legend.setWholeProperties(p) == false )
		{
			return false;
		}
		this.updateAllDrawingElements();

		// set properties on start-up
		if( this.mStartFlag )
		{
			this.onStartup(data);
		}

		this.updateSymbolsVisibleAroundFocusedObjects();

		return true;
	}



	private ElementGroupSetInLegend createGroupSet( SGData data, String name )
	{
		//
		// レジェンドの要素を新規作成
		//

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


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


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


		return legend;		
	}



	/**
	 * called on the start-up
	 * @param data
	 */
	private void onStartup( SGData data )
	{
		// set the location of the legend
		// to the north-east point of the graph area
		final float x = this.getGraphRectX()
			+ this.getGraphRectWidth() - this.mMagnification*this.getLegendWidth();
		final float y = this.getGraphRectY();
		this.setLegendLocation( x, y );

		// set axes
		SGAxis xAxis = this.mAxisElement.getAxis( DEFAULT_LEGEND_HORIZONTAL_AXIS );
		SGAxis yAxis = this.mAxisElement.getAxis( DEFAULT_LEGEND_PERPENDICULAR_AXIS );
		this.mXAxis = xAxis;
		this.mYAxis = yAxis;

		// create a property dialog for data
		this.createDataDialog( data );

		this.updateAllDrawingElements();

		this.mStartFlag = false;
	}


	private void createDataDialog( SGData data )
	{
		if( data instanceof SGISXYTypeData | data instanceof SGISXYTypeMultipleData )
		{
			if( this.mSXYDataDialog == null )
			{
				this.mSXYDataDialog = new SGPropertyDialogSXYData( this.mDialogOwner, true );
			}
		}
		else if( data instanceof SGIVXYTypeData )
		{
			if( this.mVXYDataDialog == null )
			{
				this.mVXYDataDialog = new SGPropertyDialogVXYData( this.mDialogOwner, true );
			}
		}
	}


	private SGPropertyDialog showDataDialog( ElementGroupSetInLegend legend )
	{
		SGPropertyDialog dg = null;
		if( legend instanceof ElementGroupSetInLegendSXY )
		{
			ElementGroupSetInLegendSXY legendSXY = (ElementGroupSetInLegendSXY)legend;
			
			dg = this.mSXYDataDialog;

		}
		else if( legend instanceof ElementGroupSetInLegendVXY )
		{
			dg = this.mVXYDataDialog;
		}

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

		// set proeprties to the dialog
		dg.addPropertyDialogObserver(legend);
		dg.setDialogProperty();
		dg.setColorButtonBorder( true );

		// create temporary objects
		legend.prepare();

		// show the dialog
		dg.setVisible(true);

		dg.removeAllPropertyDialogObserver();


		// notify to the root
		this.notifyToRoot();


		return dg;
	}


	// used only on the start-up
	private boolean mStartFlag = true;
	


	/**
	 * 
	 */
	private ElementGroupSetInLegend createLegendElement( final SGData data, final String name )
	{

		ElementGroupSetInLegend legend = null;
		if( ( data instanceof SGISXYTypeData )
			| ( data instanceof SGISXYTypeMultipleData ) )
		{
			legend = new ElementGroupSetInLegendSXY();
		}
		else if( data instanceof SGIVXYTypeData )
		{
			legend = new ElementGroupSetInLegendVXY();
		}
		else
		{
			return null;
		}


		// name of data
		legend.setName( name );


		// axes
		if( data instanceof SGITwoDimensionalData )
		{
			SGIFigureElementAxis aElement = this.mAxisElement;

			// get axes list
			final SGAxis bAxis = aElement.getAxisInPlane( SGIFigureElementAxis.AXIS_HORIZONTAL_1 );
			final SGAxis tAxis = aElement.getAxisInPlane( SGIFigureElementAxis.AXIS_HORIZONTAL_2 );
			final SGAxis lAxis = aElement.getAxisInPlane( SGIFigureElementAxis.AXIS_PERPENDICULAR_1 );
			final SGAxis rAxis = aElement.getAxisInPlane( SGIFigureElementAxis.AXIS_PERPENDICULAR_2 );
			SGAxis axisX = null;
			SGAxis axisY = null;
			if( DEFAULT_LEGEND_SCALE_REFERENCE.equals( SGIFigureElementAxis.LEFT_BOTTOM ) )
			{
				axisX = bAxis;
				axisY = lAxis;
			}
			else if( DEFAULT_LEGEND_SCALE_REFERENCE.equals( SGIFigureElementAxis.LEFT_TOP ) )
			{
				axisX = tAxis;
				axisY = lAxis;
			}
			else if( DEFAULT_LEGEND_SCALE_REFERENCE.equals( SGIFigureElementAxis.RIGHT_BOTTOM ) )
			{
				axisX = bAxis;
				axisY = rAxis;
			}
			else if( DEFAULT_LEGEND_SCALE_REFERENCE.equals( SGIFigureElementAxis.RIGHT_TOP ) )
			{
				axisX = tAxis;
				axisY = rAxis;
			}
			else
			{
				return null;
			}

			legend.setXAxis(axisX);
			legend.setYAxis(axisY);
		}
		else
		{
			// not supported
			return null;
		}


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

				if( element instanceof SGDrawingElementErrorBar )
				{
					legend.addDrawingElementGroup( SGIElementGroupConstants.ERROR_BAR_GROUP );
				}
				else if( element instanceof SGDrawingElementLine )
				{
					legend.addDrawingElementGroup( SGIElementGroupConstants.POLYLINE_GROUP );
				}
				else if( element instanceof SGDrawingElementRectangle )
				{
					legend.addDrawingElementGroup( SGIElementGroupConstants.RECTANGLE_GROUP );

					// set bar width when data is added
					{
						ElementGroupBar groupBar = (ElementGroupBar)legend.getBarGroup();
						SGAxis axisX = legend.getXAxis();
						double[] xArray = null;
						if( data instanceof SGISXYTypeData )
						{
							xArray = ((SGISXYTypeData)data).getXValueArray();
						}
						else if( data instanceof SGISXYTypeMultipleData )
						{
							xArray = ((SGISXYTypeMultipleData)data).getXValueArray();
						}

						double minDiff = Double.MAX_VALUE;
						for( int jj=0; jj<xArray.length-1; jj++ )
						{
							final double diff = Math.abs( xArray[jj+1] - xArray[jj] );
							if( diff < minDiff )
							{
								minDiff = diff;
							}
						}
						minDiff = getNumberInRangeOrder( minDiff, axisX );
						groupBar.setWidthValue( minDiff );
					}

				}
				else if( element instanceof SGDrawingElementSymbol )
				{
					legend.addDrawingElementGroup( SGIElementGroupConstants.SYMBOL_GROUP );
				}
				else if( element instanceof SGDrawingElementString )
				{
					legend.addDrawingElementGroup( SGIElementGroupConstants.TICK_LABEL_GROUP );
				}
				else
				{
					throw new Error();
				}
			}
		}
		else if( data instanceof SGIVXYTypeData )
		{
			for( int ii=0; ii<elementList.size(); ii++ )
			{
				SGDrawingElement element = (SGDrawingElement)elementList.get(ii);

				if( element instanceof SGDrawingElementArrow )
				{
					legend.addDrawingElementGroup( SGIElementGroupConstants.ARROW_GROUP );
				}
				else
				{
					throw new Error();
				}
			}

			ElementGroupSetInLegendVXY legendVXY = (ElementGroupSetInLegendVXY)legend;
			SGIVXYTypeData dataVXY = (SGIVXYTypeData)data;

			// set the scaling factor
			final float percm
				= SGUtilityForFigureElement.getInitialMagnitudePerCM( dataVXY, this );
			legendVXY.setMagnitudePerCM( percm );
			legendVXY.setDirectionInvariant( dataVXY.isPolar() );
		}
		else
		{
			throw new Error("This data-type is not defined.");
		}


		// visible in legend
		boolean visibleInLegend = this.mGraphElement.getVisibleInLegendFlag( data );
		legend.setVisibleInLegend( visibleInLegend );


		legend.initPropertiesHistory();

		return legend;

	}



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



	/**
	 * 
	 */
	public boolean getFocusedObjectsList( ArrayList list )
	{
		if( this.isSelected() )
		{
			list.add( this );
		}
		return true;
	}


	/**
	 * 
	 *
	 */
	public boolean hideSelectedObject( SGISelectable s )
	{
		return true;
	}


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

		return null;
	}


	/**
	 * 
	 */
	public boolean isDataVisible( SGData data )
	{
		ElementGroupSetInLegend groupSet
			= (ElementGroupSetInLegend)this.getElementGroupSet(data);
		return groupSet.isVisible();
	}


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

		return null;
	}



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

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

		ArrayList list = new ArrayList();

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

		return list;
	}


	/**
	 * 
	 */
	public SGAxis getXAxis( final SGData data )
	{
		final ElementGroupSetInLegend groupSet = this.getElementGroupSet(data);
		
		if( groupSet != null )
		{
			return groupSet.getXAxis();
		}

		return null;
	}


	/**
	 * 
	 */
	public SGAxis getYAxis( final SGData data )
	{
		final ElementGroupSetInLegend groupSet = this.getElementGroupSet(data);
		
		if( groupSet != null )
		{
			return groupSet.getYAxis();
		}

		return null;
	}


	/**
	 * 
	 */
	public SGAxis getZAxis( final SGData data )
	{
		final ElementGroupSetInLegend groupSet = this.getElementGroupSet(data);
		
		if( groupSet != null )
		{
			return groupSet.mZAxis;
		}

		return null;
	}



	/**
	 * 
	 */
	private boolean mSelectedFlag = false;
	
	/**
	 * 
	 */
	public void setSelected( final boolean b )
	{
		this.mSelectedFlag = b;
	}
	

	/**
	 * 
	 */
	public boolean isSelected()
	{
		return this.mSelectedFlag;
	}

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



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


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


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



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



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


	/**
	 * 
	 * @param value
	 */
	public boolean setXValue( final double value )
	{
		SGAxis axis = this.mXAxis;
			
		// current values gotten from the position of legend
		double currentValue = calcValue( this.getComponent().getX(), axis, true );
		currentValue = getNumberInRangeOrder( currentValue, axis );


		// if values from the dialog is diffrent from the current values,
		// set the values from the dialog

		float x;
		if( value==currentValue )
		{
			x = this.mLegendX;
		}
		else
		{
			final float x_ = calcLocation( value, axis, true );
			x = ( x_ - this.mGraphRectX )/this.mMagnification;
		}

		this.mLegendX = x;

		this.updateAllDrawingElements();
		
		return true;
	}


	/**
	 * 
	 * @param value
	 */
	public boolean setYValue( final double value )
	{
		SGAxis axis = this.mYAxis;
			
		// current values gotten from the position of legend
		double currentValue = calcValue( this.getComponent().getY(), axis, false );
		currentValue = getNumberInRangeOrder( currentValue, axis );


		// if values from the dialog is diffrent from the current values,
		// set the values from the dialog

		float y;
		if( value==currentValue )
		{
			y = this.mLegendY;
		}
		else
		{
			final float y_ = calcLocation( value, axis, false );
			y = ( y_ - this.mGraphRectY )/this.mMagnification;
		}

		this.mLegendY = y;

		this.updateAllDrawingElements();

		return true;
	}

	
	

	/**
	 * 
	 * @param config
	 * @param value
	 * @return
	 */
	public boolean hasValidXAxisValue( final int config, final Number value )
	{
		final SGAxis axis = (config==-1) ? this.mXAxis : this.mAxisElement.getAxisInPlane( config );
		final double v = (value!=null) ? value.doubleValue() : this.getXValue();
		return axis.isValidValue(v);
	}

	/**
	 * 
	 * @param config
	 * @param value
	 * @return
	 */
	public boolean hasValidYAxisValue( final int config, final Number value )
	{
		final SGAxis axis = (config==-1) ? this.mYAxis : this.mAxisElement.getAxisInPlane( config );
		final double v = (value!=null) ? value.doubleValue() : this.getYValue();
		return axis.isValidValue(v);
	}


	
	/**
	 * 
	 */
	public void translate( final float dx, final float dy )
	{
		this.setLegendLocation(
			this.getLegendX() + dx, this.getLegendY() + dy );
		this.updateAllDrawingElements();
	}


	/**
	 * 
	 * @return
	 */
	public double getXValue()
	{
		SGAxis axis = this.mXAxis;
		double value = calcValue( this.getLegendX(), axis, true );
		if( value==Double.NaN )
		{
			return value;
		}

		value = getNumberInRangeOrder( value, axis );
		return value;
	}

	
	/**
	 * 
	 * @return
	 */
	public double getYValue()
	{
		SGAxis axis = this.mYAxis;
		double value = calcValue( this.getLegendY(), axis, false );
		if( value==Double.NaN )
		{
			return value;
		}

		value = getNumberInRangeOrder( value, axis );
		return value;
	}


	/**
	 * 
	 */
	private boolean initEditField()
	{
		this.mTextField.setVisible(false);
		this.mTextField.addActionListener(this);
		this.mTextField.addCaretListener(this);

		return true;
	}


	public void setComponent( JComponent com )
	{
		super.setComponent(com);
		com.add(this.mTextField);
	}



	/**
	 * 
	 * @return
	 */
	public boolean clearFocusedObjects()
	{
		if( super.clearFocusedObjects() == false )
		{
			return false;
		}

		if( this.mTextField.isVisible() )
		{
			this.terminateEditField();
		}
		this.clearFocusedGroup();

		return true;
	}




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



	/**
	 * 
	 */
	public boolean prepare()
	{
		this.mTemporaryProperties = this.getProperties();
		return true;
	}



	/**
	 * 
	 */
	private boolean createDialog()
	{
		SGLegendDialog dg = new SGLegendDialog( this.mDialogOwner, true );
		this.mLegendDialog = dg;
		return true;
	}



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

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

		p.visible = this.isLegendVisible();
		p.frameLineVisible = this.isFrameLineVisible();
		p.frameLineWidth = this.getFrameLineWidth();
		p.frameLineColor = this.getFrameLineColor();
		p.backgroundColor = this.getBackgroundColor();
		p.transparent = this.isBackgroundTransparent();
		p.fontName = this.getFontName();
		p.fontSize = this.getFontSize();
		p.fontStyle = this.getFontStyle();
		p.stringColor = this.getStringColor();
		p.symbolSpan = this.getSymbolSpan();

		p.xAxis = this.mXAxis;
		p.yAxis = this.mYAxis;
		
		return p;
	}


	/**
	 * 
	 */
	public SGProperties getDataProperties( SGData data )
	{
		final ElementGroupSetInLegend groupSet
			= this.getElementGroupSet(data);
		if( groupSet != null )
		{
			return groupSet.getWholeProperties();
		}
		return null;
	}



	/**
	 * 
	 */
	public SGProperties getProperties()
	{
		LegendCommonProperties wp = new LegendCommonProperties();
		wp = (LegendCommonProperties)this.getCommonProperties();
		return wp;
	}



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

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

		LegendCommonProperties wp = (LegendCommonProperties)p;

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

		return true;
	}



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



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

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

		this.setLegendVisible( p.visible );
		this.setFrameVisible( p.frameLineVisible );
		this.setFrameLineWidth( p.frameLineWidth );
		this.setFrameLineColor( p.frameLineColor );
		this.setBackgroundColor( p.backgroundColor );
		this.setBackgroundTransparent( p.transparent );
		this.setFontName( p.fontName );
		this.setFontSize( p.fontSize );
		this.setFontStyle( p.fontStyle );
		this.setFontColor( p.stringColor );
		this.setSymbolSpan( p.symbolSpan );

		this.mXAxis = p.xAxis;
		this.mYAxis = p.yAxis;
		
		return true;
	}



	private static final float MARGIN_HORIZONTAL = 6.0f;
	private static final float MARGIN_VERTICAL = 6.0f;
	private final static float marginTop = MARGIN_VERTICAL;
	private final static float marginBottom = MARGIN_VERTICAL;
	private final static float marginLeft = MARGIN_HORIZONTAL;
	private final static float marginRight = MARGIN_HORIZONTAL;
	private final static float spaceDataAndString = MARGIN_HORIZONTAL;
	private final static float spaceLegend = MARGIN_VERTICAL;


	/**
	 * create all drawing elements
	 */
	private boolean updateAllDrawingElements()
	{
		final float mag = this.mMagnification;

		// get visible legend array
		final ArrayList visibleGroupSetList = this.getVisibleTotallyLegendList();
		final int num = visibleGroupSetList.size();
		final ElementGroupSetInLegend[] legendArray = new ElementGroupSetInLegend[num];
		for( int ii=0; ii<num; ii++ )
		{
			legendArray[ii] = (ElementGroupSetInLegend)visibleGroupSetList.get(ii);
		}

		// create string elements
		for( int ii=0; ii<num; ii++ )
		{
			legendArray[ii].createStringElement();
		}

		// get the bounding box of string elements
		final Rectangle2D[] stringBoundsArray = new Rectangle2D[num];
		for( int ii=0; ii<num; ii++ )
		{
			stringBoundsArray[ii] = legendArray[ii].getStringBounds();
		}

		// get height of string elements
		final float[] stringHeightArray = new float[num];
		for( int ii=0; ii<num; ii++ )
		{
			stringHeightArray[ii] = (float)stringBoundsArray[ii].getHeight();
		}

		// max width of string elements
		float stringWidthMax = 0.0f;
		for( int ii=0; ii<num; ii++ )
		{
			float width = (float)stringBoundsArray[ii].getWidth();
			if( width > stringWidthMax )
			{
				stringWidthMax = width;
			}
		}

		// max width of drawing elements
		float dataWidthMax = this.getSymbolSpan();
		for( int ii=0; ii<num; ii++ )
		{
			final float width = legendArray[ii].getMaxDataElementWidth()/mag;
			if( width > dataWidthMax )
			{
				dataWidthMax = width;
			}
		}


		// legend width in the default zoom
		final float legendWidth
			= dataWidthMax + stringWidthMax/mag + spaceDataAndString;


		// height array of drawing elements
		final double[] dataHeightArray = new double[num];
		for( int ii=0; ii<num; ii++ )
		{
			dataHeightArray[ii] = legendArray[ii].getMaxDataElementHeight();
		}


		// total height array
		float[] legendHeightArray = new float[num];
		for( int ii=0; ii<num; ii++ )
		{
			legendHeightArray[ii]
				= (float)Math.max( dataHeightArray[ii], stringHeightArray[ii] );
		}


		// rectangle array of legend
		Rectangle2D[] legendRectArray = new Rectangle2D[num];
		float rectY = this.getLegendY() + mag*marginTop;
		final float lx = this.getLegendX() + mag*marginLeft;
		final float lw = mag*legendWidth;
		for( int ii=0; ii<num; ii++ )
		{
			final float ly = rectY;
			final float lh = legendHeightArray[ii];
			legendRectArray[ii] = new Rectangle2D.Float(lx,ly,lw,lh);
			rectY += lh + mag*spaceLegend;
		}


		// set bounds
		for( int ii=0; ii<num; ii++ )
		{
			legendArray[ii].setRect( legendRectArray[ii] );
		}

		final float w = mag*dataWidthMax;
		for( int ii=0; ii<num; ii++ )
		{
			final float x = (float)legendRectArray[ii].getX();
			final float y = (float)legendRectArray[ii].getY();
			final float h = (float)legendArray[ii].getMaxDataElementHeight();
			final Rectangle2D dRect = new Rectangle2D.Float(x,y,w,h);
			legendArray[ii].setDrawingElementBounds(dRect);
		}


		// legend height in the default zoom
		float legendHeight = 0.0f;
		for( int ii=0; ii<num; ii++ )
		{
			legendHeight += legendHeightArray[ii]/mag;
		}
		legendHeight += (num-1)*spaceLegend;


		// create drawing elements of each object
		for( int ii=0; ii<num; ii++ )
		{
			legendArray[ii].createDrawingElement();
		}


		// set location of string elements
		final float sx	= this.getLegendX() + mag*( marginLeft + dataWidthMax + spaceDataAndString );
		for( int ii=0; ii<num; ii++ )
		{
			final float sy = (float)legendRectArray[ii].getY()
				- 0.50f * stringHeightArray[ii]
				+ 0.50f * legendHeightArray[ii]
				+ (float)stringBoundsArray[ii].getY();
			legendArray[ii].getStringElement().setLocation( sx, sy );
		}


		// set to attributes
		this.mLegendWidth = marginLeft + legendWidth + marginRight;
		this.mLegendHeight = marginTop + legendHeight + marginBottom;

		return true;
	}




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

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

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

		return true;
	}




	/**
	 * 
	 */
	public void paintGraphics( Graphics g, boolean clip )
	{
		final Graphics2D g2d = (Graphics2D)g;

		if( this.isLegendVisible() )
		{

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


			// グラフの描画
			ArrayList list = this.getVisibleTotallyLegendList();
			for( int ii=0; ii<list.size(); ii++ )
			{
				ElementGroupSetInLegend groupSet
					= (ElementGroupSetInLegend)list.get(ii);
				groupSet.paintGraphics2D( g2d );
			}


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

			// draw symbols around all objects
			if( this.mSymbolsVisibleFlagAroundAllObjects & list.size()!=0 )
			{
				ArrayList pList = this.getAnchorPointList();
				SGUtilityForFigureElementJava2D.drawAnchorAsChildObject( pList, g2d );
			}

			
			// draw symbols around focused objects
			if( this.mSymbolsVisibleFlagAroundFocusedObjects & this.isSelected() )
			{
				ArrayList pList = this.getAnchorPointList();
				SGUtilityForFigureElementJava2D.drawAnchorAsFocusedObject( pList, g2d );
			}

		}

	}


	/**
	 *
	 *
	 */
	private void updateSymbolsVisibleAroundFocusedObjects()
	{
		ArrayList list = this.getVisibleTotallyLegendList();
		this.setSymbolsVisibleAroundFocusedObjects( list.size()!=0 );
	}



	private ArrayList getAnchorPointList()
	{
		ArrayList list = new ArrayList();
		
		Rectangle2D rect = this.getLegendRect();
		final float x = (float)rect.getX();
		final float y = (float)rect.getY();
		final float w = (float)rect.getWidth();
		final float h = (float)rect.getHeight();
			
		Point2D nw = new Point2D.Float(x,y);
		Point2D sw = new Point2D.Float(x,y+h);
		Point2D ne = new Point2D.Float(x+w,y);
		Point2D se = new Point2D.Float(x+w,y+h);

		list.add( nw );
		list.add( sw );
		list.add( ne );
		list.add( se );
		
		return list;
	}



	/**
	 * 
	 * @param g2d
	 */
	private void drawLegendFrameLines( final Graphics2D g2d )
	{
		if( g2d==null )
		{
			return;
		}

		ArrayList list = this.getVisibleTotallyLegendList();
		if( list.size() == 0 )
		{
			return;
		}

		g2d.setPaint( this.mFrameLineColor );

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

		g2d.draw( this.getLegendRect() );

	}



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



	/**
	 * Overrode to remove a object related to the data.
	 */
	public boolean removeData( final SGData data )
	{
		// remove group set
		SGElementGroupSet groupSet = this.getElementGroupSet(data);
		this.mLegendList.remove(groupSet);

		// remove data
		return super.removeData(data);
	}


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

		return false;
	}



	/**
	 * 同期を取る
	 */
	public boolean synchronize( SGIFigureElement element, String msg )
	{

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

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

			SGIFigureElementGraph gElement = (SGIFigureElementGraph)element;
			flag = this.synchronizeToGraphElement( gElement, msg );
		}
		else if( element instanceof SGIFigureElementString )
		{
			
		}
		else if( element instanceof SGIFigureElementLegend )
		{
			
		}
		else if( element instanceof SGIFigureElementAxisBreak )
		{
			
		}
		else if( element instanceof SGIFigureElementSignificantDifference )
		{
			
		}
		else if( element instanceof SGIFigureElementTimingLine )
		{
			
		}
		else if( element instanceof SGIFigureElementGrid )
		{

		}
		else if( element instanceof SGIFigureElementShape )
		{

		}
		else
		{
			flag = element.synchronizeArgument( this, msg );
		}


		return flag;
	}



	/**
	 * 
	 */
	private boolean synchronizeToGraphElement( final SGIFigureElementGraph element, final String msg )
	{

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

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


//		// axes
//		for( int ii=0; ii<groupSetListNew.size(); ii++ )
//		{
//			SGData data = (SGData)dataListNew.get(ii);
//			ElementGroupSetInLegend legend
//				= (ElementGroupSetInLegend)groupSetListNew.get(ii);
//			legend.setXAxis( element.getXAxis(data) );
//			legend.setYAxis( element.getYAxis(data) );
//			legend.setZAxis( element.getZAxis(data) );
//		}


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

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

			boolean diffFlag = false;

			SGProperties wp = element.getDataProperties(data);
			SGProperties wp_ = legend.getWholeProperties();

//System.out.println("legend:"+msg+"  "+wp.equals(wp_));

//			if( !wp.equals(wp_) )
			if( !wp.equals(wp_) & !msg.equals( SGIFigureElement.NOTIFY_CHANGE_ON_UNDO ) )
			{
				diffFlag = true;
			}


//			// name of data
//			String nameNew = element.getDataName(data);
//			String nameOld = legend.getName();
//			if( nameNew.equals( nameOld ) == false )
//			{
//				diffFlag = true;
//			}
//			legend.setName( nameNew );
//
//			// visible
//			boolean visibleFlag = element.isDataVisible(data);
//			if( visibleFlag != legend.isVisible() )
//			{
//				diffFlag = true;
//			}
//			legend.setVisible( visibleFlag );
//
//			// drawing element of data
//			ArrayList sList = element.getDrawingElementList(data);
//			final boolean diff_ = legend.synchronizeDrawingElements(sList);
//			if( diff_ )
//			{
//				diffFlag = true;
//			}
//
//			// visible in legend
//			boolean visibleInLegend = element.getVisibleInLegendFlag( data );
//			if( visibleInLegend != legend.isVisibleInLegend() )
//			{
//				diffFlag = true;
//			}
//			legend.setVisibleInLegend( visibleInLegend );
//
//			// set changed flag
//			if( diffFlag )
//			{
//				legend.setChanged(true);
//			}

			if( legend.setWholeProperties(wp) == false )
			{
				return false;
			}

		}


//		if( element instanceof SGIVXYGraphElement )
//		{
//			SGIVXYGraphElement vg = (SGIVXYGraphElement)element;
//
//			for( int ii=dataListNew.size()-1; ii>=0; ii-- )
//			{
//				SGData data = (SGData)dataListNew.get(ii);
//				final float f = vg.getMagnitudeScalingFactor(data);
//				ElementGroupSetInLegendVXY legend
//					= (ElementGroupSetInLegendVXY)groupSetListNew.get(ii);
//				legend.setMagnitudeScalingFactor(f);
//			}
//		}

		this.updateAllDrawingElements();			
		this.updateSymbolsVisibleAroundFocusedObjects();


		return true;
	}




	/**
	 * Synchronize the element given by the argument.
	 * @param element An object to be synchronized.
	 */
	public boolean synchronizeArgument( final SGIFigureElement element, final String msg )
	{
	    // this shouldn't happen
	    throw new Error();
	}


	/**
	 * ズーム
	 */
	public boolean zoom( final float ratio )
	{
		if( super.zoom(ratio) == false )
		{
			return false;
		}

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

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


		// 描画要素を作成
		this.updateAllDrawingElements();

		return true;
	}





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

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


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


		ArrayList list = new ArrayList();
		list.add( graphRect );
		if( this.isLegendVisible() )
		{
			list.add( lRect );
		}

		Rectangle2D uniRect = SGUtility.createUnion(list);

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

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

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

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

//System.out.println();

		return true;
	}




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

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

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

		Rectangle2D rect = this.getLegendRect();
		if( rect.contains(x,y) )
		{
			ArrayList gList = this.getVisibleTotallyLegendList();

			if( cnt==1 )
			{
				this.updateFocusedObjectsList( this, e );

				if( SwingUtilities.isLeftMouseButton(e) )
				{
					for( int ii=0; ii<gList.size(); ii++ )
					{
						ElementGroupSetInLegend legend
							= (ElementGroupSetInLegend)gList.get(ii);
						Rectangle2D sRect = legend.getStringElement().getElementBounds();
						if( sRect.contains(x,y) )
						{
							if( SwingUtilities.isLeftMouseButton(e) )
							{
								if( this.isSelected() )
								{
									this.showEditField(legend);
								}
							}
						}
					}
				}
				else if( SwingUtilities.isRightMouseButton(e) )
				{
					this.mPopupMenu.show( this.getComponent(), x, y );
				}
			}
			else if( cnt==2 )
			{

				for( int ii=0; ii<gList.size(); ii++ )
				{
					ElementGroupSetInLegend legend
						= (ElementGroupSetInLegend)gList.get(ii);

					ArrayList list = legend.getElementGroupList();
					for( int jj=list.size()-1; jj>=0; jj-- )
					{

						SGElementGroup group = (SGElementGroup)list.get(jj);
						if( group.isVisible() == false )
						{
							continue;
						}
	
						SGDrawingElement[] array = group.getDrawingElementArray();
						for( int kk=0; kk<array.length; kk++ )
						{
							if( array[kk].isVisible() == false )
							{
								continue;
							}
	
							final boolean b = array[kk].contains(x,y);
							if(b)
							{
								if( SwingUtilities.isLeftMouseButton(e) )
								{
									if( cnt==2 )
									{
										legend.onMouseClicked(e);
										this.showDataDialog(legend);
										return true;
									}
								}
							}
						}
					}
				}


				if( SwingUtilities.isLeftMouseButton(e) )
				{
					this.setPropertiesOfSelectedObjects();
				}
			}

			return true;
		}


		return false;
	}



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



	/**
	 * 
	 * @return
	 */
	public ArrayList getPropertyDialogObserverList()
	{
		return this.getFocusedObjectsList();
	}



	/**
	 * Returns a list of child nodes.
	 * @return a list of chid nodes
	 */
	public ArrayList getChildNodes()
	{
		return new ArrayList();
	}


	/**
	 * 
	 * @return
	 */
	public SGPropertyDialog getPropertyDialog()
	{
		return this.mLegendDialog;
	}


	/**
	 * 
	 */
	public String getFontName()
	{
		return this.mFontName;
	}



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


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


	/**
	 * 
	 */
	public float getFontSize( final String unit )
	{
		return (float)SGUtilityText.convertFromPoint( this.getFontSize(), unit );
	}


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


	/**
	 * 
	 */
	public float getFrameLineWidth( final String unit )
	{
		return (float)SGUtilityText.convertFromPoint( this.getFrameLineWidth(), unit );
	}


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


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


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


	/**
	 * @return
	 */
	public float getSymbolSpan()
	{
		return this.mSymbolSpan;
	}


	/**
	 * @return
	 */
	public float getSymbolSpan( final String unit )
	{
		return (float)SGUtilityText.convertFromPoint( this.getSymbolSpan(), unit );
	}



	/**
	 * @param f
	 */
	public boolean setSymbolSpan( final float w )
	{
		this.mSymbolSpan = w;
		return true;
	}


	/**
	 * @param f
	 */
	public boolean setSymbolSpan( final float w, final String unit )
	{
		final double conv = SGUtilityText.convert( w, unit, SYMBOL_SPAN_UNIT );
		if( conv < SYMBOL_SPAN_MIN ) return false;
		if( conv > SYMBOL_SPAN_MAX ) return false;

		this.setSymbolSpan( (float)SGUtilityText.convertToPoint( w, unit ) );
		return true;
	}


	/**
	 * 
	 */
	private boolean showEditField( ElementGroupSetInLegend legend )
	{
		this.mFocusedGroup = legend;
		JTextField tf = this.mTextField;

		final Rectangle2D rect = legend.getStringElement().getElementBounds();
		final float fontSize = this.getMagnification()*this.getFontSize();

		final int x = (int)( rect.getX() - tf.getInsets().left );
		final int y = (int)( rect.getY() -  fontSize/2.0f );
		final int w = (int)( rect.getWidth() + fontSize );
		final int h = (int)( rect.getHeight() + fontSize );
		tf.setLocation( x, y );
		tf.setSize( w, h );

		Font font = new Font( this.getFontName(), this.getFontStyle(), (int)(fontSize) );
		tf.setFont( font );
		tf.setForeground( this.mFontColor );
		tf.setText( legend.getName() );

		// show the text field
		tf.setVisible(true);
		tf.requestFocus();
		tf.setCaretPosition(0);

		return true;
	}


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


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



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

		this.repaint();

		return true;
	}



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

		if( !SGUtilityText.isValidString( str ) ) {
			return false;
		}


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


		//
		this.updateAllDrawingElements();


		// update the history
		if( before.equals(after) == false )
		{
			this.mFocusedGroup.setChanged( true );
		}

		notifyChange();

		this.notifyToRoot();

		return true;
	}



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



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



	/**
	 * 
	 * @param e
	 */
	public boolean onMousePressed( final MouseEvent e )
	{
		if( !isLegendVisible() )
		{
			return false;
		}

		if( this.mTextField.isVisible() )
		{
			this.terminateEditField();
		}

		Rectangle2D lRect = this.getLegendRect();
		if( lRect.contains( e.getX(), e.getY() ) )
		{
			this.mLegendLocation = new Point(
					(int)this.mLegendX,
					(int)this.mLegendY
				);
			this.mPressedPoint = e.getPoint();
			setMouseCursor( Cursor.MOVE_CURSOR );
			return true;
		}

		this.clearFocusedGroup();

		return false;
	}



	/**
	 * 
	 * @param e
	 */
	public boolean onMouseDragged( final MouseEvent e )
	{
		if( this.mPressedPoint==null )
		{
			return false;
		}

		
		// レジェンドの位置設定
		if( this.isSelected() )
		{
			final int dx = e.getX() - this.mPressedPoint.x;
			final int dy = e.getY() - this.mPressedPoint.y;
			this.translate(dx,dy);
			this.mPressedPoint = e.getPoint();

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

	}



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

		//
		if( this.mLegendLocation!=null )
		{
			if( this.isMoved() )
			{
				this.setChanged(true);
			}
		}


		Rectangle2D rect = this.getLegendRect();
		if( rect.contains( e.getPoint() ) )
		{
			setMouseCursor( Cursor.HAND_CURSOR );
		}
		else
		{
			setMouseCursor( Cursor.DEFAULT_CURSOR );
		}


		//
//		this.notifyToRoot();


		return true;
	}


	/**
	 * 
	 * @return
	 */
	public boolean setTemporaryPropertiesOfFocusedObjects()
	{
		this.mTemporaryProperties = this.getProperties();
		return true;
	}



	/**
	 * 
	 * @return
	 */
	public boolean setChangedFocusedObjects()
	{
		if( this.isSelected() )
		{
			SGProperties temp = this.mTemporaryProperties;
			if( temp!=null )
			{
				SGProperties p = this.getProperties();
				if( p.equals(temp)==false )
				{
					this.setChanged(true);
				}
			}
		}

		return true;
	}

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

		return rect;
	}



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

		Rectangle2D rect = this.getLegendRect();

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

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

	}



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

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

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

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



	/**
	 * 
	 * @param e
	 */
	public boolean onDrawingElement( final int x, final int y )
	{
		if( this.isLegendVisible() )
		{
			if( this.getLegendRect().contains(x,y) )
			{
				this.setMouseCursor( Cursor.HAND_CURSOR );
				return true;
			}
		}
		
		return false;
	}



	/**
	 * 
	 */
	public boolean setAxisElement( final SGIFigureElementAxis element )
	{
		this.mAxisElement = element;
		return true;
	}
	
	
	
	/**
	 *
	 */
	public boolean setGraphElement( final SGIFigureElementGraph element )
	{
		this.mGraphElement = element;
		return true;
	}



	/**
	 * 
	 */
	public int getXAxisLocation()
	{
		return this.mAxisElement.getLocationInPlane( this.mXAxis );
	}


	/**
	 * 
	 */
	public int getYAxisLocation()
	{
		return this.mAxisElement.getLocationInPlane( this.mYAxis );
	}


	/**
	 * 
	 */
	public boolean setXAxisLocation( final int config )
	{
		if( config!=SGIFigureElementAxis.AXIS_HORIZONTAL_1
			& config!=SGIFigureElementAxis.AXIS_HORIZONTAL_2 )
		{
			return false;
		}
		this.mXAxis = this.getAxis(config);
		return true;
	}

	/**
	 * 
	 */
	public boolean setYAxisLocation( final int config )
	{
		if( config!=SGIFigureElementAxis.AXIS_PERPENDICULAR_1
			& config!=SGIFigureElementAxis.AXIS_PERPENDICULAR_2 )
		{
			return false;
		}
		this.mYAxis = this.getAxis(config);
		return true;
	}

	private SGAxis getAxis( final int config )
	{
		return this.mAxisElement.getAxisInPlane( config );
	}


	/**
	 * 
	 */
	public void setVisible( final boolean b )
	{
		this.mLegendVisibleFlag = b;
	}


	/**
	 * 
	 */
	public boolean setLegendVisible( final boolean b )
	{
		this.setVisible(b);
		return true;
	}


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


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


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


	/**
	 * 
	 */
	public boolean setFrameLineWidth( final float width, final String unit )
	{
		final double conv = SGUtilityText.convert( width, unit, LINE_WIDTH_UNIT );
		if( conv < LINE_WIDTH_MIN_VALUE ) return false;
		if( conv > LINE_WIDTH_MAX_VALUE ) return false;

		return this.setFrameLineWidth( (float)SGUtilityText.convertToPoint( width, unit ) );
	}


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


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


	/**
	 * 
	 */
	public boolean setFontSize( final float size )
	{
		this.setFont( this.getFontName(), this.getFontStyle(), size );
		return true;
	}


	/**
	 * 
	 */
	public boolean setFontSize( final float size, final String unit )
	{
		final double conv = SGUtilityText.convert( size, unit, FONT_SIZE_UNIT );
		if( conv < FONT_SIZE_MIN_VALUE ) return false;
		if( conv > FONT_SIZE_MAX_VALUE ) return false;

		return this.setFontSize( (float)SGUtilityText.convertToPoint( size, unit ) );
	}


	/**
	 * 
	 */
	public boolean setFontStyle( final int style )
	{
		this.setFont( this.getFontName(), style, this.getFontSize() );
		return true;
	}


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


	/**
	 * 
	 */
	public boolean setFontName( final String name )
	{
		this.setFont( name, this.getFontStyle(), this.getFontSize() );
		return true;
	}


	/**
	 * 
	 */
	public boolean setFont( final String name, final int style, final float size )
	{
		this.mFontName = name;
		this.mFontStyle = style;
		this.mFontSize = size;
		this.updateAllDrawingElements();
		return true;
	}


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

		return null;
	}


	/**
	 * 
	 */
	public boolean isVisible()
	{
		final boolean visible = this.mLegendVisibleFlag;

		boolean visible2 = false;
		ArrayList list = this.mLegendList;
		for( int ii=0; ii<list.size(); ii++ )
		{
			ElementGroupSetInLegend groupSet = (ElementGroupSetInLegend)list.get(ii);
			final boolean b = groupSet.isVisibleTotally();
			if(b)
			{
				visible2 = true;
				break;
			}
		}

		final boolean b = visible & visible2;
		return b;
	}


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


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


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



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

		}

		return null;
	}


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

		return null;
	}



	/**
	 * 
	 */
	private ElementGroupLine getGroupLine( final ElementGroupSetInLegend groupSet )
	{
		ArrayList groupList = groupSet.getElementGroupList();
		for( int ii=0; ii<groupList.size(); ii++ )
		{
			SGElementGroup group = (SGElementGroup)groupList.get(ii);
			if( group instanceof ElementGroupLine )
			{
				return (ElementGroupLine)group;
			}
		}

		return null;
	}


	/**
	 * 
	 */
	private ElementGroupBar getGroupBar( final ElementGroupSetInLegend groupSet )
	{
		ArrayList groupList = groupSet.getElementGroupList();
		for( int ii=0; ii<groupList.size(); ii++ )
		{
			SGElementGroup group = (SGElementGroup)groupList.get(ii);
			if( group instanceof ElementGroupBar )
			{
				return (ElementGroupBar)group;
			}
		}

		return null;
	}


	/**
	 * 
	 */
	private ElementGroupSymbol getGroupSymbol( final ElementGroupSetInLegend groupSet )
	{
		ArrayList groupList = groupSet.getElementGroupList();
		for( int ii=0; ii<groupList.size(); ii++ )
		{
			SGElementGroup group = (SGElementGroup)groupList.get(ii);
			if( group instanceof ElementGroupSymbol )
			{
				return (ElementGroupSymbol)group;
			}
		}

		return null;
	}


	/**
	 * 
	 * @param groupSet
	 * @return
	 */
	private ElementGroupErrorBar getGroupErrorBar( final ElementGroupSetInLegend groupSet )
	{
		ArrayList groupList = groupSet.getElementGroupList();
		for( int ii=0; ii<groupList.size(); ii++ )
		{
			SGElementGroup group = (SGElementGroup)groupList.get(ii);
			if( group instanceof ElementGroupErrorBar )
			{
				return (ElementGroupErrorBar)group;
			}
		}

		return null;
	}


	/**
	 * 
	 */
	private ElementGroupArrow getGroupArrow( final ElementGroupSetInLegend groupSet )
	{
		ArrayList groupList = groupSet.getElementGroupList();
		for( int ii=0; ii<groupList.size(); ii++ )
		{
			SGElementGroup group = (SGElementGroup)groupList.get(ii);
			if( group instanceof ElementGroupArrow )
			{
				return (ElementGroupArrow)group;
			}
		}

		return null;
	}


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

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


		//
		// Pop-up menu
		//

		if( command.equals( MENUCMD_HIDE ) )
		{
			this.setLegendVisible( false );
			repaint();
			this.setChanged(true);
			this.notifyToRoot();
			return;
		}
		else if( command.equals( MENUCMD_PROPERTY ) )
		{
			this.setPropertiesOfSelectedObjects();
		}

	}



	/**
	 * 
	 */
	public boolean commit()
	{
		// ダイアログを出す前後でプロパティが変更されている場合のみ、
		// 履歴を更新する
		SGProperties pTemp = this.mTemporaryProperties;
		SGProperties pPresent = this.getProperties();
		if( pTemp.equals(pPresent) == false )
		{
			this.setChanged( true );
		}
		this.mTemporaryProperties = null;

		this.updateAllDrawingElements();
		this.repaint();

		notifyChange();

		return true;
	}


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

		this.mTemporaryProperties = null;
		this.updateAllDrawingElements();
		this.repaint();

		notifyChange();

		return true;
	}


	/**
	 * 
	 */
	public boolean preview()
	{
		this.updateAllDrawingElements();
		this.repaint();

		notifyChange();

		return true;
	}



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

		this.updateAllDrawingElements();
		this.notifyChangeOnUndo();

//		repaint();

		return true;
	}




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

		this.updateAllDrawingElements();
		this.notifyChangeOnUndo();

//		repaint();

		return true;
	}


	
//	/**
//	 * 
//	 */
//	public boolean isChanged()
//	{
//		if( super.isChanged() )
//		{
//			return true;
//		}
//		ArrayList list = this.getVisibleLegendList();
//		for( int ii=0; ii<list.size(); ii++ )
//		{
//			SGIUndoable el = (SGIUndoable)list.get(ii);
//			if( el.isChanged() )
//			{
//				return true;
//			}
//		}
//		return false;
//	}


//	/**
//	 * 
//	 */
//	public boolean updateHistory()
//	{
//		return this.updateHistory( this.getVisibleLegendList() );
//	}



	/**
	 * Returns a list of visible group sets.
	 * @return a list of group sets
	 */
	protected ArrayList getVisibleLegendList()
	{
		ArrayList list = new ArrayList();
		ArrayList gList = this.mLegendList;
		for( int ii=0; ii<gList.size(); ii++ )
		{
			ElementGroupSetInLegend groupSet
				= (ElementGroupSetInLegend)gList.get(ii);
			if( groupSet.isVisible() )
			{
				list.add(groupSet);
			}
		}

		return list;
	}



	/**
	 * Returns a list of "totally" visible group sets.
	 * @return a list of group sets
	 */
	protected ArrayList getVisibleTotallyLegendList()
	{
		ArrayList list = new ArrayList();
		ArrayList gList = this.mLegendList;
		for( int ii=0; ii<gList.size(); ii++ )
		{
			ElementGroupSetInLegend groupSet
				= (ElementGroupSetInLegend)gList.get(ii);
			if( groupSet.isVisibleTotally() )
			{
				list.add(groupSet);
			}
		}

		return list;
	}



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

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

		return null;

	}



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

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

		return null;
	}



	/**
	 * 
	 */
	public boolean createDataObject( final Element el, final SGData data )
	{
		if( super.createDataObject( el, data ) == false )
		{
			return false;
		}


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


		//
		this.mLegendList.add( groupSet );

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

		
		// create drawing elements
		this.updateAllDrawingElements();

		
		// set false the flag
		this.mStartFlag = false;


		// create property dialogs for data
		this.createDataDialog(data);		


		return true;
	}


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

		if( data instanceof SGISXYTypeData | data instanceof SGISXYTypeMultipleData )
		{
			groupSet = new ElementGroupSetInLegendSXY();
		}
		else if( data instanceof SGIVXYTypeData )
		{
			groupSet = new ElementGroupSetInLegendVXY();
		}

		return groupSet;
	}

	
	/**
	 * 
	 */
	private int setProperty(
		final Element el, final ElementGroupSetInLegend groupSet )
	{
		SGData data = this.getData(groupSet);

		final int ic = SGIConstants.PROPERTY_FILE_INCORRECT;
		int ret = ic;

		String str = null;

		// name of data
		str = el.getAttribute( KEY_DATA_NAME );
		if( str.length()==0 )
		{
			return ic;
		}
		final String name = str;
		groupSet.setName(name);


		// visible in legend
		str = el.getAttribute( KEY_VISIBLE_IN_LEGEND );
		if( str.length()==0 )
		{
			return ic;
		}
		Boolean b = SGUtilityText.getBoolean(str);
		if( b==null )
		{
			return ic;
		}
		groupSet.setVisibleInLegend( b.booleanValue() );


		if( data instanceof SGITwoDimensionalData )
		{
			ret = this.setPropertyOfElementGroupSetInLegendForTwoDimensionalData( el, groupSet, data );
		}

		return SGIConstants.SUCCESSFUL_COMPLETION;
	}


	/**
	 * 
	 */
	private int setPropertyOfElementGroupSetInLegendForTwoDimensionalData(
		final Element el,
		final ElementGroupSetInLegend groupSet,
		final SGData data )
	{
		final int ic = SGIConstants.PROPERTY_FILE_INCORRECT;
		SGIFigureElementAxis aElement = this.mAxisElement;
		String str = null;


		// X-axis
		str = el.getAttribute( KEY_X_AXIS_POSITION );
		if( str.length()==0 )
		{
			return ic;
		}
		SGAxis xAxis = aElement.getAxis( str );
		if( xAxis == null )
		{
			return ic;
		}

		// Y-axis
		str = el.getAttribute( KEY_Y_AXIS_POSITION );
		if( str.length()==0 )
		{
			return ic;
		}
		SGAxis yAxis = aElement.getAxis( str );
		if( yAxis == null )
		{
			return ic;
		}
		
		
		// set x- and y-axis
		groupSet.setXAxis( xAxis );
		groupSet.setYAxis( yAxis );


		int ret = SGIConstants.PROPERTY_FILE_INCORRECT;
		if( ( data instanceof SGISXYTypeData ) | ( data instanceof SGISXYTypeMultipleData ) )
		{
			ElementGroupSetInLegendSXY gs = (ElementGroupSetInLegendSXY)groupSet;
			ret = this.setPropertyOfElementGroupSetInLegendSXY(el, gs, data);
		}
		else if( data instanceof SGIVXYTypeData )
		{
			ElementGroupSetInLegendVXY gs = (ElementGroupSetInLegendVXY)groupSet;
			ret = this.setPropertyOfElementGroupSetInLegendVXY(el, gs, data);
		}

		return ret;
	}

	
	
	/**
	 * 
	 */
	private int setPropertyOfElementGroupSetInLegendSXY(
		final Element el,
		final ElementGroupSetInLegendSXY groupSet,
		final SGData data )
	{

		final int ic = SGIConstants.PROPERTY_FILE_INCORRECT;
		SGIFigureElementAxis aElement = this.mAxisElement;
		String str = null;

		// create drawing element groups
		
		SGElementGroup group = null;
		NodeList nList = null;

		// bar
		nList = el.getElementsByTagName( SGIBarConstants.TAG_NAME_BAR );
		if( nList.getLength()!=1 )
		{
			return ic;
		}
		if( groupSet.addDrawingElementGroup( SGIElementGroupConstants.RECTANGLE_GROUP ) == false )
		{
			return ic;
		}
		Element bar = (Element)nList.item(0);
		group = groupSet.getBarGroup();
		if( group.readProperty(bar) == false )
		{
			return ic;
		}

		// code for the versions older than 0.9.1 	 
		ElementGroupBar groupBar = (ElementGroupBar)group;
		final float rectWidth = groupBar.getRectangleWidth();
		if( rectWidth!=0.0f )
		{
			final float ratio = rectWidth/this.mGraphRectWidth;
			SGAxis axisX = groupSet.getXAxis();
			final double max = axisX.getMaxValue();
			final double min = axisX.getMinValue();
			double value = ( max - min )*ratio;
			value = this.getNumberInRangeOrder( value, axisX );
			groupBar.setWidthValue( value );
		}


		if( data instanceof SGISXYTypeData )
		{
			SGISXYTypeData dataSXY = (SGISXYTypeData)data;

			// error bar
			nList = el.getElementsByTagName( SGIErrorBarConstants.TAG_NAME_ERROR_BAR );
			if( nList.getLength()==1 )
			{
				// if data has error bars
				if( dataSXY.isErrorValueHolding() )
				{
					if( groupSet.addDrawingElementGroup( SGIElementGroupConstants.ERROR_BAR_GROUP ) == false )
					{
						return ic;
					}

					ElementGroupErrorBar eGroup = (ElementGroupErrorBar)groupSet.getErrorBarGroup();

					Element errorBar = (Element)nList.item(0);
					if( eGroup.readProperty(errorBar)==false )
					{
						return ic;
					}

					if( eGroup.setPropertiesOfDrawingElements() == false )
					{
						return ic;
					}

				}
			}
			else if( nList.getLength()==0 )
			{
				// if data has error bars
				if( dataSXY.isErrorValueHolding() )
				{
					if( groupSet.addDrawingElementGroup( SGIElementGroupConstants.ERROR_BAR_GROUP ) == false )
					{
						return ic;
					}

					ElementGroupErrorBar eGroup = (ElementGroupErrorBar)groupSet.getErrorBarGroup();

					if( eGroup.setPropertiesOfDrawingElements() == false )
					{
						return ic;
					}
				}
			}
			else
			{
				return ic;
			}
		}


		// line
		nList = el.getElementsByTagName( SGILineConstants.TAG_NAME_LINE );
		if( nList.getLength()!=1 )
		{
			return ic;
		}
		if( groupSet.addDrawingElementGroup( SGIElementGroupConstants.POLYLINE_GROUP ) == false )
		{
			return ic;
		}
		Element line = (Element)nList.item(0);
		group = groupSet.getLineGroup();
		if( group.readProperty(line) == false )
		{
			return ic;
		}
		
		
		// symbol
		nList = el.getElementsByTagName( SGISymbolConstants.TAG_NAME_SYMBOL );
		if( nList.getLength()!=1 )
		{
			return ic;
		}
		if( groupSet.addDrawingElementGroup( SGIElementGroupConstants.SYMBOL_GROUP ) == false )
		{
			return ic;
		}
		Element symbol = (Element)nList.item(0);
		group = groupSet.getSymbolGroup();
		if( group.readProperty(symbol) == false )
		{
			return ic;
		}

		
		if( data instanceof SGISXYTypeData )
		{
			SGISXYTypeData dataSXY = (SGISXYTypeData)data;

			// tick label
			nList = el.getElementsByTagName( SGITickLabelConstants.TAG_NAME_TICK_LABELS );
			if( nList.getLength()==1 )
			{
				// if data has tick labels
				if( dataSXY.isStringArrayHolding() )
				{
					if( groupSet.addDrawingElementGroup( SGIElementGroupConstants.TICK_LABEL_GROUP ) == false )
					{
						return ic;
					}

					ElementGroupTickLabels tGroup = (ElementGroupTickLabels)groupSet.getTickLabelGroup();

					Element tickLabel = (Element)nList.item(0);
					if( tGroup.readProperty(tickLabel) == false )
					{
						return ic;
					}

					if( tGroup.setPropertiesOfDrawingElements() == false )
					{
						return ic;
					}
				}
			}
			else if( nList.getLength()==0 )
			{
				// if data has tick labels
				if( dataSXY.isStringArrayHolding() )
				{
					if( groupSet.addDrawingElementGroup( SGIElementGroupConstants.TICK_LABEL_GROUP ) == false )
					{
						return ic;
					}

					ElementGroupTickLabels tGroup = (ElementGroupTickLabels)groupSet.getTickLabelGroup();

					if( tGroup.setPropertiesOfDrawingElements() == false )
					{
						return ic;
					}
				}
			}
			else
			{
				return ic;
			}
		}

		
		//
		groupSet.initPropertiesHistory();

		
		return SGIConstants.SUCCESSFUL_COMPLETION;
	}


	
	/**
	 * 
	 */
	private int setPropertyOfElementGroupSetInLegendVXY(
		final Element el,
		final ElementGroupSetInLegendVXY groupSet,
		final SGData data )
	{

		final int ic = SGIConstants.PROPERTY_FILE_INCORRECT;
		String str = null;
		Number num = null;


		// create drawing element groups
		
		SGElementGroup group = null;
		NodeList nList = null;

		// arrow
		nList = el.getElementsByTagName( SGIArrowConstants.TAG_NAME_ARROW );
		if( nList.getLength()!=1 )
		{
			return ic;
		}
		if( groupSet.addDrawingElementGroup( SGIElementGroupConstants.ARROW_GROUP ) == false )
		{
			return ic;
		}
		Element arrow = (Element)nList.item(0);
		group = groupSet.getArrowGroup();
		if( group.readProperty(arrow) == false )
		{
			return ic;
		}


		// magnitude
		str = el.getAttribute( SGIFigureElementGraph.KEY_MAGNITUDE_PER_CM );
		if( str.length()!=0 )
		{
			num = SGUtilityText.getFloat(str);
			if( num==null )
			{
				return ic;
			}
			final float value = num.floatValue();
			groupSet.setMagnitudePerCM( value );
		}

		
		//
		groupSet.initPropertiesHistory();
		
		return SGIConstants.SUCCESSFUL_COMPLETION;
	}



	/**
	 * 
	 * @return
	 */
	public String getTagName()
	{
		return TAG_NAME_LEGEND;
	}

	
	/**
	 * 
	 */
	public boolean writeProperty( final Element el )
	{
		el.setAttribute( KEY_LEGEND_VISIBLE, Boolean.toString( this.mLegendVisibleFlag ) );

		el.setAttribute( KEY_X_AXIS_POSITION, this.mAxisElement.getLocationName( this.mXAxis ) );
		el.setAttribute( KEY_Y_AXIS_POSITION, this.mAxisElement.getLocationName( this.mYAxis ) );

		el.setAttribute( KEY_X_VALUE, Double.toString( this.getXValue() ) );
		el.setAttribute( KEY_Y_VALUE, Double.toString( this.getYValue() ) );

		
//		el.setAttribute( KEY_LEGEND_X, Float.toString( this.mLegendX*SGIConstants.CM_POINT_RATIO ) + SGIConstants.cm );
//		el.setAttribute( KEY_LEGEND_Y, Float.toString( this.mLegendY*SGIConstants.CM_POINT_RATIO ) + SGIConstants.cm );
		
		
		el.setAttribute( KEY_FRAME_VISIBLE, Boolean.toString( this.mFrameVisibleFlag ) );
		el.setAttribute( KEY_FRAME_LINE_WIDTH, Float.toString( this.mFrameLineWidth ) + SGIConstants.pt );
		el.setAttribute( KEY_FRAME_LINE_COLOR, SGUtilityText.getColorString( this.mFrameLineColor ) );
		el.setAttribute( KEY_BACKGROUND_COLOR, SGUtilityText.getColorString( this.mBackgroundColor ) );
		el.setAttribute( KEY_BACKGROUND_TRANSPARENT, Boolean.toString( this.mLegendTransparentFlag ) );

		el.setAttribute( KEY_FONT_NAME, this.mFontName );
		el.setAttribute( KEY_FONT_SIZE, Float.toString( this.mFontSize ) + SGIConstants.pt );
		el.setAttribute( KEY_FONT_STYLE, SGUtilityText.getFontStyleName( this.mFontStyle ) );
		el.setAttribute( KEY_STRING_COLORS, SGUtilityText.getColorString( this.mFontColor ) );

		el.setAttribute( KEY_SYMBOL_SPAN, Float.toString( this.mSymbolSpan*SGIConstants.CM_POINT_RATIO ) + SGIConstants.cm );

		return true;
	}
	
	
	/**
	 * 
	 */
	public Element createElement( final Document document )
	{
		return this.createThisElement( document );
	}

	
	
	/**
	 * 
	 */
	public boolean readProperty( final Element el )
	{
		String str = null;
		Number num = null;
		Color cl = null;
		Boolean b = null;

		
		// set legend visible
		str = el.getAttribute( SGIFigureElementLegend.KEY_LEGEND_VISIBLE );
		if( str.length()!=0 )
		{
			b = SGUtilityText.getBoolean(str);
			if( b==null )
			{
				return false;
			}
			if( this.setLegendVisible( b.booleanValue() ) == false )
			{
				return false;
			}
		}

		
		// set axes
		str = el.getAttribute( KEY_X_AXIS_POSITION );
		if( str.length()!=0 )
		{
			SGAxis xAxis = this.mAxisElement.getAxis(str);
			this.mXAxis = xAxis;
		}
		
		str = el.getAttribute( KEY_Y_AXIS_POSITION );
		if( str.length()!=0 )
		{
			SGAxis yAxis = this.mAxisElement.getAxis(str);
			this.mYAxis = yAxis;
		}


		str = el.getAttribute( KEY_X_VALUE );
		if( str.length()!=0 )
		{
			num = SGUtilityText.getDouble(str);
			if( num==null )
			{
				return false;
			}
			final double xValue = num.doubleValue();
			if( this.mXAxis.isValidValue( xValue ) == false )
			{
				return false;
			}
			if( this.setXValue( xValue ) == false )
			{
				return false;
			}
		}

		
		str = el.getAttribute( KEY_Y_VALUE );
		if( str.length()!=0 )
		{
			num = SGUtilityText.getDouble(str);
			if( num==null )
			{
				return false;
			}
			final double yValue = num.doubleValue();
			if( this.mYAxis.isValidValue( yValue ) == false )
			{
				return false;
			}
			if( this.setYValue( yValue ) == false )
			{
				return false;
			}
		}


		// set frame visible
		str = el.getAttribute( SGIFigureElementLegend.KEY_FRAME_VISIBLE );
		if( str.length()!=0 )
		{
			b = SGUtilityText.getBoolean(str);
			if( b == null )
			{
				return false;
			}
			if( this.setFrameVisible( b.booleanValue() ) == false )
			{
				return false;
			}
		}


		// set frame line width
		str = el.getAttribute( SGIFigureElementLegend.KEY_FRAME_LINE_WIDTH );
		if( str.length()!=0 )
		{
			StringBuffer uFrameLineWidth = new StringBuffer();
			num = SGUtilityText.getNumber( str, uFrameLineWidth );
			if( num == null )
			{
				return false;
			}
			if( this.setFrameLineWidth( num.floatValue(), uFrameLineWidth.toString() ) == false )
			{
				return false;
			}
		}


		// set frame line color
		str = el.getAttribute( SGIFigureElementLegend.KEY_FRAME_LINE_COLOR );
		if( str.length()!=0 )
		{
			cl = SGUtilityText.getColorFromString(str);
			if( cl == null )
			{
				return false;
			}
			if( this.setFrameLineColor(cl) == false )
			{
				return false;
			}
		}


		// background color
		str = el.getAttribute( SGIFigureElementLegend.KEY_BACKGROUND_COLOR );
		if( str.length()!=0 )
		{
			cl = SGUtilityText.getColorFromString(str);
			if( cl == null )
			{
				return false;
			}
			if( this.setBackgroundColor(cl) == false )
			{
				return false;
			}
		}

		
		// transparent
		str = el.getAttribute( SGIFigureElementLegend.KEY_BACKGROUND_TRANSPARENT );
		if( str.length()!=0 )
		{
			b = SGUtilityText.getBoolean(str);
			if( b==null )
			{
				return false;
			}
			if( this.setBackgroundTransparent( b.booleanValue() ) == false )
			{
				return false;
			}
		}


		// set font name
		str = el.getAttribute( KEY_FONT_NAME );
		if( str.length()!=0 )
		{
			final String fontName = str;
			if( this.setFontName( fontName ) == false )
			{
				return false;
			}
		}


		// set font size
		str = el.getAttribute( KEY_FONT_SIZE );
		if( str.length()!=0 )
		{
			StringBuffer uFontSize = new StringBuffer();
			num = SGUtilityText.getNumber( str, uFontSize );
			if( num==null )
			{
				return false;
			}
			if( this.setFontSize( num.floatValue(), uFontSize.toString() ) == false )
			{
				return false;
			}
		}


		// set font style
		str = el.getAttribute( KEY_FONT_STYLE );
		if( str.length()!=0 )
		{
			final int fontStyle = SGUtilityText.getFontStyle(str);
			if( fontStyle==-1 )
			{
				return false;
			}
			if( this.setFontStyle( fontStyle ) == false )
			{
				return false;
			}
		}


		// set the font color
		str = el.getAttribute( KEY_STRING_COLORS );
		if( str.length()!=0 )
		{
			cl = SGUtilityText.getColorFromString(str);
			if( cl==null )
			{
				return false;
			}
			if( this.setFontColor( cl ) == false )
			{
				return false;
			}
		}


		// set symbol span
// implemented from 0.9.1
		str = el.getAttribute( KEY_SYMBOL_SPAN );
		float symbolSpan;
		if( str.length()!=0 )
		{
			num = SGUtilityText.getLengthInPoint( str );
			if( num==null )
			{
				return false;
			}
			symbolSpan = num.floatValue();
		}
		else
		{
			num = new Float( DEFAULT_LEGEND_SYMBOL_SPAN );
			symbolSpan = num.floatValue();
		}
		if( this.setSymbolSpan( symbolSpan ) == false )
		{
			return false;
		}

		return true;
	}


	

	private boolean setDirectlyBefore()
	{
		return this.prepare();
	}

	private boolean setDirectlyAfter()
	{
		this.commit();
		this.updateAllDrawingElements();
		this.notifyChange();
		this.notifyToRoot();
		this.repaint();
		return true;
	}


	public boolean setAxisXDirectly( final int value )
	{
		if( this.setDirectlyBefore() == false ) return false;
		if( this.setXAxisLocation( value ) == false ) return false;
		if( this.setDirectlyAfter() == false ) return false;
		return true;
	}

	public boolean setAxisYDirectly( final int value )
	{
		if( this.setDirectlyBefore() == false ) return false;
		if( this.setYAxisLocation( value ) == false ) return false;
		if( this.setDirectlyAfter() == false ) return false;
		return true;
	}


	public boolean setXValueDirectly( final double value )
	{
		if( this.setDirectlyBefore() == false ) return false;
		if( this.setXValue( value ) == false ) return false;
		if( this.setDirectlyAfter() == false ) return false;
		return true;
	}

	public boolean setYValueDirectly( final double value )
	{
		if( this.setDirectlyBefore() == false ) return false;
		if( this.setYValue( value ) == false ) return false;
		if( this.setDirectlyAfter() == false ) return false;
		return true;
	}

	public boolean setLegendVisibleDirectly( final boolean value )
	{
		if( this.setDirectlyBefore() == false ) return false;
		if( this.setLegendVisible( value ) == false ) return false;
		if( this.setDirectlyAfter() == false ) return false;
		return true;
	}

	public boolean setFontNameDirectly( final String value )
	{
		if( this.setDirectlyBefore() == false ) return false;
		if( this.setFontName( value ) == false ) return false;
		if( this.setDirectlyAfter() == false ) return false;
		return true;
	}

	public boolean setFontStyleDirectly( final int value )
	{
		if( this.setDirectlyBefore() == false ) return false;
		if( this.setFontStyle( value ) == false ) return false;
		if( this.setDirectlyAfter() == false ) return false;
		return true;
	}


	public boolean setFontSizeDirectly( final float value, final String unit )
	{
		if( this.setDirectlyBefore() == false ) return false;
		if( this.setFontSize( value, unit ) == false ) return false;
		if( this.setDirectlyAfter() == false ) return false;
		return true;
	}

	public boolean setFontColorDirectly( final Color value )
	{
		if( this.setDirectlyBefore() == false ) return false;
		if( this.setFontColor( value ) == false ) return false;
		if( this.setDirectlyAfter() == false ) return false;
		return true;
	}

	public boolean setFrameVisibleDirectly( final boolean value )
	{
		if( this.setDirectlyBefore() == false ) return false;
		if( this.setFrameVisible( value ) == false ) return false;
		if( this.setDirectlyAfter() == false ) return false;
		return true;
	}

	public boolean setFrameLineWidthDirectly( final float value, final String unit )
	{
		if( this.setDirectlyBefore() == false ) return false;
		if( this.setFrameLineWidth( value, unit ) == false ) return false;
		if( this.setDirectlyAfter() == false ) return false;
		return true;
	}

	public boolean setFrameColorDirectly( final Color value )
	{
		if( this.setDirectlyBefore() == false ) return false;
		if( this.setFrameLineColor( value ) == false ) return false;
		if( this.setDirectlyAfter() == false ) return false;
		return true;
	}

	public boolean setBackgroundTransparentDirectly( final boolean value )
	{
		if( this.setDirectlyBefore() == false ) return false;
		if( this.setBackgroundTransparent( value ) == false ) return false;
		if( this.setDirectlyAfter() == false ) return false;
		return true;
	}

	public boolean setBackgroundColorDirectly( final Color value )
	{
		if( this.setDirectlyBefore() == false ) return false;
		if( this.setBackgroundColor( value ) == false ) return false;
		if( this.setDirectlyAfter() == false ) return false;
		return true;
	}

	public boolean setSymbolSpanDirectly( final float value, final String unit )
	{
		if( this.setDirectlyBefore() == false ) return false;
		if( this.setSymbolSpan( value, unit ) == false ) return false;
		if( this.setDirectlyAfter() == false ) return false;
		return true;
	}

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

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

		/**
		 * 
		 * @param rect
		 */
		public void setDataElementBounds( final Rectangle2D rect );

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

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


		/**
		 * 
		 * @param gs
		 * @return
		 */
		boolean setElementGroupSet( ElementGroupSetInLegend gs );
	}




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


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


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


		/**
		 * 
		 */
		protected SGProperties mTemporaryPropertiesInner = null;


		/**
		 * 
		 */
		protected SGDataDialog mDialog = null;


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



		/**
		 * Returns whether this group set is visible by two flags.
		 * @return visibility of this group set
		 */
		private boolean isVisibleTotally()
		{
			return ( this.isVisible() & this.isVisibleInLegend() );
		}


		/**
		 * 
		 */
		public boolean getLegendVisibleFlag()
		{
			return this.isVisibleInLegend();
		}


		/**
		 * データ名の文字列描画要素を作成
		 */
		private boolean createStringElement()
		{
			final float mag = this.getMagnification();
			final float angle = 0.0f;
			SGDrawingElementString2DExtended el = 
				new SGDrawingElementString2DExtended( 
						this.mName, 
						SGFigureElementLegend.this.mFontName,
						SGFigureElementLegend.this.mFontStyle,
						SGFigureElementLegend.this.mFontSize,
						SGFigureElementLegend.this.mFontColor,
						mag,
						angle
						);
			this.mDrawingString = el;
			return true;
		}


		/**
		 * 
		 * @return
		 */
		private boolean paintString( final Graphics2D g2d )
		{
			if( this.mDrawingString!=null )
			{
				this.mDrawingString.paintElement(g2d);
			}
			return true;
		}


		/**
		 * 
		 * @return
		 */
		private SGDrawingElementString2DExtended getStringElement()
		{
			return this.mDrawingString;
		}


		/**
		 * 
		 * @return
		 */
		private Rectangle2D getStringBounds()
		{
			if( this.mDrawingString==null )
			{
				return null;
			}
			Rectangle2D rect = this.mDrawingString.getStringRect();
			final float visual_height = (float)rect.getHeight();
			final float visual_y = (float)rect.getY();
			final float strike_through_offset = this.mDrawingString.getStrikethroughOffset();
			final float advance = this.mDrawingString.getAdvance();
			final float top = -visual_y + strike_through_offset;
			final float bottom = visual_height - top;
			float glowh = 0.0f;
			float glowy = 0.0f;
			if(bottom > top){
				glowh = bottom - top;
				glowy = glowh;
			}else{
				glowh = top - bottom;
			}
			rect.setRect(
					0, glowy,
					advance, visual_height + glowh
			);
			return rect;
		}


		/**
		 * 
		 * @return
		 */
		private Rectangle2D getRect()
		{
			return this.mDataRect;
		}


		/**
		 * 
		 * @param rect
		 */
		private void setRect( Rectangle2D rect )
		{
			this.mDataRect = rect;
		}


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

			return max;
		}


		/**
		 * 
		 */
		public double getMaxDataElementHeight()
		{
			double max = 0.0;
			ArrayList list = this.mDrawingElementGroupList;
			for( int ii=0; ii<list.size(); ii++ )
			{
				SGElementGroup group = (SGElementGroup)list.get(ii);
				if( !group.isVisible() )
				{
					continue;
				}
				ILegendElement el = (ILegendElement)list.get(ii);
				double height = el.getPreferredHeight();
				if( height > max )
				{
					max = height;
				}
			}

			return max;
		}


		/**
		 * 
		 * @param rect
		 */
		void setDrawingElementBounds( final Rectangle2D rect )
		{
			ArrayList list = this.mDrawingElementGroupList;
			for( int ii=0; ii<list.size(); ii++ )
			{
				SGElementGroup group = (SGElementGroup)list.get(ii);
				if( !group.isVisible() )
				{
					continue;
				}
				ILegendElement el = (ILegendElement)list.get(ii);
				el.setDataElementBounds( rect );
			}
		}


		/**
		 * 
		 * @return
		 */
		private boolean createDrawingElement()
		{
			final ArrayList list = this.mDrawingElementGroupList;
			for( int ii=0; ii<list.size(); ii++ )
			{
				SGElementGroup group = (SGElementGroup)list.get(ii);
				if( group.isVisible() )
				{
					ILegendElement el = (ILegendElement)group;
					el.createDrawingElementInLegend();
				}
			}

			return true;
		}


		/**
		 * 
		 */
		public void paintGraphics2D( final Graphics2D g2d )
		{
			// draw the name of data
			g2d.setPaint( SGFigureElementLegend.this.mFontColor );
			this.paintString( g2d );

			// draw the symbols
			this.paintSymbol( g2d );
		}


		abstract void paintSymbol( Graphics2D g2d );

		abstract boolean onMouseClicked( final MouseEvent e );


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

			ILegendElement lElement = (ILegendElement)group;
			lElement.setElementGroupSet( this );


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

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

			// 倍率
			group.setMagnification( this.getMagnification() );

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

			return true;
		}


		abstract boolean synchronizeDrawingElements( ArrayList eList );


		protected SGAxis getAxis( final int location )
		{
			return SGFigureElementLegend.this.mAxisElement.getAxisInPlane( location );
		}


		/**
		 * Returns a property dialog.
		 * @return property dialog
		 */
		public SGPropertyDialog getPropertyDialog()
		{
			return this.mDialog;
		}


		// テンポラリオブジェクトを作成させる
		public boolean prepare()
		{
			this.mTemporaryPropertiesInner = this.getWholeProperties();
			return true;
		}


		// ダイアログに設定された値を元に設定し、終了
		public boolean commit()
		{
			updateSymbolsVisibleAroundFocusedObjects();

			SGProperties pTemp = this.mTemporaryPropertiesInner;
			SGProperties pPresent = this.getWholeProperties();

			if( pTemp.equals(pPresent) == false )
			{
				this.setChanged(true);
			}

			this.mTemporaryPropertiesInner = null;

			//
			if( updateAllDrawingElements() == false )
			{
				return false;
			}

			repaint();
			notifyChange();

			return true;
		}


		// 設定前の状態に戻す
		public boolean cancel()
		{
			if( this.setWholeProperties( this.mTemporaryPropertiesInner ) == false )
			{
				return false;
			}

			this.mTemporaryPropertiesInner = null;

			//
			if( updateAllDrawingElements() == false )
			{
				return false;
			}
			repaint();
			notifyChange();

			return true;
		}


		// ダイアログに設定された値を元に設定する
		public boolean preview()
		{
			updateSymbolsVisibleAroundFocusedObjects();

			//
			if( updateAllDrawingElements() == false )
			{
				return false;
			}
			repaint();
			notifyChange();

			return true;
		}

		
		/**
		 * 
		 * @return
		 */
		public String getTagName()
		{
			return "";
		}


		/**
		 * 
		 */
		public boolean writeProperty( final Element el )
		{
			return true;
		}


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

			updateAllDrawingElements();
			notifyChange();
		}



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

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

			ElementGroupSetPropertiesInFigureElement ep = (ElementGroupSetPropertiesInFigureElement)p;

			SGIFigureElementAxis aElement = SGFigureElementLegend.this.mAxisElement;

			ep.xAxis = aElement.getLocationInCube( this.getXAxis() );
			ep.yAxis = aElement.getLocationInCube( this.getYAxis() );
			ep.zAxis = aElement.getLocationInCube( this.getZAxis() );

			return true;
		}



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

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

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

			ElementGroupSetPropertiesInFigureElement ep = (ElementGroupSetPropertiesInFigureElement)p;

			SGIFigureElementAxis aElement = SGFigureElementLegend.this.mAxisElement;

			this.setXAxis( aElement.getAxisInCube( ep.xAxis ) );
			this.setYAxis( aElement.getAxisInCube( ep.yAxis ) );
			this.setZAxis( aElement.getAxisInCube( ep.zAxis ) );

			return true;
		}



		/**
		 * アンドゥを行う
		 */
		public boolean setMementoBackward()
		{
			if( super.setMementoBackward() == false ) return false;

			updateAllDrawingElements();
			notifyChangeOnUndo();

			return true;
		}


		/**
		 * リドゥを行う
		 */
		public boolean setMementoForward()
		{
			if( super.setMementoForward() == false ) return false;

			updateAllDrawingElements();
			notifyChangeOnUndo();

			return true;
		}



		/**
		 * 
		 *
		 */
		public void notifyToRoot()
		{
			SGFigureElementLegend.this.notifyToRoot();
		}


	}



	/**
	 * 
	 */
	private class ElementGroupSetInLegendSXY extends ElementGroupSetInLegend
		implements SGISXYDataDialogObserver, SGISXYDataConstants
	{

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


		public int getSelectedTabIndex()
		{
			return this.mSelectedTabIndex;
		}

		private int mSelectedTabIndex = -1;



		/**
		 * 
		 */
		void paintSymbol( final Graphics2D g2d )
		{

			// bar
			ElementGroupBar groupBar = getGroupBar( this );
			if( groupBar!=null )
			{
				if( groupBar.isVisible() )
				{
					groupBar.paintElement(g2d);
				}
			}
			
			// error bar
			ElementGroupErrorBar groupErrorBar = getGroupErrorBar( this );
			if( groupErrorBar!=null )
			{
				if( groupErrorBar.isVisible() )
				{
					groupErrorBar.paintElement(g2d);
				}
			}

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

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

		}


		// Line
		
		public boolean isLineVisible()
		{
			return this.getLineGroup().isVisible();
		}
		
		public float getLineWidth()
		{
			return this.getLineGroup().getLineWidth();
		}

		public float getLineWidth( final String unit )
		{
			return (float)SGUtilityText.convertFromPoint( this.getLineWidth(), unit );
		}
		
		public int getLineType()
		{
			return this.getLineGroup().getLineType();
		}

		public Color getLineColor()
		{
			return this.getLineGroup().getColor(0);
		}


		public boolean setLineVisible( final boolean b )
		{
			this.getLineGroup().setVisible(b);
			return true;
		}

		public boolean setLineWidth( final float width )
		{
			return this.getLineGroup().setLineWidth( width );
		}

		public boolean setLineWidth( final float width, final String unit )
		{
			return this.setLineWidth( (float)SGUtilityText.convertToPoint( width, unit ) );
		}

		public boolean setLineType( final int type )
		{
			return this.getLineGroup().setLineType( type );
		}
		
		public boolean setLineColor( final Color cl )
		{
			return this.getLineGroup().setColor( cl );
		}



		// Symbol

		public boolean isSymbolVisible()
		{
			return this.getSymbolGroup().isVisible();
		}

		public int getSymbolType()
		{
			return this.getSymbolGroup().getType();
		}

		public float getSymbolSize()
		{
			return this.getSymbolGroup().getSize();
		}

		public float getSymbolSize( final String unit )
		{
			return (float)SGUtilityText.convertFromPoint( this.getSymbolSize(), unit );
		}

		public float getSymbolLineWidth()
		{
			return this.getSymbolGroup().getLineWidth();
		}

		public float getSymbolLineWidth( final String unit )
		{
			return (float)SGUtilityText.convertFromPoint( this.getSymbolLineWidth(), unit );
		}

		public Color getSymbolInnerColor()
		{
			return this.getSymbolGroup().getColor(0);
		}

		public Color getSymbolLineColor()
		{
			return this.getSymbolGroup().getLineColor();
		}

		public boolean setSymbolVisible( final boolean b )
		{
			this.getSymbolGroup().setVisible(b);
			return true;
		}

		public boolean setSymbolType( final int type )
		{
			return this.getSymbolGroup().setType(type);
		}

		public boolean setSymbolSize( final float size )
		{
			return this.getSymbolGroup().setSize(size);
		}

		public boolean setSymbolSize( final float size, final String unit )
		{
			return this.setSymbolSize( (float)SGUtilityText.convertToPoint( size, unit ) );
		}

		public boolean setSymbolLineWidth( final float width )
		{
			return this.getSymbolGroup().setLineWidth(width);
		}

		public boolean setSymbolLineWidth( final float width, final String unit )
		{
			return this.setSymbolLineWidth( (float)SGUtilityText.convertToPoint( width, unit ) );
		}

		public boolean setSymbolInnerColor( final Color cl )
		{
			return this.getSymbolGroup().setColor(cl);
		}

		public boolean setSymbolLineColor( final Color cl )
		{
			return this.getSymbolGroup().setLineColor(cl);
		}



		// Bar

		public boolean isBarVisible()
		{
			return this.getBarGroup().isVisible();
		}

		public double getBarBaselineValue()
		{
			return this.getBarGroup().getBaselineValue();
		}

		public float getBarWidth()
		{
			return this.getBarGroup().getRectangleWidth();
		}

		public double getBarWidthValue()
		{
			return this.getBarGroup().getWidthValue();
		}

		public float getBarEdgeLineWidth()
		{
			return this.getBarGroup().getEdgeLineWidth();
		}

		public float getBarEdgeLineWidth( final String unit )
		{
			return (float)SGUtilityText.convertFromPoint( this.getBarEdgeLineWidth(), unit );
		}

		public Color getBarInnerColor()
		{
			return this.getBarGroup().getColor(0);
		}

		public Color getBarEdgeLineColor()
		{
			return this.getBarGroup().getEdgeLineColor();
		}

		public boolean setBarVisible( final boolean b )
		{
			this.getBarGroup().setVisible(b);
			return true;
		}

		public boolean setBarBaselineValue( final double value )
		{
			return this.getBarGroup().setBaselineValue( value );
		}

		public boolean setBarWidth( final float width )
		{
			return this.getBarGroup().setRectangleWidth( width );
		}

		public boolean setBarWidthValue( final double value )
		{
			return this.getBarGroup().setWidthValue( value );
		}

		public boolean setBarEdgeLineWidth( final float width )
		{
			return this.getBarGroup().setEdgeLineWidth( width );
		}

		public boolean setBarEdgeLineWidth( final float width, final String unit )
		{
			return this.setBarEdgeLineWidth( (float)SGUtilityText.convertToPoint( width, unit ) );
		}

		public boolean setBarInnerColor( final Color cl )
		{
			return this.getBarGroup().setColor(cl);
		}

		public boolean setBarEdgeLineColor( final Color cl )
		{
			return this.getBarGroup().setEdgeLineColor(cl);
		}

		public boolean hasValidBaselineValue( final int config, final Number value )
		{
			final SGAxis axis = (config==-1) ? this.mYAxis : SGFigureElementLegend.this.mAxisElement.getAxisInPlane( config );
			final double v = (value!=null) ? value.doubleValue() : this.getBarBaselineValue();
			return axis.isValidValue(v);
		}


		// Error Bar
		public boolean isErrorBarHolding()
		{
			return (this.getErrorBarGroup()!=null);
		}

		public boolean isErrorBarVisible()
		{
			return this.getErrorBarGroup().isVisible();
		}

		public int getErrorBarHeadType()
		{
			return this.getErrorBarGroup().getHeadType();
		}

		public float getErrorBarHeadSize()
		{
			return this.getErrorBarGroup().getHeadSize();
		}

		public float getErrorBarHeadSize( final String unit )
		{
			return (float)SGUtilityText.convertFromPoint( this.getErrorBarHeadSize(), unit );
		}

		public Color getErrorBarColor()
		{
			return this.getErrorBarGroup().getColor(0);
		}

		public float getErrorBarLineWidth()
		{
			return this.getErrorBarGroup().getLineWidth();
		}

		public float getErrorBarLineWidth( final String unit )
		{
			return (float)SGUtilityText.convertFromPoint( this.getErrorBarLineWidth(), unit );
		}

		public int getErrorBarStyle()
		{
			return this.getErrorBarGroup().getErrorBarStyle();
		}

		public boolean setErrorBarVisible( final boolean b )
		{
			this.getErrorBarGroup().setVisible(b);
			return true;
		}

		public boolean setErrorBarHeadType( final int type )
		{
			this.getErrorBarGroup().setHeadType( type );
			return true;
		}

		public boolean setErrorBarHeadSize( final float size )
		{
			this.getErrorBarGroup().setHeadSize( size );
			return true;
		}

		public boolean setErrorBarHeadSize( final float size, final String unit )
		{
			return this.setErrorBarHeadSize( (float)SGUtilityText.convertToPoint( size, unit ) );
		}

		public boolean setErrorBarColor( final Color cl )
		{
			return this.getErrorBarGroup().setColor(cl);
		}

		public boolean setErrorBarLineWidth( final float width )
		{
			this.getErrorBarGroup().setLineWidth( width );
			return true;
		}

		public boolean setErrorBarLineWidth( final float width, final String unit )
		{
			return this.setErrorBarLineWidth( (float)SGUtilityText.convertToPoint( width, unit ) );
		}

		public boolean setErrorBarStyle( final int style )
		{
			this.getErrorBarGroup().setErrorBarStyle(style);
			return true;
		}



		// Tick Label

		public boolean isTickLabelHolding()
		{
			return (this.getTickLabelGroup()!=null);
		}

		public boolean isTickLabelVisible()
		{
			return this.getTickLabelGroup().isVisible();
		}

		public String getTickLabelFontName()
		{
			return this.getTickLabelGroup().getFontName();
		}

		public int getTickLabelFontStyle()
		{
			return this.getTickLabelGroup().getFontStyle();
		}

		public float getTickLabelFontSize()
		{
			return this.getTickLabelGroup().getFontSize();
		}

		public float getTickLabelFontSize( final String unit )
		{
			return (float)SGUtilityText.convertFromPoint( this.getTickLabelFontSize(), unit );
		}

		public Color getTickLabelColor()
		{
			return this.getTickLabelGroup().getColor(0);
		}

		public boolean isTickLabelHorizontal()
		{
			return (this.getTickLabelGroup().getAngle()==SGITickLabelConstants.ANGLE_HORIZONTAL);
		}

		public boolean setTickLabelVisible( final boolean b )
		{
			this.getTickLabelGroup().setVisible(b);
			return true;
		}

		public boolean setTickLabelFontName( final String name )
		{
			return this.getTickLabelGroup().setFontName( name );
		}

		public boolean setTickLabelFontStyle( final int style )
		{
			return this.getTickLabelGroup().setFontStyle( style );
		}

		public boolean setTickLabelFontSize( final float size )
		{
			return this.getTickLabelGroup().setFontSize( size );
		}

		public boolean setTickLabelFontSize( final float size, final String unit )
		{
			return this.setTickLabelFontSize( (float)SGUtilityText.convertToPoint( size, unit ) );
		}

		public boolean setTickLabelColor( final Color cl )
		{
			return this.getTickLabelGroup().setColor(cl);
		}


		public boolean setTickLabelHorizontal( final boolean b )
		{
			float angle;
			if(b)
			{
				angle = SGITickLabelConstants.ANGLE_HORIZONTAL;
			}
			else
			{
				angle = SGITickLabelConstants.ANGLE_INCLINED;
			}
			return this.getTickLabelGroup().setAngle( angle );			
		}


		//
		boolean onMouseClicked( final MouseEvent e )
		{
			SGElementGroup group = this.getElementGroupAt( e.getX(), e.getY() );

			int index = -1;
			if( group instanceof ElementGroupLine )
			{
				index = 0;
			}
			else if( group instanceof ElementGroupSymbol )
			{
				index = 1;
			}
			else if( group instanceof ElementGroupBar )
			{
				index = 2;
			}
			else if( group instanceof ElementGroupErrorBar )
			{
				index = 3;
			}
			else if( group instanceof ElementGroupTickLabels )
			{
				index = 4;
			}
			this.mSelectedTabIndex = index;

			return true;
		}


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

			SGElementGroup group = null;
			if( type == SGIElementGroupConstants.POLYLINE_GROUP )
			{
				group = new ElementGroupLine();
			}
			else if( type == SGIElementGroupConstants.RECTANGLE_GROUP )
			{
				group = new ElementGroupBar();
			}
			else if( type == SGIElementGroupConstants.SYMBOL_GROUP )
			{
				group = new ElementGroupSymbol();
			}
			else if( type == SGIElementGroupConstants.ARROW_GROUP )
			{
				group = new ElementGroupArrow();
			}
			else if( type == SGIElementGroupConstants.ERROR_BAR_GROUP )
			{
				group = new ElementGroupErrorBar();
			}
			else if( type == SGIElementGroupConstants.TICK_LABEL_GROUP )
			{
				group = new ElementGroupTickLabels();
			}
			else
			{
				throw new Error();
			}

			this.addDrawingElementGroup( group );

			return true;
		}


		/**
		 * 
		 */
		public int getXAxisLocation()
		{
			return SGFigureElementLegend.this.mAxisElement.getLocationInPlane( this.getXAxis() );
		}


		/**
		 * 
		 */
		public int getYAxisLocation()
		{
			return SGFigureElementLegend.this.mAxisElement.getLocationInPlane( this.getYAxis() );
		}



		/**
		 * 
		 */
		public boolean setXAxisLocation( final int config )
		{
			this.mXAxis = this.getAxis(config);
			return true;
		}

		/**
		 * 
		 */
		public boolean setYAxisLocation( final int config )
		{
			this.mYAxis = this.getAxis(config);
			return true;
		}


		boolean synchronizeDrawingElements( ArrayList eList )
		{
			boolean diffFlag = false;
			for( int ii=0; ii<eList.size(); ii++ )
			{
				SGDrawingElement el = (SGDrawingElement)eList.get(ii);

				ArrayList groupList = null;
				if( el instanceof SGDrawingElementErrorBar )
				{
					groupList = this.getErrorBarGroups();
				}
				else if( el instanceof SGDrawingElementLine )
				{
					groupList = this.getLineGroups();
				}
				else if( el instanceof SGDrawingElementSymbol )
				{
					groupList = this.getSymbolGroups();
				}
				else if( el instanceof SGDrawingElementBar )
				{
					groupList = this.getBarGroups();
				}
				else if( el instanceof SGDrawingElementString )
				{
					groupList = this.getTickLabelGroups();
				}

				if( groupList==null )
				{
					continue;
				}
				
				for( int jj=0; jj<groupList.size(); jj++ )
				{
					SGElementGroup group = (SGElementGroup)groupList.get(jj);
					SGDrawingElement elOld = group.getDrawingElement();
					SGProperties p = el.getProperties();
					SGProperties pOld = elOld.getProperties();
					if( p.equals(pOld) == false )
					{
						diffFlag = true;
					}
					group.setProperty(el);
				}
			}

			return diffFlag;
		}


	}



	/**
	 * 
	 */
	private class ElementGroupSetInLegendVXY extends ElementGroupSetInLegend
		implements SGIVXYDataDialogObserver, SGIVXYDataConstants
	{

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

		// scaling factor for the magnitude of vectors
		private float mMagnitudePerCM = 1.0f;

		public float getMagnitudePerCM()
		{
			return this.mMagnitudePerCM;
		}
	
		public boolean setMagnitudePerCM( final float f )
		{
			this.mMagnitudePerCM = f;
			return true;
		}


		// a flag whether to fix the direction of each vector
		private boolean mDirectionFixedFlag;

		public boolean isDirectionInvariant()
		{
			return this.mDirectionFixedFlag;
		}

		public boolean setDirectionInvariant( final boolean b )
		{
			this.mDirectionFixedFlag = b;
			return true;
		}


		/**
		 * 
		 */
		public boolean addDrawingElementGroup( final int type )
		{
			SGElementGroup group = null;
			if( type == SGIElementGroupConstants.ARROW_GROUP )
			{
				group = new ElementGroupArrow();
			}
			else
			{
				throw new Error();
			}

			this.addDrawingElementGroup( group );

			return true;
		}


		//
		boolean synchronizeDrawingElements( ArrayList eList )
		{
			boolean diffFlag = false;
			for( int ii=0; ii<eList.size(); ii++ )
			{
				SGDrawingElement el = (SGDrawingElement)eList.get(ii);

				ArrayList groupList = null;
				if( el instanceof SGDrawingElementArrow )
				{
					groupList = this.getArrowGroups();
				}

				if( groupList==null )
				{
					continue;
				}
				
				for( int jj=0; jj<groupList.size(); jj++ )
				{
					SGElementGroup group = (SGElementGroup)groupList.get(jj);
					SGDrawingElement elOld = group.getDrawingElement();
					SGProperties p = el.getProperties();
					SGProperties pOld = elOld.getProperties();
					if( p.equals(pOld) == false )
					{
						diffFlag = true;
					}
					group.setProperty(el);
				}
			}

			return diffFlag;
		}


		/**
		 * 
		 */
		void paintSymbol( final Graphics2D g2d )
		{
			// arrow
			ElementGroupArrow groupArrow = getGroupArrow( this );
			if( groupArrow!=null )
			{
				if( groupArrow.isVisible() )
				{
					groupArrow.paintElement(g2d);
				}
			}
			
		}


		boolean onMouseClicked( final MouseEvent e )
		{
			return true;
		}


		/**
		 * 
		 */
		public int getXAxisLocation()
		{
			return SGFigureElementLegend.this.mAxisElement.getLocationInPlane( this.getXAxis() );
		}


		/**
		 * 
		 */
		public int getYAxisLocation()
		{
			return SGFigureElementLegend.this.mAxisElement.getLocationInPlane( this.getYAxis() );
		}


		public float getLineWidth( final String unit )
		{
			return this.getArrowGroup().getLineWidth( unit );
		}
	
		public int getLineType()
		{
			return this.getArrowGroup().getLineType();
		}
	
		public Color getColor()
		{
			return this.getArrowGroup().getColor();
		}

		public float getHeadSize( final String unit )
		{
			return this.getArrowGroup().getHeadSize( unit );
		}

		public float getHeadOpenAngle()
		{
			return this.getArrowGroup().getHeadOpenAngle();
		}
	
		public float getHeadCloseAngle()
		{
			return this.getArrowGroup().getHeadCloseAngle();
		}

		public int getStartHeadType()
		{
			return this.getArrowGroup().getStartHeadType();
		}
	
		public int getEndHeadType()
		{
			return this.getArrowGroup().getEndHeadType();
		}


		/**
		 * 
		 */
		public boolean setXAxisLocation( final int config )
		{
			this.mXAxis = this.getAxis(config);
			return true;
		}

		/**
		 * 
		 */
		public boolean setYAxisLocation( final int config )
		{
			this.mYAxis = this.getAxis(config);
			return true;
		}


		public boolean setLineWidth( final float width, final String unit )
		{
			return this.getArrowGroup().setLineWidth( width, unit );
		}
	
		public boolean setLineType( final int type )
		{
			return this.getArrowGroup().setLineType( type );
		}
	
		public boolean setColor( final Color cl )
		{
			return this.getArrowGroup().setColor( cl );
		}

		public boolean setHeadSize( final float size, final String unit )
		{
			return this.getArrowGroup().setHeadSize( size, unit );
		}
	
		public boolean setHeadOpenAngle( final float angle )
		{
			return this.getArrowGroup().setHeadOpenAngle( angle );
		}
	
		public boolean setHeadCloseAngle( final float angle )
		{
			return this.getArrowGroup().setHeadCloseAngle( angle );
		}
	
		public boolean setStartHeadType( final int type )
		{
			return this.getArrowGroup().setStartHeadType( type );
		}

		public boolean setEndHeadType( final int type )
		{
			return this.getArrowGroup().setEndHeadType( type );
		}


		public boolean hasValidAngle( final Number open, final Number close )
		{
			final float openAngle = (open!=null) ? open.floatValue() : this.getHeadOpenAngle();
			final float closeAngle = (close!=null) ? close.floatValue() : this.getHeadCloseAngle();
			return ( openAngle < closeAngle );
		}


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

			return ep;
		}


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

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

			ElementGroupSetInVXYGraphProperties ep = (ElementGroupSetInVXYGraphProperties)p;

			ep.mMagnitudeScalingFactor = this.getMagnitudePerCM();

			return true;
		}


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

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

			ElementGroupSetInVXYGraphProperties ep = (ElementGroupSetInVXYGraphProperties)p;

			this.setMagnitudePerCM( ep.mMagnitudeScalingFactor );

			return true;
		}

	}



	/**
	 * @author  okumura
	 */
	private class ElementGroupLine extends SGElementGroupLine
		implements ILegendElement, SGISXYDataConstants
	{
		protected ElementGroupSetInLegend mGroupSet = null;

		public boolean setElementGroupSet( ElementGroupSetInLegend gs )
		{
			this.mGroupSet = gs;
			return true;
		}

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


		/**
		 * 
		 */
		private boolean init()
		{
			this.setVisible( DEFAULT_LINE_VISIBLE );
			this.setLineWidth( DEFAULT_LINE_WIDTH, LINE_WIDTH_UNIT );
			this.setLineType( DEFAULT_LINE_TYPE );
			this.setColor( DEFAULT_LINE_COLOR );

			return true;
		}


		/**
		 * 
		 */
		public float getPreferredWidth()
		{
			return this.getMagnification()*getSymbolSpan();
		}


		/**
		 * 
		 */
		public float getPreferredHeight()
		{
			return this.getMagnification()*this.getLineWidth();
		}


		private Rectangle2D mBoundsRect = new Rectangle2D.Float();

		/**
		 * 
		 * @param rect
		 */
		public void setDataElementBounds( final Rectangle2D rect )
		{
			this.mBoundsRect = rect;
		}


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

	
		/**
		 * 描画要素の作成
		 */
		public boolean createDrawingElementInLegend()
		{
//			final float width = this.getDataElementWidth();

			Rectangle2D lRect = getRectOfGroupSet(this.mGroupSet);
			Rectangle2D dRect = this.mBoundsRect;

			SGTuple2f start = new SGTuple2f();
			start.x = (float)lRect.getX();
			start.y = (float)lRect.getY() + 0.50f*(float)lRect.getHeight();
			SGTuple2f end = new SGTuple2f();
			end.x = start.x + (float)dRect.getWidth();
			end.y = start.y;

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

			return true;
		}


		/**
		 * 
		 * @param el
		 * @return
		 */
		public boolean readProperty( final Element el )
		{
			if( super.readProperty(el) == false )
			{
				return false;
			}

			return SGFigureElementLegend.this.readProperty( this, el );
		}

	}



	/**
	 * @author  okumura
	 */
	private class ElementGroupBar extends SGElementGroupBar
		implements ILegendElement, SGISXYDataConstants
	{
		protected ElementGroupSetInLegend mGroupSet = null;

		public boolean setElementGroupSet( ElementGroupSetInLegend gs )
		{
			this.mGroupSet = gs;
			return true;
		}


		/**
		 *
		 */
		protected ElementGroupBar()
		{
			super();
			this.init();
		}


		/**
		 * 
		 */
		private void init()
		{
			this.setVisible( DEFAULT_BAR_VISIBLE );
			this.setBaselineValue( DEFAULT_BAR_BASELINE_VALUE );
//			this.setRectangleWidth( BAR_WIDTH );
			this.setColor( DEFAULT_BAR_COLOR );
			this.setEdgeLineWidth( DEFAULT_BAR_EDGE_LINE_WIDTH, LINE_WIDTH_UNIT );
			this.setEdgeLineColor( DEFAULT_BAR_EDGE_LINE_COLOR );
		}


		/**
		 * 
		 */
		public float getPreferredWidth()
		{
			final ElementGroupSetInLegendSXY gs
				= (ElementGroupSetInLegendSXY)this.mGroupSet;
			Rectangle2D strRect = gs.mDrawingString.getElementBounds();
			return (float)strRect.getHeight();			
		}


		/**
		 * 
		 */
		public float getPreferredHeight()
		{
			return this.getPreferredWidth();
		}

		private Rectangle2D mBoundsRect = new Rectangle2D.Float();

		/**
		 * 
		 * @param rect
		 */
		public void setDataElementBounds( final Rectangle2D rect )
		{
			this.mBoundsRect = rect;
		}


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


		/**
		 * 
		 */
		public boolean createDrawingElementInLegend()
		{
			// set size
			final float h = this.getPreferredWidth();
			final float w = h;
			this.setRectangleWidth(w);
			this.setRectangleHeight(h);

			// set location
			Rectangle2D lRect = getRectOfGroupSet( this.mGroupSet );
			Rectangle2D dRect = this.mBoundsRect;
			final float x = (float)lRect.getX() + 0.50f*( (float)dRect.getWidth() - w );
			final float y = (float)lRect.getY() + 0.50f*(float)lRect.getHeight();
			SGTuple2f start = new SGTuple2f(x,y);
			this.setLocation( new SGTuple2f[]{ start } );

			return true;
		}



		/**
		 * 
		 * @return
		 */
		public boolean initDrawingElement( final int num )
		{
			super.initDrawingElement(num);
			this.setHorizontal(true);
			return true;
		}



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

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

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

//			// calculate the height
//			final ElementGroupSetInLegendSXY gs
//				= (ElementGroupSetInLegendSXY)this.mGroupSet;
//			final SGAxis xAxis = gs.getXAxis();
//			final double xMin = xAxis.getMinValue();
//			final double xMax = xAxis.getMaxValue();
//			final float width = mGraphRectWidth*(float)( this.getWidthValue()/( xMax - xMin ) );
//			this.setRectangleWidth( width );
//
//			final float w = 0.60f*this.getDataElementWidth();
//			final float h = this.getMagnification()*width;

			SGDrawingElement[] array = this.mDrawingElementArray;
			for( int ii=0; ii<array.length; ii++ )
			{
				SGDrawingElementBar2D bar = (SGDrawingElementBar2D)array[ii];
//				bar.setBounds( pointArray[ii].x, pointArray[ii].y, w, h );
				bar.setLocation( pointArray[ii].x, pointArray[ii].y );
			}

			return true;
		}


		/**
		 * 
		 * @param el
		 * @return
		 */
		public boolean readProperty( final Element el )
		{
			if( super.readProperty(el) == false )
			{
				return false;
			}

			return SGFigureElementLegend.this.readProperty( this, el );
		}

	}



	/**
	 * @author  okumura
	 */
	private class ElementGroupSymbol extends SGElementGroupSymbol
		implements ILegendElement, SGISXYDataConstants
	{
		protected ElementGroupSetInLegend mGroupSet = null;

		public boolean setElementGroupSet( ElementGroupSetInLegend gs )
		{
			this.mGroupSet = gs;
			return true;
		}

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


		/**
		 * 
		 */
		private boolean init()
		{
			this.setVisible( DEFAULT_SYMBOL_VISIBLE );
			this.setType( DEFAULT_SYMBOL_TYPE );
			this.setSize( DEFAULT_SYMBOL_SIZE, SYMBOL_SIZE_UNIT );
			this.setColor( DEFAULT_SYMBOL_BODY_COLOR );
			this.setLineWidth( DEFAULT_SYMBOL_LINE_WIDTH, LINE_WIDTH_UNIT );
			this.setLineColor( DEFAULT_SYMBOL_LINE_COLOR );

			return true;
		}


		/**
		 * 
		 */
		public float getPreferredWidth()
		{
			return this.getDataElementSize();
		}


		/**
		 * 
		 */
		public float getPreferredHeight()
		{
			return 1.20f*this.getDataElementSize();
		}


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

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

		private Rectangle2D mBoundsRect = new Rectangle2D.Float();

		/**
		 * 
		 * @param rect
		 */
		public void setDataElementBounds( final Rectangle2D rect )
		{
			this.mBoundsRect = rect;
		}


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


		/**
		 * 
		 */
		public boolean createDrawingElementInLegend()
		{
			Rectangle2D lRect = getRectOfGroupSet(this.mGroupSet);
Rectangle2D dRect = this.mBoundsRect;
//			final float x = (float)lRect.getX() + 0.50f*this.getDataElementWidth();
			final float x = (float)lRect.getX() + 0.50f*(float)dRect.getWidth();
			final float y = (float)lRect.getY() + 0.50f*(float)lRect.getHeight();
			SGTuple2f position = new SGTuple2f(x,y);

			if( this.setLocation( new SGTuple2f[]{ position } ) == false )
			{
				return false;
			}

			return true;

		}


		/**
		 * 
		 * @param el
		 * @return
		 */
		public boolean readProperty( final Element el )
		{
			if( super.readProperty(el) == false )
			{
				return false;
			}

			return SGFigureElementLegend.this.readProperty( this, el );
		}

	}



	/**
	 * @author  okumura
	 */
	private class ElementGroupArrow extends SGElementGroupArrow
		implements ILegendElement, SGIVXYDataConstants
	{
		protected ElementGroupSetInLegend mGroupSet = null;

		public boolean setElementGroupSet( ElementGroupSetInLegend gs )
		{
			this.mGroupSet = gs;
			return true;
		}


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


		/**
		 * 
		 */
		private boolean init()
		{
			this.setLineWidth( DEFAULT_LINE_WIDTH, LINE_WIDTH_UNIT );
			this.setLineType( DEFAULT_LINE_TYPE );
			this.setColor( DEFAULT_COLOR );
			this.setStartHeadType( DEFAULT_START_HEAD_TYPE );
			this.setEndHeadType( DEFAULT_END_HEAD_TYPE );
			this.setHeadSize( DEFAULT_HEAD_SIZE, ARROW_HEAD_SIZE_UNIT );
			this.setHeadOpenAngle( DEFAULT_HEAD_OPEN_ANGLE );
			this.setHeadCloseAngle( DEFAULT_HEAD_CLOSE_ANGLE );

			this.mMagnitudeString.setFontName( DEFAULT_LEGEND_FONT_NAME );
			this.mMagnitudeString.setFontStyle( DEFAULT_LEGEND_FONT_STYLE );
			this.mMagnitudeString.setFontSize( DEFAULT_LEGEND_FONT_SIZE, FONT_SIZE_UNIT );
			this.mMagnitudeString.setColor( DEFAULT_LEGEND_FONT_COLOR );

			return true;
		}


		/**
		 * 
		 */
		public float getPreferredWidth()
		{
			return this.getMagnification()*getSymbolSpan();
		}


		/**
		 * 
		 */
		private Rectangle2D getDataElementBounds()
		{
			SGDrawingElement[] array = this.mDrawingElementArray;
			if( array!=null )
			{
				if( array.length == 0 )
				{
					return new Rectangle2D.Float();
				}

				SGDrawingElementArrow2D el
					= (SGDrawingElementArrow2D)array[0];
				Rectangle2D rect = el.getElementBounds();
				return rect;
			}
			return new Rectangle2D.Float();
		}

		/**
		 * 
		 */
		public float getPreferredHeight()
		{
			final float elementSize = 1.20f*(float)this.getDataElementBounds().getHeight();
			final float strHeight = (float)this.mMagnitudeString.getElementBounds().getHeight();
			final float size = elementSize + 2.0f*strHeight;
			return size;
		}

		private Rectangle2D mBoundsRect = new Rectangle2D.Float();

		/**
		 * 
		 * @param rect
		 */
		public void setDataElementBounds( final Rectangle2D rect )
		{
			this.mBoundsRect = rect;
		}


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


		/**
		 * 
		 */
		public boolean createDrawingElementInLegend()
		{
			Rectangle2D lRect = getRectOfGroupSet(this.mGroupSet);
			Rectangle2D dRect = this.mBoundsRect;
			final float headSize = this.getMagnification()*this.getHeadSize();
			final int startHeadType = this.getStartHeadType();
			final int endHeadType = this.getEndHeadType();

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

			SGTuple2f start = new SGTuple2f();
			start.x = x;
			if( this.doShiftX( startHeadType ) )
			{
				start.x += headSize;
			}
			start.y = y + 0.50f*h;

			SGTuple2f end = new SGTuple2f();
			end.x = x + w;
			if( this.doShiftX( endHeadType ) )
			{
				end.x -= headSize;
			}
			end.y = start.y;

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

			//
			this.updateMagnitudeString();

			return true;
		}


		private boolean doShiftX( final int type )
		{
			final boolean b
				= (type!=SGIArrowConstants.SYMBOL_TYPE_ARROW_HEAD)
				& (type!=SGISymbolConstants.SYMBOL_TYPE_TRANSVERSELINE)
				& (type!=SGISymbolConstants.SYMBOL_TYPE_VOID);
			return b;
		}

		private boolean updateMagnitudeString()
		{
			ElementGroupSetInLegendVXY groupSet
				= (ElementGroupSetInLegendVXY)this.mGroupSet;
			final float percm = groupSet.getMagnitudePerCM();
			final float span = SGFigureElementLegend.this.getSymbolSpan(cm);
			final float value = percm*span;
			final float valueReduced = (float)SGUtilityNumber.getNumberInNumberOrder( value, value, 3 );
			this.mMagnitudeString.setString( Float.toString(valueReduced) );

			Rectangle2D lRect = getRectOfGroupSet(this.mGroupSet);
			Rectangle2D dRect = this.mBoundsRect;
			Rectangle2D sRect = this.mMagnitudeString.getElementBounds();
			Rectangle2D elRect = this.getDataElementBounds();

			SGTuple2f location = new SGTuple2f();
			location.x = (float)( lRect.getX() + 0.50f*( dRect.getWidth() - sRect.getWidth() ) );
//			location.y = (float)lRect.getY() + 0.50f*(float)lRect.getHeight() + this.getMagnification()*this.getLineWidth();
			location.y = (float)( elRect.getY() + elRect.getHeight() ) + 2.0f;

			this.mMagnitudeString.setLocation( location );

			return true;
		}


		// string to display the magnitude of an arrow
		private SGDrawingElementString2DExtended mMagnitudeString
			= new SGDrawingElementString2DExtended();


		/**
		 * 
		 */
		public boolean zoom( float ratio )
		{
			super.zoom(ratio);
			this.mMagnitudeString.zoom(ratio);
			return true;
		}


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

			this.mMagnitudeString.paint( g2d, clipRect );

			return true;
		}


		/**
		 * 
		 * @param el
		 * @return
		 */
		public boolean readProperty( final Element el )
		{
			if( super.readProperty(el) == false )
			{
				return false;
			}

			return SGFigureElementLegend.this.readProperty( this, el );
		}

	}



	/**
	 * Error bars.
	 */
	private class ElementGroupErrorBar extends SGElementGroupErrorBar
		implements ILegendElement, SGISXYDataConstants
	{
		protected ElementGroupSetInLegend mGroupSet = null;

		public boolean setElementGroupSet( ElementGroupSetInLegend gs )
		{
			this.mGroupSet = gs;
			return true;
		}

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


		/**
		 * 
		 */
		private boolean init()
		{
			this.setVisible( DEFAULT_ERROR_BAR_VISIBLE );
			this.setLineWidth( DEFAULT_ERROR_BAR_LINE_WIDTH, LINE_WIDTH_UNIT );
			this.setHeadSize( DEFAULT_ERROR_BAR_SYMBOL_SIZE, ERROR_BAR_HEAD_SIZE_UNIT );
			this.setHeadType( DEFAULT_ERROR_BAR_SYMBOL_TYPE );
			this.setLineWidth( DEFAULT_ERROR_BAR_LINE_WIDTH, LINE_WIDTH_UNIT );
			this.setErrorBarStyle( DEFAULT_ERROR_BAR_STYLE );
			this.setColor( DEFAULT_ERROR_BAR_COLOR );

			return true;
		}


		/**
		 * 
		 */
		public float getPreferredWidth()
		{
			return this.getMagnification()*this.getHeadSize();
		}


		private static final float DEFAULT_ERROR_BAR_HEIGHT = 10.0f;

		/**
		 * 
		 */
		public float getPreferredHeight()
		{
			ElementGroupSetInLegendSXY legend = (ElementGroupSetInLegendSXY)this.mGroupSet;
			SGElementGroupSymbol sg = legend.getSymbolGroup();
			SGElementGroupBar bg = legend.getBarGroup();

			float size = 0.0f;
			if( sg.isVisible() | bg.isVisible() )
			{
				final float symbolSize = sg.isVisible() ? ((ILegendElement)sg).getPreferredHeight() : 0.0f;
				final float barWidth = bg.isVisible() ? ((ILegendElement)bg).getPreferredHeight() : 0.0f;
				size = (symbolSize>barWidth) ? symbolSize : barWidth;
			}
			else
			{
				size = DEFAULT_ERROR_BAR_HEIGHT;
			}

			final float mag = this.getMagnification();
			final float barHeight = 1.20f*mag*size;
			final float headSize = mag*this.getHeadSize();
			return barHeight + 2.0f*headSize;
		}


		private Rectangle2D mBoundsRect = new Rectangle2D.Float();


		/**
		 * 
		 * @param rect
		 */
		public void setDataElementBounds( final Rectangle2D rect )
		{
			this.mBoundsRect = rect;
		}


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


		/**
		 * 描画要素の作成
		 */
		public boolean createDrawingElementInLegend()
		{
			SGTuple2f start = new SGTuple2f();
			SGTuple2f end = new SGTuple2f();

			Rectangle2D lRect = getRectOfGroupSet( this.mGroupSet );
			Rectangle2D dRect = this.mBoundsRect;

			final float mag = this.getMagnification();
			final float width = mag*getSymbolSpan();

			final float x = (float)lRect.getX() + 0.50f*(float)dRect.getWidth();
			start.x = x;
			end.x = x;

			final float headSize = mag*this.getHeadSize();

			final float y = (float)lRect.getY() + 0.50f*headSize;
			final float h = (float)dRect.getHeight() - headSize;

			final int style = this.getErrorBarStyle();
			switch( style )
			{
				case ERROR_BAR_BOTHSIDES :
				{
					start.y = y + h;
					end.y = y;
					break;
				}
				
				case ERROR_BAR_DOWNSIDE :
				{
					start.y = y + h;
					end.y = y + 0.50f*h;
					break;
				}

				case ERROR_BAR_UPSIDE :
				{
					start.y = y + 0.50f*h;
					end.y = y;
					break;
				}

				default :
				{
					throw new Error();				
				}
			}

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

			return true;
		}


		/**
		 * 
		 * @param el
		 * @return
		 */
		public boolean readProperty( final Element el )
		{
			if( super.readProperty(el) == false )
			{
				return false;
			}

			return SGFigureElementLegend.this.readProperty( this, el );
		}

	}



	/**
	 * @author  okumura
	 */
	private class ElementGroupTickLabels extends SGElementGroupTickLabel
		implements ILegendElement, SGISXYDataConstants
	{
		protected ElementGroupSetInLegend mGroupSet = null;

		public boolean setElementGroupSet( ElementGroupSetInLegend gs )
		{
			this.mGroupSet = gs;
			return true;
		}


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


		/**
		 * 
		 */
		private boolean init()
		{
			this.setVisible( DEFAULT_TICK_LABEL_VISIBLE );
			this.setFontName( DEFAULT_TICK_LABEL_FONT_NAME );
			this.setFontStyle( DEFAULT_TICK_LABEL_FONT_STYLE );
			this.setFontSize( DEFAULT_TICK_LABEL_FONT_SIZE, FONT_SIZE_UNIT );
			this.setAngle( DEFAULT_TICK_LABEL_ANGLE );
			this.setColor( DEFAULT_TICK_LABEL_FONT_COLOR );

			return true;
		}


		/**
		 * 
		 */
		protected SGDrawingElement createDrawingElementInstance()
		{
			return new SGDrawingElementString2DExtended();
		}


		/**
		 * 描画要素の作成
		 */
		public boolean createDrawingElementInLegend()
		{
			return true;
		}


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


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


		private Rectangle2D mBoundsRect = new Rectangle2D.Float();

		/**
		 * 
		 * @param rect
		 */
		public void setDataElementBounds( final Rectangle2D rect )
		{
			this.mBoundsRect = rect;
		}

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


		/**
		 * 
		 * @param el
		 * @return
		 */
		public boolean readProperty( final Element el )
		{
			if( super.readProperty(el) == false )
			{
				return false;
			}

			return SGFigureElementLegend.this.readProperty( this, el );
		}
	}


	//
	private boolean readProperty( final SGElementGroup group, final Element el )
	{
		String str;
		Boolean b;

		// visible
		str = el.getAttribute( KEY_VISIBLE );
		if( str.length()!=0 )
		{
			b = SGUtilityText.getBoolean(str);
			if( b==null )
			{
				return false;
			}
			group.setVisible( b.booleanValue() );
		}

		return true;
	}


	/**
	 * @author  okumura
	 */
	public static class LegendCommonProperties extends SGProperties
	{

		float x;
		float y;
		boolean visible;
		boolean frameLineVisible;
		float frameLineWidth;
		Color frameLineColor;
		String fontName;
		float fontSize;
		int fontStyle;
		Color stringColor;
		Color backgroundColor;
		boolean transparent;
		float symbolSpan;
		SGAxis xAxis;
		SGAxis yAxis;


		public void dispose()
		{
			this.frameLineColor = null;
			this.fontName = null;
			this.stringColor = null;
			this.stringColor = null;
			this.xAxis = null;
			this.yAxis = null;
		}

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

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

			LegendCommonProperties p = (LegendCommonProperties)obj;

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

			return true;
		}


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

			return str;
		}



	}

}

