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.InputEvent;
import java.awt.event.KeyEvent;
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.SGIConstants;
import jp.riken.brain.ni.samuraigraph.base.SGIFigureElement;
import jp.riken.brain.ni.samuraigraph.base.SGIFigureElementAxis;
import jp.riken.brain.ni.samuraigraph.base.SGIFigureElementAxisBreak;
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.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.SGIMovable;
import jp.riken.brain.ni.samuraigraph.base.SGISelectable;
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
		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 properties 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 = 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_) & !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 onKeyPressed(final KeyEvent e) {
		boolean effective = false;
		final int keycode = e.getKeyCode();
		final int mod = e.getModifiersEx();
		final boolean isShiftPressed = ((mod & InputEvent.SHIFT_DOWN_MASK) != 0);
		int dx = 0;
		int dy = 0;
		switch (keycode) {
		case KeyEvent.VK_UP:
			if (isShiftPressed) {
				dy = -1;
			} else {
				dy = -10;
			}
			break;
		case KeyEvent.VK_DOWN:
			if (isShiftPressed) {
				dy = 1;
			} else {
				dy = 10;
			}
			break;
		case KeyEvent.VK_LEFT:
			if (isShiftPressed) {
				dx = -1;
			} else {
				dx = -10;
			}
			break;
		case KeyEvent.VK_RIGHT:
			if (isShiftPressed) {
				dx = 1;
			} else {
				dx = 10;
			}
			break;
		}
		if (dx != 0 || dy != 0) {
			if (this.isSelected()) {
				if (this.setDirectlyBefore() == false)
					return false;
				this.translate((float) dx, (float) dy);
				if (this.setDirectlyAfter() == false)
					return false;
				effective = true;
			}
		}
		return effective;
	}

	/**
	 * 
	 */
	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 = SGIConstants.SUCCESSFUL_COMPLETION;

		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 ret;
	}

	/**
	 * 
	 */
	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
		// SymbolSpan is appeared since ver. 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 {
			// for previous version before 0.9.1
			num = new Float(SGUtilityText.convertToPoint(
					DEFAULT_LEGEND_SYMBOL_SPAN, SYMBOL_SPAN_UNIT));
			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;
		}

	}

}
