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

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Cursor;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Shape;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.geom.Line2D;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import javax.swing.JLabel;
import javax.swing.JPopupMenu;
import javax.swing.SwingUtilities;

import jp.riken.brain.ni.samuraigraph.base.SGAxis;
import jp.riken.brain.ni.samuraigraph.base.SGIFigureElementAxisBreak;
import jp.riken.brain.ni.samuraigraph.base.SGIFigureElementAxis;
import jp.riken.brain.ni.samuraigraph.base.SGICopiable;
import jp.riken.brain.ni.samuraigraph.base.SGIDisposable;
import jp.riken.brain.ni.samuraigraph.base.SGIFigureElement;
import jp.riken.brain.ni.samuraigraph.base.SGIFigureElementGraph;
import jp.riken.brain.ni.samuraigraph.base.SGIFigureElementGrid;
import jp.riken.brain.ni.samuraigraph.base.SGIFigureElementLegend;
import jp.riken.brain.ni.samuraigraph.base.SGIMovable;
import jp.riken.brain.ni.samuraigraph.base.SGINode;
import jp.riken.brain.ni.samuraigraph.base.SGISelectable;
import jp.riken.brain.ni.samuraigraph.base.SGIFigureElementShape;
import jp.riken.brain.ni.samuraigraph.base.SGIFigureElementSignificantDifference;
import jp.riken.brain.ni.samuraigraph.base.SGIFigureElementString;
import jp.riken.brain.ni.samuraigraph.base.SGIFigureElementTimingLine;
import jp.riken.brain.ni.samuraigraph.base.SGIUndoable;
import jp.riken.brain.ni.samuraigraph.base.SGProperties;
import jp.riken.brain.ni.samuraigraph.base.SGPropertyDialog;
import jp.riken.brain.ni.samuraigraph.base.SGTuple2f;
import jp.riken.brain.ni.samuraigraph.base.SGUndoManager;
import jp.riken.brain.ni.samuraigraph.base.SGUtility;
import jp.riken.brain.ni.samuraigraph.base.SGUtilityText;
import jp.riken.brain.ni.samuraigraph.figure.SGFigureElement;
import jp.riken.brain.ni.samuraigraph.figure.SGIAxisBreakConstants;
import jp.riken.brain.ni.samuraigraph.figure.SGDrawingElementAxisBreak.AxisBreakSymbolProperties;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;


/**
 * A class managing axis break symbols.
 */
public class SGFigureElementAxisBreak extends SGFigureElement
	implements SGIFigureElementAxisBreak, SGIAxisBreakConstants
{

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

	
	/**
	 * 
	 */
	private SGAxisBreakDialog mDialog = null;


	/**
	 * 
	 *
	 */
	public SGFigureElementAxisBreak()
	{
		super();
	}


	/**
	 * 
	 */
	public void dispose()
	{
		super.dispose();
		this.mDialog.dispose();
		this.mDialog = null;
		this.mAxisElement = null;
	}


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



	/**
	 * create a dialog of axis break symbols
	 */
	private boolean createDialog()
	{
		final SGAxisBreakDialog absdg
			= new SGAxisBreakDialog( this.mDialogOwner, true );
		this.mDialog = absdg;
		return true;
	}


	/**
	 * 
	 */
	public String toString()
	{
		return "SGAxisBreakElement";
	}

	
	/**
	 * 
	 * @return
	 */
	public String getClassDescription()
	{
		return "Axis Break Symbols";
	}


	
	/**
	 * 
	 */
	public boolean synchronize( final SGIFigureElement element, final String msg )
	{

		boolean flag = true;
		if( element instanceof SGIFigureElementGraph )
		{
			
		}
		else if( element instanceof SGIFigureElementString )
		{
			
		}
		else if( element instanceof SGIFigureElementLegend )
		{
			
		}
		else if( element instanceof SGIFigureElementAxis )
		{
			flag = this.synchronizeToAxisElement( (SGIFigureElementAxis)element, msg );
		}
		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 synchronizeToAxisElement( SGIFigureElementAxis element, String msg )
	{
		ArrayList list = this.getVisibleChildList();
		for( int ii=0; ii<list.size(); ii++ )
		{
			AxisBreakSymbol el = (AxisBreakSymbol)list.get(ii);
			el.setDrawingElementsLocation();
		}
		
		return true;
	}
	
	

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


	
	/**
	 * 
	 * @param element
	 */
	public void setAxisElement( final SGIFigureElementAxis element )
	{
		this.mAxisElement = element;
	}


	/**
	 * 
	 */
	public String getTagName()
	{
		return TAG_NAME_AXIS_BREAK;
	}

	

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


	
	/**
	 * 
	 */
	public boolean readProperty( final Element element )
	{
		NodeList nList = element.getElementsByTagName( SGIAxisBreakConstants.TAG_NAME_AXIS_BREAK_SYMBOL );
		for( int ii=0; ii<nList.getLength(); ii++ )
		{
			Node node = nList.item(ii);
			if( node instanceof Element )
			{
				Element el = (Element)node;
				AxisBreakSymbol abs = new AxisBreakSymbol();
				if( abs.readProperty(el) == false )
				{
					return false;
				}
				abs.initPropertiesHistory();
				this.addToList(abs);
			}
		}
		
		return true;
	}



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

		return true;
	}

	
	/**
	 * 
	 */
	private boolean setLocationOfAllDrawingElements()
	{
		List list = this.mChildList;
		for( int ii=0; ii<list.size(); ii++ )
		{
			AxisBreakSymbol abs = (AxisBreakSymbol)list.get(ii);
			abs.setDrawingElementsLocation();
		}
		return true;
	}

	
	/**
	 * ズーム
	 */
	public boolean zoom( final float ratio )
	{
		super.zoom(ratio);

		List list = this.mChildList;
		for( int ii=0; ii<list.size(); ii++ )
		{
			final AxisBreakSymbol el = (AxisBreakSymbol)list.get(ii);
			el.zoom(ratio);
		}

		return true;
	}




	/**
	 * 
	 */
	public void paintGraphics( Graphics g, boolean clip )
	{

		final Graphics2D g2d = (Graphics2D)g;

		// draw all visible symbols
		ArrayList list = this.getVisibleChildList();
		for( int ii=0; ii<list.size(); ii++ )
		{
			AxisBreakSymbol el = (AxisBreakSymbol)list.get(ii);
			if( el.isValid() == false )
			{
				continue;
			}
			el.paintElement(g2d);
//			if( el.mFrameFlag )
//			{
//				el.drawBoundingBox(g2d);
//			}
		}
		
		
		// draw symbols around all objects
		if( this.mSymbolsVisibleFlagAroundAllObjects )
		{
			for( int ii=0; ii<list.size(); ii++ )
			{
				AxisBreakSymbol el = (AxisBreakSymbol)list.get(ii);
				if( el.isValid() == false )
				{
					continue;
				}
				ArrayList pList = el.getAnchorPointList();
				SGUtilityForFigureElementJava2D.drawAnchorAsChildObject( pList, g2d );
			}
		}

		// draw symbols around focused objects
		if( this.mSymbolsVisibleFlagAroundFocusedObjects )
		{
			ArrayList fList = new ArrayList();
			this.getFocusedObjectsList( fList );
			for( int ii=0; ii<fList.size(); ii++ )
			{
				AxisBreakSymbol el = (AxisBreakSymbol)fList.get(ii);
				if( el.isValid() == false )
				{
					continue;
				}
				ArrayList pList = el.getAnchorPointList();
				SGUtilityForFigureElementJava2D.drawAnchorAsFocusedObject( pList, g2d );
			}
		}
		
	}

	
	
	/**
	 * 
	 * @param document
	 * @return
	 */
	public Element createElement( final Document document )
	{
		// create an Element object
		Element el = this.createThisElement( document );
		if( el==null )
		{
			return null;
		}

		// axis symbol
		ArrayList abList = this.getVisibleChildList();
		for( int ii=0; ii<abList.size(); ii++ )
		{
			AxisBreakSymbol abs = (AxisBreakSymbol)abList.get(ii);
			if( abs.isValid() == false )
			{
				continue;
			}

			Element elAbs = abs.createElement( document );
			if( elAbs==null )
			{
				return null;
			}
			el.appendChild( elAbs );
		}
		
		return el;
	}

	
	
	/**
	 * 
	 * @param x
	 * @param y
	 * @return
	 */
	public boolean addAxisBreakSymbol( final int x, final int y )
	{
		if( this.getGraphRect().contains( x, y ) == false )
		{
			return false;
		}

		SGAxis xAxis = SGFigureElementAxisBreak.this.mAxisElement.getAxis( DEFAULT_AXIS_BREAK_HORIZONTAL_AXIS );
		SGAxis yAxis = SGFigureElementAxisBreak.this.mAxisElement.getAxis( DEFAULT_AXIS_BREAK_PERPENDICULAR_AXIS );
		return this.addAxisBreakSymbol( xAxis, yAxis, x, y );
	}

	
	

	/**
	 * 
	 */
	public boolean addAxisBreakSymbol(
		final SGAxis xAxis, final SGAxis yAxis, final int x, final int y )
	{
		
		AxisBreakSymbol el = new AxisBreakSymbol(
			DEFAULT_AXIS_BREAK_LENGTH,
			AXIS_BREAK_LENGTH_UNIT,
			DEFAULT_AXIS_BREAK_INTERVAL,
			AXIS_BREAK_INTERVAL_UNIT,
			DEFAULT_AXIS_BREAK_DISTORTION,
			DEFAULT_AXIS_BREAK_ANGLE,
			DEFAULT_AXIS_BREAK_FOR_HORIZONTAL
		);
		el.addColor( DEFAULT_AXIS_BREAK_INNER_COLOR );
		el.setLineColor( DEFAULT_AXIS_BREAK_LINE_COLOR );
		el.setLineWidth( DEFAULT_AXIS_BREAK_LINE_WIDTH, LINE_WIDTH_UNIT );
		el.setMagnification( this.mMagnification );
		el.mXAxis = xAxis;
		el.mYAxis = yAxis;

		el.setLocation(x,y);
		el.setAxisValue();


		//
		this.addToList( el );

		//
		this.setChanged(true);

		// initialize history
		el.initPropertiesHistory();
		
		this.notifyToRoot();

		return true;
	}


	/**
	 * 全描画要素の位置を決定
	 */
	protected boolean setAllDrawingElementsLocation()
	{
		ArrayList list = this.getVisibleChildList();
		for( int ii=0; ii<list.size(); ii++ )
		{
			final AxisBreakSymbol el
				= (AxisBreakSymbol)list.get(ii);
			if( el.setDrawingElementsLocation() == false )
			{
				return false;
			}
		}

		return true;
	}


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

		this.clearFocusedObjects();
		this.notifyChangeOnUndo();

		return true;
	}



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

		this.clearFocusedObjects();
		this.notifyChangeOnUndo();

		return true;
	}



	
	/**
	 * 
	 */
	public boolean onMouseClicked( final MouseEvent e )
	{
		// Axis Break Symbols
		ArrayList list = this.getVisibleChildList();
		for( int ii=list.size()-1; ii>=0; ii-- )
		{
			final AxisBreakSymbol el = (AxisBreakSymbol)list.get(ii);
			if( el.isValid() == false )
			{
				continue;
			}
			if( this.clickDrawingElements(el,e) )
			{
				return true;
			}
		}

		return false;
	}

	
	
	/**
	 * 
	 * @return
	 */
	public boolean setTemporaryPropertiesOfFocusedObjects()
	{
		ArrayList list = this.getFocusedObjectsList();
		for( int ii=0; ii<list.size(); ii++ )
		{
			AxisBreakSymbol el = (AxisBreakSymbol)list.get(ii);
			el.mTemporaryProperties = el.getProperties();
		}
		return true;
	}



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


	/**
	 * 
	 */
	private boolean clickDrawingElements(
		final AxisBreakSymbol el, final MouseEvent e )
	{
		final int x = e.getX();
		final int y = e.getY();
		final int cnt = e.getClickCount();

		// clicked on the line elements
		if( el.contains(x,y) )
		{
			this.updateFocusedObjectsList( el, e );

			if( SwingUtilities.isLeftMouseButton(e) & cnt==1 )
			{

			}
			else if( SwingUtilities.isLeftMouseButton(e) & cnt==2 )
			{
				this.setPropertiesOfSelectedObjects();
			}
			else if( SwingUtilities.isRightMouseButton(e) & cnt==1 )
			{
				el.getPopupMenu().show( this.getComponent(), x, y );
			}

			return true;
		}


		return false;
	}



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

		// Axis Break Symbols
		ArrayList list = this.getVisibleChildList();
		for( int ii=list.size()-1; ii>=0; ii-- )
		{
			final AxisBreakSymbol el = (AxisBreakSymbol)list.get(ii);
			if( el.isValid() == false )
			{
				continue;
			}
			if( el.contains(x,y) )
			{
				this.mPressedPoint = e.getPoint();
				this.setMouseCursor( Cursor.MOVE_CURSOR );
				if( el.isSelected() )
				{
					this.mDraggableFlag = true;
				}
				return true;
			}
		}

		return false;
	}



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

		final int dx = e.getX() - this.mPressedPoint.x;
		final int dy = e.getY() - this.mPressedPoint.y;
		
		ArrayList list = this.getFocusedObjectsList();
		for( int ii=0; ii<list.size(); ii++ )
		{
			AxisBreakSymbol el = (AxisBreakSymbol)list.get(ii);
			if( el.isValid() == false )
			{
				continue;
			}
			el.translate(dx,dy);
		}
		
		this.mPressedPoint = e.getPoint();

		return true;
	}


	

	/**
	 * 
	 * @return
	 */
	public boolean setChangedFocusedObjects()
	{
		ArrayList list = this.getFocusedObjectsList();
		for( int ii=0; ii<list.size(); ii++ )
		{
			AxisBreakSymbol el = (AxisBreakSymbol)list.get(ii);
			SGProperties temp = el.mTemporaryProperties;
			if( temp!=null )
			{
				SGProperties p = el.getProperties();
				if( p.equals(temp)==false )
				{
					el.setChanged(true);
				}
			}
		}
		return true;
	}
	
	
	
	/**
	 * 
	 * @param e
	 */
	public boolean onMouseReleased( final MouseEvent e )
	{

		// Axis Break Symbol
		ArrayList list = this.getFocusedObjectsList();
		for( int ii=0; ii<list.size(); ii++ )
		{
			AxisBreakSymbol el = (AxisBreakSymbol)list.get(ii);
			if( el.isValid() == false )
			{
				continue;
			}
			Rectangle2D rect = el.getElementBounds();
			if( rect.contains(e.getPoint()) )
			{
				this.setMouseCursor( Cursor.HAND_CURSOR );
			}
			else
			{
				this.setMouseCursor( Cursor.DEFAULT_CURSOR );
			}
		}

		this.mDraggableFlag = false;
		this.notifyToRoot();
		
		return true;
	}
	
	
	
	/**
	 * 
	 */
	public boolean onDrawingElement( final int x, final int y )
	{
		ArrayList list = this.getVisibleChildList();
		for( int ii=list.size()-1; ii>=0; ii-- )
		{
			final AxisBreakSymbol el = (AxisBreakSymbol)list.get(ii);
			if( el.isValid() == false )
			{
				continue;
			}
			final boolean flag = el.contains(x,y);
//			el.mFrameFlag = flag;
			if( flag )
			{
				this.setMouseCursor( Cursor.HAND_CURSOR );
				return true;
			}
		}

		return false;
	}



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

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

		ArrayList list = this.getVisibleChildList();

		ArrayList axisBreakRectList = new ArrayList();
		for( int ii=0; ii<list.size(); ii++ )
		{
			AxisBreakSymbol el = (AxisBreakSymbol)list.get(ii);
			Rectangle2D rect = el.getElementBounds();
			axisBreakRectList.add( rect );
		}
		
		Rectangle2D rectAxisBreakSymbols = null;
		if( axisBreakRectList.size()!=0 )
		{
			rectAxisBreakSymbols = SGUtility.createUnion( axisBreakRectList );
		}
		
		
		Rectangle2D gRect = this.getGraphRect();
		
		ArrayList rectList = new ArrayList();
		rectList.add( gRect );
		
		if( rectAxisBreakSymbols!=null )
		{
			rectList.add( rectAxisBreakSymbols );
		}
		
		Rectangle2D rectAll = SGUtility.createUnion( rectList );
		
		final float top = (float)( gRect.getY() - rectAll.getY() );
		final float bottom = (float)(
			( rectAll.getY() + rectAll.getHeight() )
			- ( gRect.getY() + gRect.getHeight() ) );
		final float left = (float)( gRect.getX() - rectAll.getX() );
		final float right = (float)(
			( rectAll.getX() + rectAll.getWidth() )
			- ( gRect.getX() + gRect.getWidth() ) );
		
		topAndBottom.x += top;
		topAndBottom.y += bottom;
		leftAndRight.x += left;
		leftAndRight.y += right;
		
		return true;
	}



	/**
	 * 
	 */
	protected Set getAvailableChildSet()
	{
		Set set = new HashSet();
		List mList = this.getMementoList();
		for( int ii=0; ii<mList.size(); ii++ )
		{
			AxisProperties ap = (AxisProperties)mList.get(ii);
			set.addAll( ap.visibleAxisBreakSymbolList );
		}

		return set;		
	}



	/**
	 * 
	 */
	public static class AxisProperties extends SGProperties
	{
		List visibleAxisBreakSymbolList = new ArrayList();

		AxisProperties(){}
		
		public void dispose()
		{
			this.visibleAxisBreakSymbolList.clear();
			this.visibleAxisBreakSymbolList = null;
		}
		
		/**
		 * 
		 */
		public boolean equals( final Object obj )
		{
			if( ( obj instanceof AxisProperties) == false )
			{
				return false;
			}
			
			AxisProperties p = (AxisProperties)obj;
			if( p.visibleAxisBreakSymbolList.equals(this.visibleAxisBreakSymbolList) == false )
			{
				return false;
			}

			return true;
		}
	}


	/**
	 * 
	 */
	public SGProperties getProperties()
	{
		AxisProperties wp = new AxisProperties();
		wp.visibleAxisBreakSymbolList = this.getVisibleChildList();
		return wp;
	}



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

		AxisProperties wp = (AxisProperties)p;
		final boolean flag = this.setVisibleChildList( wp.visibleAxisBreakSymbolList );
		if( !flag )
		{
			return false;
		}

		return true;
	}



	/**
	 * Create copies of the focused objects.
	 * @return
	 */
	public boolean duplicateFocusedObjects()
	{
		final int ox = (int)( this.mMagnification*OFFSET_DUPLICATED_OBJECT_X );
		final int oy = (int)( this.mMagnification*OFFSET_DUPLICATED_OBJECT_Y );

		ArrayList cList = this.duplicateObjects();
		for( int ii=0; ii<cList.size(); ii++ )
		{
			// duplicate
			AxisBreakSymbol el = (AxisBreakSymbol)cList.get(ii);

			// translate the duplicate
			el.translate( ox, oy );

			// set selected
			el.setSelected(true);

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

			// initialize history
			el.initPropertiesHistory();
		}

		if( cList.size()!=0 )
		{
			this.setChanged(true);
		}
		
//		this.repaint();

		return true;
	}



	/**
	 * Paste the objects.
	 * @param list of the objects to be pasted
	 * @return true:succeeded, false:failed
	 */
	public boolean paste( ArrayList list )
	{
		final float mag = this.getMagnification();
		final int ox = (int)( mag*OFFSET_DUPLICATED_OBJECT_X );
		final int oy = (int)( mag*OFFSET_DUPLICATED_OBJECT_Y );

		int cnt = 0;
		for( int ii=0; ii<list.size(); ii++ )
		{
			Object obj = list.get(ii);
			if( obj instanceof AxisBreakSymbol )
			{
				AxisBreakSymbol abs = (AxisBreakSymbol)obj;

				// translate the instance to be pasted
				abs.translate( ox, oy );

				SGProperties p = abs.getProperties();
				
				AxisBreakSymbol el = new AxisBreakSymbol();
				el.setMagnification(mag);
				el.setProperties(p);

				el.mXAxis = this.mAxisElement.getAxisInCube( abs.mTempXAxis );
				el.mYAxis = this.mAxisElement.getAxisInCube( abs.mTempYAxis );

				el.setDrawingElementsLocation();
				el.setAxisValue();

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

				// initialize history
				el.initPropertiesHistory();

				cnt++;
			}
		}
		
		if( cnt!=0 )
		{
			this.setChanged(true);
		}

//		this.repaint();

		return true;
	}



	//
	private AxisBreakSymbol getAxisBreakSymbol( final int id )
	{
		AxisBreakSymbol el = (AxisBreakSymbol)this.getChildObject(id);
		if( el == null ) return null;
		if( el.isVisible() == false ) return null;
		return el;
	}


	public boolean setAxisXDirectly( final int id, final int value )
	{
		AxisBreakSymbol el = this.getAxisBreakSymbol(id);
		if( el==null ) return false;
		if( this.setDirectlyBefore(el) == false ) return false;
		if( el.setXAxisLocation( value ) == false ) return false;
		if( this.setDirectlyAfter(el) == false ) return false;
		return true;
	}

	public boolean setAxisYDirectly( final int id, final int value )
	{
		AxisBreakSymbol el = this.getAxisBreakSymbol(id);
		if( el==null ) return false;
		if( this.setDirectlyBefore(el) == false ) return false;
		if( el.setYAxisLocation( value ) == false ) return false;
		if( this.setDirectlyAfter(el) == false ) return false;
		return true;
	}

	public boolean setLocationXDirectly( final int id, final double value )
	{
		AxisBreakSymbol el = this.getAxisBreakSymbol(id);
		if( el==null ) return false;
		if( this.setDirectlyBefore(el) == false ) return false;
		if( el.setXValue( value ) == false ) return false;
		if( this.setDirectlyAfter(el) == false ) return false;
		return true;
	}

	public boolean setLocationYDirectly( final int id, final double value )
	{
		AxisBreakSymbol el = this.getAxisBreakSymbol(id);
		if( el==null ) return false;
		if( this.setDirectlyBefore(el) == false ) return false;
		if( el.setYValue( value ) == false ) return false;
		if( this.setDirectlyAfter(el) == false ) return false;
		return true;
	}

	public boolean setLengthDirectly( final int id, final float value, final String unit )
	{
		AxisBreakSymbol el = this.getAxisBreakSymbol(id);
		if( el==null ) return false;
		if( this.setDirectlyBefore(el) == false ) return false;
		if( el.setLength( value, unit ) == false ) return false;
		if( this.setDirectlyAfter(el) == false ) return false;
		return true;
	}

	public boolean setIntervalDirectly( final int id, final float value, final String unit )
	{
		AxisBreakSymbol el = this.getAxisBreakSymbol(id);
		if( el==null ) return false;
		if( this.setDirectlyBefore(el) == false ) return false;
		if( el.setInterval( value, unit ) == false ) return false;
		if( this.setDirectlyAfter(el) == false ) return false;
		return true;
	}

	public boolean setDistortionDirectly( final int id, final float value )
	{
		AxisBreakSymbol el = this.getAxisBreakSymbol(id);
		if( el==null ) return false;
		if( this.setDirectlyBefore(el) == false ) return false;
		if( el.setDistortion( value ) == false ) return false;
		if( this.setDirectlyAfter(el) == false ) return false;
		return true;
	}

	public boolean setAngleDirectly( final int id, final float value )
	{
		AxisBreakSymbol el = this.getAxisBreakSymbol(id);
		if( el==null ) return false;
		if( this.setDirectlyBefore(el) == false ) return false;
		if( el.setAngle( value ) == false ) return false;
		if( this.setDirectlyAfter(el) == false ) return false;
		return true;
	}

	public boolean setLineWidthDirectly( final int id, final float value, final String unit )
	{
		AxisBreakSymbol el = this.getAxisBreakSymbol(id);
		if( el==null ) return false;
		if( this.setDirectlyBefore(el) == false ) return false;
		if( el.setLineWidth( value, unit ) == false ) return false;
		if( this.setDirectlyAfter(el) == false ) return false;
		return true;
	}

	public boolean setAlignmentDirectly( final int id, final boolean value )
	{
		AxisBreakSymbol el = this.getAxisBreakSymbol(id);
		if( el==null ) return false;
		if( this.setDirectlyBefore(el) == false ) return false;
		if( el.setForHorizontalAxisFlag( value ) == false ) return false;
		if( this.setDirectlyAfter(el) == false ) return false;
		return true;
	}

	public boolean setLineColorDirectly( final int id, final Color value )
	{
		AxisBreakSymbol el = this.getAxisBreakSymbol(id);
		if( el==null ) return false;
		if( this.setDirectlyBefore(el) == false ) return false;
		if( el.setLineColor( value ) == false ) return false;
		if( this.setDirectlyAfter(el) == false ) return false;
		return true;
	}

	public boolean setInnerColorDirectly( final int id, final Color value )
	{
		AxisBreakSymbol el = this.getAxisBreakSymbol(id);
		if( el==null ) return false;
		if( this.setDirectlyBefore(el) == false ) return false;
		if( el.setInnerColor( value ) == false ) return false;
		if( this.setDirectlyAfter(el) == false ) return false;
		return true;
	}


	private boolean setDirectlyBefore( AxisBreakSymbol el )
	{
		return el.prepare();
	}

	private boolean setDirectlyAfter( AxisBreakSymbol el )
	{
		if( el.commit() == false )
		{
			return false;
		}
		this.notifyChange();
		this.notifyToRoot();
		this.repaint();
		return true;
	}

	
	/**
	 * @author  okumura
	 */
	private class AxisBreakSymbol extends SGDrawingElementAxisBreak2D
		implements ActionListener, SGIAxisBreakDialogObserver,
			SGIUndoable, SGISelectable, SGIMovable, SGICopiable, SGINode, SGIDisposable,
			ChildObject
	{

		/**
		 * ID number.
		 */
		private int mID;


		public int getID()
		{
			return this.mID;
		}

		public boolean setID( final int id )
		{
			this.mID = id;
			return true;
		}


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

		
		/**
		 * 
		 */
		private double mXValue;

		
		/**
		 * 
		 */
		private double mYValue;

		
		/**
		 * 
		 */
		private boolean mFrameFlag = false;


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


		/**
		 * Pop-up menu.
		 */
		private JPopupMenu mPopupMenu = new JPopupMenu();


		/**
		 * 
		 */
		AxisBreakSymbol()
		{
			super();
			this.init();
		}


		/**
		 * 
		 */
		AxisBreakSymbol(
			final float length,
			final String lengthUnit,
			final float interval,
			final String intervalUnit,
			final float dist,
			final float angle,
			final boolean horizontal )
		{
			super(length,lengthUnit,interval,intervalUnit,dist,angle,horizontal);
			this.init();
		}


		/**
		 * 
		 * @return
		 */
		private boolean init()
		{
			this.createPopupMenu();
			return true;
		}


		/**
		 * 
		 */
		public void dispose()
		{
			super.dispose();
			this.mPopupMenu = null;
			this.mTemporaryProperties = null;
			this.mUndoManager.dispose();
			this.mUndoManager = null;
			this.mXAxis = null;
			this.mYAxis = null;
		}


		public String toString()
		{
			return "AxisBreak:"+this.mID;
		}

		public void finalize()
		{
//			System.out.println( "finalize:"+this );
		}


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


		/**
		 * 
		 */
		public int getYAxisLocation()
		{
			return SGFigureElementAxisBreak.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 SGFigureElementAxisBreak.this.mAxisElement.getAxisInPlane( config );
		}


		/**
		 * 
		 */
		public double getXValue()
		{
			return this.mXValue;
		}


		/**
		 * 
		 */
		public double getYValue()
		{
			return this.mYValue;
		}


		/**
		 * 
		 */
		public Color getInnerColor()
		{
			return this.getColor(0);
		}


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

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


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


		/**
		 * 
		 * @param value
		 */
		public boolean setXValue( final double value )
		{
			this.mXValue = value;
			return true;
		}


		/**
		 * 
		 * @param value
		 */
		public boolean setYValue( final double value )
		{
			this.mYValue = value;
			return true;
		}


		/**
		 * 
		 */
		public boolean setLineWidth( 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 super.setLineWidth( width, unit );
		}


		/**
		 * 
		 */
		public boolean setLength( final float len, final String unit )
		{
			final double conv = SGUtilityText.convert( len, unit, AXIS_BREAK_LENGTH_UNIT );
			if( conv < AXIS_BREAK_LENGTH_MIN ) return false;
			if( conv > AXIS_BREAK_LENGTH_MAX ) return false;

			return super.setLength( len, unit );
		}


		/**
		 * 
		 */
		public boolean setInterval( final float interval, final String unit )
		{
			final double conv = SGUtilityText.convert( interval, unit, AXIS_BREAK_INTERVAL_UNIT );
			if( conv < AXIS_BREAK_INTERVAL_MIN ) return false;
			if( conv > AXIS_BREAK_INTERVAL_MAX ) return false;

			return super.setInterval( interval, unit );
		}


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

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


		/**
		 * 
		 */
		public boolean setInnerColor( final Color cl )
		{
			return this.setColor( cl );
		}


		/**
		 * 
		 */
		public Object copy()
		{
			AxisBreakSymbol el = new AxisBreakSymbol();
			el.setMagnification( this.getMagnification() );
			el.setProperties( this.getProperties() );
			el.setLocation( this.getX(), this.getY() );
			el.mTempXAxis = SGFigureElementAxisBreak.this.mAxisElement.getLocationInCube( this.mXAxis );
			el.mTempYAxis = SGFigureElementAxisBreak.this.mAxisElement.getLocationInCube( this.mYAxis );
			return el;
		}


		private int mTempXAxis = -1;
		private int mTempYAxis = -1;


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



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


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


		/**
		 * 
		 * @return
		 */
		public String getInstanceDescription()
		{
			SGIFigureElementAxis aElement = SGFigureElementAxisBreak.this.mAxisElement;
			String xAxis = aElement.getLocationName( this.mXAxis );
			String yAxis = aElement.getLocationName( this.mYAxis );

			String str = "";
			str += this.mID + ": " + xAxis + ", " + yAxis + ", ";
			str += "( X=" + this.mXValue + ", Y=" + this.mYValue + " )";
			return str;
		}


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

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

			SGUtility.addItem( p, this, MENUCMD_MOVE_TO_FRONT );
			SGUtility.addItem( p, this, MENUCMD_MOVE_TO_BACK );

			p.addSeparator();

			SGUtility.addItem( p, this, MENUCMD_CUT );
			SGUtility.addItem( p, this, MENUCMD_COPY );
			SGUtility.addItem( p, this, MENUCMD_PASTE );

			p.addSeparator();

			SGUtility.addItem( p, this, MENUCMD_DELETE );
			SGUtility.addItem( p, this, MENUCMD_DUPLICATE );

			p.addSeparator();

			SGUtility.addItem( p, this, MENUCMD_PROPERTY );

			return true;
		}


		/**
		 * 
		 */
		public SGTuple2f getLocation()
		{
			final float basex = super.getX();
			final float basey = super.getY();
			final float x = this.getMagnification() * basex + SGFigureElementAxisBreak.this.mGraphRectX;
			final float y = this.getMagnification() * basey + SGFigureElementAxisBreak.this.mGraphRectY;
			return new SGTuple2f( x, y );
		}

		public float getX()
		{
			return this.getLocation().x;
		}

		public float getY()
		{
			return this.getLocation().y;
		}

		/**
		 * 
		 */
		public boolean setLocation( final float x, final float y)
		{
			final float mag = this.getMagnification();
			final float nx = ( x - SGFigureElementAxisBreak.this.mGraphRectX ) / mag;
			final float ny = ( y - SGFigureElementAxisBreak.this.mGraphRectY ) / mag;
			super.setLocation( nx, ny );
			return true;
		}


		/**
		 * 
		 */
		public void translate( final float dx, final float dy )
		{
			this.setLocation( this.getX() + dx, this.getY() + dy );
			this.setAxisValue();
			this.setDrawingElementsLocation();
		}
		
		
		/**
		 * 
		 * @param g2d
		 */
		private void drawBoundingBox( final Graphics2D g2d )
		{
			g2d.setStroke( new BasicStroke(1) );
			g2d.setPaint( Color.BLACK );
			g2d.draw( this.getElementBounds() );
		}



		/**
		 * 
		 * @return
		 */
		private ArrayList getAnchorPointList()
		{
			ArrayList list = new ArrayList();
			
			Shape array[] = this.getShapeArray();
			Line2D line1 = (Line2D)array[1];
			Line2D line2 = (Line2D)array[3];

			Point2D c1e = line1.getP1(); // mCurve1 end
			Point2D c2s = line1.getP2(); // mCurve2 start
			Point2D c2e = line2.getP1(); // mCurve2 end
			Point2D c1s = line2.getP2(); // mCurve1 start
			Point2D c1m = new Point2D.Float( 
					(float)( c1s.getX() + c1e.getX() ) / 2.0f,
					(float)( c1s.getY() + c1e.getY() ) / 2.0f
			);
			Point2D c2m = new Point2D.Float( 
					(float)( c2s.getX() + c2e.getX() ) / 2.0f,
					(float)( c2s.getY() + c2e.getY() ) / 2.0f
			);
			list.add( c1s ); list.add( c1m ); list.add( c1e );
			list.add( c2s ); list.add( c2m ); list.add( c2e );

			return list;
		}

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

			if( command.equals( MENUCMD_PROPERTY ) )
			{
				SGFigureElementAxisBreak.this.setPropertiesOfSelectedObjects();
			}
			else if(
				command.equals( MENUCMD_COPY )
				| command.equals( MENUCMD_CUT )
				| command.equals( MENUCMD_PASTE )
				| command.equals( MENUCMD_DELETE )
				| command.equals( MENUCMD_DUPLICATE )
				| command.equals( MENUCMD_MOVE_TO_FRONT )
				| command.equals( MENUCMD_MOVE_TO_BACK )
			)
			{
				notifyToListener( command );
			}

		}


		private boolean mValidFlag = true;

		public boolean isValid()
		{
			return this.mValidFlag;
		}

		public void setValid( final boolean b )
		{
			this.mValidFlag = b;
		}


		/**
		 * 
		 */
		public boolean setDrawingElementsLocation()
		{
//System.out.println(mGraphRectX+"  "+mGraphRectY);
			final float x = calcLocation( this.mXValue, this.mXAxis, true );
			final float y = calcLocation( this.mYValue, this.mYAxis, false );

			if( Float.isNaN(x) | Float.isNaN(y) )
			{
				this.setValid( false );
				return false;
			}
			this.setValid( true );

			this.setLocation(x,y);
			return true;
		}


		
		/**
		 * 
		 * @return
		 */
		public boolean setAxisValue()
		{
			final double xValue = calcValue( this.getX(), this.mXAxis, true );
			final double yValue = calcValue( this.getY(), this.mYAxis, false );

			this.mXValue = getNumberInRangeOrder( xValue, this.mXAxis );
			this.mYValue = getNumberInRangeOrder( yValue, this.mYAxis );
			
			return true;
		}
		
		
		
		/**
		 * @return
		 */
		public String getTagName()
		{
			return TAG_NAME_AXIS_BREAK_SYMBOL;
		}
		

		/**
		 * 
		 * @param document
		 * @return
		 */
		public Element createElement( final Document document )
		{
			Element el = document.createElement( this.getTagName() );
			if( this.writeProperty(el) == false )
			{
				return null;
			}
			return el;
		}
		
		
		/**
		 * 
		 * @param el
		 * @return
		 */
		public boolean writeProperty( final Element el )
		{
			if( super.writeProperty(el) == false )
			{
				return false;
			}

			el.setAttribute( KEY_X_VALUE, Double.toString( this.mXValue ) );
			el.setAttribute( KEY_Y_VALUE, Double.toString( this.mYValue ) );
			el.setAttribute( KEY_X_AXIS_POSITION, SGFigureElementAxisBreak.this.mAxisElement.getLocationName( this.mXAxis ) );
			el.setAttribute( KEY_Y_AXIS_POSITION, SGFigureElementAxisBreak.this.mAxisElement.getLocationName( this.mYAxis ) );

			return true;
		}
		
		

		/**
		 * 
		 */
		public boolean readProperty( final Element el )
		{

			if( super.readProperty(el) == false )
			{
				return false;
			}


			String str = null;
			Number num = null;
			Color cl = null;
			Boolean b = null;
			ArrayList list = null;


			// x axis
			str = el.getAttribute( KEY_X_AXIS_POSITION );
			if( str.length()!=0 )
			{
				SGAxis xAxis = SGFigureElementAxisBreak.this.mAxisElement.getAxis( str );
				if( xAxis==null )
				{
					return false;
				}
				this.mXAxis = xAxis;
			}
			
			
			// y axis
			str = el.getAttribute( KEY_Y_AXIS_POSITION );
			if( str.length()!=0 )
			{
				SGAxis yAxis = SGFigureElementAxisBreak.this.mAxisElement.getAxis( str );
				if( yAxis==null )
				{
					return false;
				}
				this.mYAxis = yAxis;
			}


			// x value
			str = el.getAttribute( SGIAxisBreakConstants.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;
				}
			}


			// y value
			str = el.getAttribute( SGIAxisBreakConstants.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;
				}
			}
			
			return true;
		}

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


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

			if( p.equals(this.mTemporaryProperties) == false )
			{
				this.setChanged(true);
			}
			
			if( this.create() == false )
			{
				return false;
			}
			
			if( this.setDrawingElementsLocation() == false )
			{
				return false;
			}

//
			repaint();

			return true;
		}


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


		/**
		 * 
		 */
		public boolean preview()
		{
			if( this.create() == false )
			{
				return false;
			}
			
			if( this.setDrawingElementsLocation() == false )
			{
				return false;
			}

			repaint();

			return true;
		}



		private SGUndoManager mUndoManager = new SGUndoManager(this);

		/**
		 * 
		 * @return
		 */
		public SGProperties getMemento()
		{
			return this.getProperties();
		}


		/**
		 * 
		 * @param p
		 * @return
		 */
		public boolean setMemento( SGProperties p )
		{
			return this.setProperties(p);
		}


		/**
		 * 
		 * @return
		 */
		public boolean isUndoable()
		{
			return this.mUndoManager.isUndoable();
		}

	
		/**
		 * 
		 * @return
		 */
		public boolean isRedoable()
		{
			return this.mUndoManager.isRedoable();
		}


		/**
		 * 
		 */
		public boolean initPropertiesHistory()
		{
			return this.mUndoManager.initPropertiesHistory();
		}


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

			this.create();
			this.setDrawingElementsLocation();

			return true;
		}


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

			this.create();
			this.setDrawingElementsLocation();

			return true;
		}



		/**
		 * アンドゥ操作を依頼する
		 */
		public boolean undo()
		{
			return this.setMementoBackward();
		}

	
	
		/**
		 * リドゥ操作を依頼する
		 */
		public boolean redo()
		{
			return this.setMementoForward();
		}


		/**
		 * 履歴の更新の実行。アンドゥ対象の操作が行われたときに、真っ先に呼ばれる。
		 */
		public boolean updateHistory()
		{
			return this.mUndoManager.updateHistory();
		}


		/**
		 * 
		 */
		public void initUndoBuffer()
		{
			this.mUndoManager.initUndoBuffer();
		}


		/**
		 * 
		 */
		public boolean isChanged()
		{
			return this.mUndoManager.isChanged();
		}

		
		public void setChanged( final boolean b )
		{
			this.mUndoManager.setChanged( b );
		}

		public boolean isChangedRoot()
		{
			return this.isChanged();
		}


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

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

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

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

			AxisBreakSymbolWithAxesProperties ap = (AxisBreakSymbolWithAxesProperties)p;


			final Double x = ap.getXValue();
			if( x==null )
			{
				return false;
			}
			this.mXValue = x.doubleValue();
			
			
			final Double y = ap.getYValue();
			if( y==null )
			{
				return false;
			}
			this.mYValue = y.doubleValue();
			
			this.mXAxis = ap.mXAxis;
			this.mYAxis = ap.mYAxis;
			
			return true;
		}



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

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

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

			final AxisBreakSymbolWithAxesProperties dp = (AxisBreakSymbolWithAxesProperties)p;
			dp.setXValue( this.mXValue );
			dp.setYValue( this.mYValue );
			dp.mXAxis = this.mXAxis;
			dp.mYAxis = this.mYAxis;

			return true;
		}



		/**
		 * Flag whether this object is focused.
		 */
		private boolean mSelectedFlag = false;


		/**
		 * Get the flag as a focused object.
		 * @return whether this object is focused.
		 */
		public boolean isSelected()
		{
			return this.mSelectedFlag;
		}


		/**
		 * Set the flag as a focused object.
		 * @param b focused
		 */
		public void setSelected( final boolean b )
		{
			this.mSelectedFlag = b;
		}

	}


	
	/**
	 * Property of Axis Break Symbol.
	 */
	public static class AxisBreakSymbolWithAxesProperties
		extends AxisBreakSymbolProperties
	{

		private double mXValue = 0.0;
		private double mYValue = 0.0;
		private SGAxis mXAxis = null;
		private SGAxis mYAxis = null;

		/**
		 * 
		 */
		public AxisBreakSymbolWithAxesProperties()
		{
			super();
		}


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

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

			AxisBreakSymbolWithAxesProperties p = (AxisBreakSymbolWithAxesProperties)obj;

			if( p.mXValue!=this.mXValue ) return false;
			if( p.mYValue!=this.mYValue ) return false;
			if( this.mXAxis.equals( p.mXAxis ) == false ) return false;
			if( this.mYAxis.equals( p.mYAxis ) == false ) return false;

			return true;
		}


		public Double getXValue()
		{
			return new Double( this.mXValue );
		}
		
		public Double getYValue()
		{
			return new Double( this.mYValue );
		}

		public SGAxis getXAxis()
		{
			return this.mXAxis;
		}

		public SGAxis getYAxis()
		{
			return this.mYAxis;
		}

		public boolean setXValue( final double value )
		{
			this.mXValue = value;
			return true;
		}

		public boolean setYValue( final double value )
		{
			this.mYValue = value;
			return true;
		}

		private boolean setXAxis( final SGAxis axis )
		{
			if( axis==null )
			{
				throw new IllegalArgumentException("axis==null");
			}
			this.mXAxis = axis;
			return true;
		}

		private boolean setYAxis( final SGAxis axis )
		{
			if( axis==null )
			{
				throw new IllegalArgumentException("axis==null");
			}
			this.mYAxis = axis;
			return true;
		}

	}


}

