
package jp.riken.brain.ni.samuraigraph.application;

import java.util.*;
import java.io.*;
import java.net.*;
import java.awt.dnd.*;
import java.awt.datatransfer.*;
import java.awt.*;
import java.awt.geom.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.table.*;
import jp.riken.brain.ni.samuraigraph.base.*;
import jp.riken.brain.ni.samuraigraph.data.*;
import jp.riken.brain.ni.samuraigraph.figure.*;
import jp.riken.brain.ni.samuraigraph.figure.java2d.*;



/**
 * グラフ描画サーバクラス
 */
public class SGDrawingServer
{

	/**
	 * 
	 */
	public static final int DEFAULT_PORT_NUMBER = 5557;


	/**
	 * 
	 */
	public static int PORT_NUMBER = DEFAULT_PORT_NUMBER;


	/**
	 * 
	 */
	public static final String COM_WOPEN = "wopen";


	/**
	 * 
	 */
	public static final String COM_ADD_DATE = "addData";


	/**
	 * 
	 */
	public static final String COM_READ_PROPERTY = "readProperty";



	/**
	 * main function
	 * @param args
	 */
	public static void main(String args[])
	{
/*
System.out.println("*** main ***");
for( int ii=0; ii<args.length; ii++ )
{
	System.out.println(ii+"  "+args[ii]);
}
System.out.println();
*/
		// interpret command lines
		interpretCommands( args );


		try
		{

			// create a server socket object
			ServerSocket serverSocket = new ServerSocket( SGDrawingServer.PORT_NUMBER );

			try
			{
//System.out.println("port="+serverSocket.getLocalPort());

				// create a new thread
				Connect c = new Connect(serverSocket);
			}
			catch ( Exception ex )
			{
				ex.printStackTrace();
			}

		}
		catch ( Exception ex )
		{
			ex.printStackTrace();
		}

	}



	/**
	 * 
	 */
	private static boolean interpretCommands( final String[] commands )
	{

		for( int ii=0; ii<commands.length; ii++ )
		{
			if( commands[ii].equals("-p") )
			{
				if( ii+1<commands.length )
				{
					try
					{
						Integer n = Integer.valueOf( commands[ii+1] );
						if( n==null )
						{
							continue;
						}
						PORT_NUMBER = n.intValue();
//System.out.println("*** "+PORT_NUMBER);
					}
					catch( NumberFormatException ex )
					{
						ex.printStackTrace();
						continue;
					}
				}
			}
		}


		return true;
	}





/**
 *  入出力スレッド
 */

public static class Connect extends Thread
	implements ActionListener, WindowListener, DropTargetListener
{



	/**
	 * 
	 */
	private Class mClassOfAxisElement = null;


	/**
	 * 
	 */
	private Class mClassOfSXYGraphElement = null;


	/**
	 * 
	 */
	private Class mClassOfVXYGraphElement = null;


	/**
	 * 
	 */
	private Class mClassOfLegendElement = null;


	/**
	 * 
	 */
	private Class mClassOfStringElement = null;



	/**
	 * 
	 */
	public final String PROPERTY_FILE_READ_MSG_DIALOG_TITLE = "Property file has read.";



	/**
	 * 
	 */
	public final String MSG_SUCCESSFUL_COMPLETION
		= "正常終了";


	/**
	 * 
	 */
	public final String ERRMSG_PROPERTY_FILE_INCORRECT
		= "プロパティファイルの記述が不正です。";


	/**
	 * 
	 */
	public final String ERRMSG_DATA_TYPE_INCORRECT
		= "データのタイプが違います。";


	/**
	 * 
	 */
	public final String ERRMSG_DATA_NUMBER_SHORTAGE
		= "データ数が不足しています。";


	/**
	 * 
	 */
	public final String ERRMSG_DATA_NUMBER_EXCESS
		= "データ数が過剰です。";


	/**
	 * 
	 */
	public final String ERRMSG_FILE_OPEN_FAILURE
		= "ファイルが開けませんでした。";


	/**
	 * 
	 */
	private float mRulerUnit = SGConstants.CM_POINT_RATIO;


	/**
	 * サーバソケット
	 */
	private ServerSocket mServerSocket = null;


	/**
	 * ウインドウリスト
	 */
	private TreeMap mWndMap = new TreeMap();


	/**
	 * データリスト
	 */
	private ArrayList mDataList = new ArrayList();


	/**
	 * データファイル名リスト
	 */
	private ArrayList mDataFileNameList = new ArrayList();



	/**
	 * コンストラクタ
	 */
	public Connect()
	{
	}



	/**
	 * コンストラクタ
	 */
	public Connect( ServerSocket serverSocket )
	{
		this.mServerSocket = serverSocket;

		// スレッド開始
		this.start();
	}


	/**
	 * 
	 */
	public void run()
	{

//System.out.println("サーバが起動されました。");

		//
		// SGFigureElementのリストをファイルから読み込む
		//
//System.out.println("SGFigureElementのリストをファイルから読み込む。");
		if( this.setFigureElementClass() == false )
		{
System.out.println("クラスインスタンスの作成に失敗しました。");
			return;
		}


		// 起動時にウインドウを一つ作成する
//System.out.println("ウインドウを作成します。");
		if( !this.createNewWindow() )
		{
System.out.println("ウインドウの作成に失敗しました。");
			return;
		}


		// 無限ループ
		while( true )
		{
			try
			{

				// クライアントからの接続を待つ
//System.out.println("port="+mServerSocket.getLocalPort());
				Socket socket = mServerSocket.accept();
//System.out.println(socket.getInetAddress() + "から接続を受付ました");

				// 出力ストリームを取得
				PrintWriter out = new PrintWriter( socket.getOutputStream(), true );

				// 入力ストリームを取得
				BufferedReader in = new BufferedReader(
					new InputStreamReader( socket.getInputStream() ) );

				// 入力ストリームからの読み込み
				ArrayList commandList = new ArrayList();
				String inputLine;
				while( (inputLine = in.readLine()) != null )
				{
					commandList.add( new String( inputLine ) );
				}
				if( commandList.size() == 0 )
				{
					System.out.println("入力がありません。");
					continue;
				}
//System.out.println(commandList);
				String[] commandArray = new String[commandList.size()];
				for( int ii=0; ii<commandArray.length; ii++ )
				{
					commandArray[ii] = (String)commandList.get(ii);
				}


				//
				// コマンドラインに応じた処理
				//
				
				if( this.executeCommand(commandArray) == false )
				{
// TODO:クライアントにエラーメッセージを返す
					continue;
				}

// TODO:クライアントに成功したメッセージを返す


				// 入出力ストリームを閉じる
				in.close();
				out.close();

				// ソケットを閉じる
				socket.close();

			}
			catch(Exception ex)
			{
				ex.printStackTrace();
			}

		}

	}



	/**
	 * Default class name of axis figure element.
	 */
	public static final String DEFAULT_CLASS_NAME_OF_AXIS_ELEMENT
		= "jp.riken.brain.ni.samuraigraph.figure.java2d.SGAxisElement";

	/**
	 * Default class name of sxy-graph figure element.
	 */
	public static final String DEFAULT_CLASS_NAME_OF_SXY_GRAPH_ELEMENT
		= "jp.riken.brain.ni.samuraigraph.figure.java2d.SGSXYGraphElement";

	/**
	 * Default class name of vxy-graph figure element.
	 */
	public static final String DEFAULT_CLASS_NAME_OF_VXY_GRAPH_ELEMENT
		= "jp.riken.brain.ni.samuraigraph.figure.java2d.SGVXYGraphElement";

	/**
	 * Default class name of string figure element.
	 */
	public static final String DEFAULT_CLASS_NAME_OF_STRING_ELEMENT
		= "jp.riken.brain.ni.samuraigraph.figure.java2d.SGStringElement";

	/**
	 * Default class name of legend figure element.
	 */
	public static final String DEFAULT_CLASS_NAME_OF_LEGEND_ELEMENT
		= "jp.riken.brain.ni.samuraigraph.figure.java2d.SGLegendElement";



	/**
	 * falseならクラス名の取得失敗
	 */
	private boolean setFigureElementClass()
	{

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

		try
		{

			// open the file
			FileInputStream fis = null;

			try
			{
				fis = new FileInputStream("ListOfFigureElement.txt");
			}
			catch( FileNotFoundException ex )
			{
//System.out.println("ファイルが見つかりませんので、デフォルトのクラスインスタンスを作成します。");

				this.mClassOfAxisElement = Class.forName(DEFAULT_CLASS_NAME_OF_AXIS_ELEMENT);
				this.mClassOfSXYGraphElement = Class.forName(DEFAULT_CLASS_NAME_OF_SXY_GRAPH_ELEMENT);
				this.mClassOfVXYGraphElement = Class.forName(DEFAULT_CLASS_NAME_OF_VXY_GRAPH_ELEMENT);
				this.mClassOfStringElement = Class.forName(DEFAULT_CLASS_NAME_OF_STRING_ELEMENT);
				this.mClassOfLegendElement = Class.forName(DEFAULT_CLASS_NAME_OF_LEGEND_ELEMENT);

				return true;
			}

//System.out.println("File is found!");

			InputStreamReader isw = new InputStreamReader(fis);
			BufferedReader br = new BufferedReader(isw);


			// read the file
			String line = null;
			Class cl = null;


			// SGAxisElement
			if( (line=SGUtilityText.readLine(br)) == null )
			{
				return false;
			}
			if( (line=SGUtilityText.getPropertyFromLine(line,"SGAxisElement")) == null )
			{
				return false;
			}
			cl = Class.forName(line);
			if( ( cl.newInstance() instanceof SGIAxisElement ) == false )
			{
				return false;
			}
			this.mClassOfAxisElement = cl;


			// SGSXYGraphElement
			if( (line=SGUtilityText.readLine(br)) == null )
			{
				return false;
			}
			if( (line=SGUtilityText.getPropertyFromLine(line,"SGSXYGraphElement")) == null )
			{
				return false;
			}
			cl = Class.forName(line);
			if( ( cl.newInstance() instanceof SGIGraphElement ) == false )
			{
				return false;
			}
			this.mClassOfSXYGraphElement = cl;


			// SGVXYGraphElement
			if( (line=SGUtilityText.readLine(br)) == null )
			{
				return false;
			}
			if( (line=SGUtilityText.getPropertyFromLine(line,"SGVXYGraphElement")) == null )
			{
				return false;
			}
			cl = Class.forName(line);
			if( ( cl.newInstance() instanceof SGIGraphElement ) == false )
			{
				return false;
			}
			this.mClassOfVXYGraphElement = cl;


			// SGLegendElement
			if( (line=SGUtilityText.readLine(br)) == null )
			{
				return false;
			}
			if( (line=SGUtilityText.getPropertyFromLine(line,"SGLegendElement")) == null )
			{
				return false;
			}
			cl = Class.forName(line);
			if( ( cl.newInstance() instanceof SGILegendElement ) == false )
			{
				return false;
			}
			this.mClassOfLegendElement = cl;


			// SGStringElement
			if( (line=SGUtilityText.readLine(br)) == null )
			{
				return false;
			}
			if( (line=SGUtilityText.getPropertyFromLine(line,"SGStringElement")) == null )
			{
				return false;
			}
			cl = Class.forName(line);
			if( ( cl.newInstance() instanceof SGIStringElement ) == false )
			{
				return false;
			}
			this.mClassOfStringElement = cl;


			br.close();
			isw.close();
			fis.close();
	
		}
		catch( Exception ex )
		{
			ex.printStackTrace();
			return false;
		}


/*
System.out.println(this.mClassOfAxisElement);
System.out.println(this.mClassOfSXYGraphElement);
System.out.println(this.mClassOfVXYGraphElement);
System.out.println(this.mClassOfLegendElement);
System.out.println(this.mClassOfStringElement);
System.out.println();
*/

		return true;
	}



	/**
	 * 
	 */
	private boolean executeCommand( final String[] commandArray )
	{

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

		// 第1引数のコマンド名に応じて分岐
		boolean flag = true;
		if( SGDrawingServer.COM_WOPEN.equals( commandArray[0]) )
		{
			flag = this.wopen( commandArray );
		}
		else if( SGDrawingServer.COM_ADD_DATE.equals(commandArray[0]) )
		{
			flag = this.addDataByCommandLine( commandArray );
		}
		else if( SGDrawingServer.COM_READ_PROPERTY.equals(commandArray[0]) )
		{
			flag = this.readWindowProperty( commandArray );
		}
		else
		{
			System.out.println("コマンド名が不正です。");
			return false;
		}

		if( !flag )
		{
			return false;
		}


		return true;

	}



	/**
	 * 
	 */
	private boolean wopen( final String[] commandArray )
	{

		if( commandArray.length < 1 )
		{
			return false;
		}


		// ウインドウ番号
		int windowID;
		if( commandArray.length > 1 )
		{
			String str = commandArray[1];
			Integer ID = this.getWindowIDFromString(str);
			if( ID==null )
			{
				return false;
			}
			windowID = ID.intValue();
		}
		else
		{
			windowID = this.getCurrentWindowID();
		}
//System.out.println(windowID);

		SGDrawingWindow wnd = this.getWindow(windowID);
		if( wnd != null )
		{
			System.out.println("そのウインドウは既に存在しています。");
			return false;
		}
		wnd = this.createWindow(windowID);
		if( wnd==null )
		{
			return false;
		}


		// show the window
		wnd.show();


		return true;

	}



	/**
	 * 
	 */
	private SGDrawingWindow getWindowForCommand( final int windowID )
	{

		SGDrawingWindow wnd = this.getWindow( windowID );
		if( wnd==null )
		{
			System.out.println("指定されたウインドウはありません。");
			System.out.println("ウインドウを新規作成します。");
					
			// ウインドウを作成
			wnd = this.createWindow(windowID);
			if( wnd == null )
			{
				System.out.println("ウインドウの生成に失敗しました。");
				return null;
			}
		}

		return wnd;
	}



	/**
	 * 
	 */
	public static final int MAX_WINDOW_ID = 256;


	/**
	 * 
	 */
	private Integer getWindowIDFromString( final String str )
	{

		Integer ID;
		try
		{
			ID = (Integer)Integer.valueOf(str);
		}
		catch ( Exception ex )
		{
			System.out.println("引数が不正です。");
			return null;
		}

		int id = ID.intValue();
		if( id < 1 )
		{
			System.out.println("ウインドウ番号は正の整数を入力して下さい。");
			return null;
		}
		else if( id > MAX_WINDOW_ID )
		{
			System.out.println("ウインドウ番号が大き過ぎます。");
			return null;
		}

		return ID;
	}



	/**
	 * 
	 */
	private boolean addDataByCommandLine( final String[] commandArray )
	{

		// ファイル名、[ウインドウ番号]、[フィギュア番号]を取得する
		if( commandArray.length < 2 )
		{
			System.out.println("コマンド引数が足りません。");
			return false;
		}

		// データファイル名
		String dataFileName = commandArray[1];


		// ウインドウ番号
		int windowID;
		if( commandArray.length > 2 )
		{
			final String str = commandArray[2];
			Integer ID = this.getWindowIDFromString(str);
			if( ID==null )
			{
				return false;
			}
			windowID = ID.intValue();
		}
		else
		{
			windowID = this.getCurrentWindowID();
		}
//System.out.println("windowID="+windowID);


		// ウインドウの取得
		SGDrawingWindow wnd = this.getWindowForCommand( windowID );
		if( wnd==null )
		{
			return false;
		}


		// フィギュア番号
		int figureID;
		if( commandArray.length > 3 )
		{
			String str = commandArray[3];
			figureID = (Integer.valueOf(str)).intValue();
		}
		else
		{
			figureID = wnd.getCurrentFigureId();
		}
//System.out.println("figureID="+figureID);


		// create a wizard dialog to select data-type
		this.mXYDataTypeSelectionWizardDialogFromCLorDD
			= new SGXYDataTypeSelectionWizardDialog( wnd, true );
		this.mXYDataTypeSelectionWizardDialogFromCLorDD.addActionListener(this);
		this.mXYDataTypeSelectionWizardDialogFromCLorDD.mPreviousButton.setEnabled(false);


		// create data object from file
		SGData data = this.createDataFromFile( dataFileName );
		if( data == null )
		{
			System.out.println("データの構築に失敗しました。");
			return false;
		}


		// get the figure from the window
		SGFigure figure = wnd.getFigure( figureID );

		// if figure does not exist or invisible, create a new figure
		if( figure==null || ( figure!=null && figure.isVisible()==false ) )
		{
			if( this.createNewFigure( wnd, figureID, data, new Point() ) == null )
			{
				return false;
			}
		}
		else
		// else add data to the figure
		{
			if( !figure.addData(data) )
			{
				System.out.println("データの型がフィギュアに合いません。");
				return false;
			}
		}


		return true;

	}




	/**
	 * 
	 */
	private boolean readWindowProperty( final String[] commandArray )
	{

		if( commandArray.length < 3 )
		{
			System.out.println("引数が不足しています。");
			return false;
		}


		// プロパティファイル名
		final String propertyFileName = commandArray[1];



		// データを格納したファイル名をリストに保存
		this.mDataFileNameList.clear();	// 一旦、クリアする
		for( int ii=2; ii<commandArray.length; ii++ )
		{
			this.mDataFileNameList.add(commandArray[ii]);
		}

		// ウインドウにプロパティファイルを読み込ませる
		SGDrawingWindow wnd = null;

		try
		{
			// create a window
			wnd = this.createWindowFromPropertyFile(propertyFileName);
		}
		catch( Exception ex )
		{
			ex.printStackTrace();
		}

		if( wnd == null )
		{
			System.out.println("プロパティファイルの読み込みに失敗しました。");
		}


		return true;

	}



	/**
	 * 
	 */
	private boolean readFigureProperty( final String[] commandArray )
	{

		// 引数チェック
		if( commandArray.length < 3 )
		{
			System.out.println("引数が不足しています。");
			return false;
		}


		// ウインドウ番号の読み込み
		int windowID = -1;
		try
		{
			windowID = ( Integer.valueOf( commandArray[1] ) ).intValue();
		}
		catch( Exception ex )
		{
			ex.printStackTrace();
		}


		// 引数で指定されたウインドウを開く
		SGDrawingWindow wnd = this.getWindow( windowID );
		if( wnd == null )
		{
			System.out.println("指定されたウインドウはありません。");
			return false;
		}


		// データを格納したファイル名をリストに保存
		this.mDataFileNameList.clear();	// 一旦、クリアする
		for( int ii=2; ii<commandArray.length; ii++ )
		{
			this.mDataFileNameList.add(commandArray[ii]);
		}



		return true;

	}




	/**
	 * 
	 * @param wnd
	 * @return
	 */
	private boolean setWindowLocation( final SGDrawingWindow wnd )
	{
		// set the location
		final Dimension scSize = Toolkit.getDefaultToolkit().getScreenSize();
		final int x = (int)( scSize.getWidth() - wnd.getWidth() )/2;
		final int y = (int)( scSize.getHeight() - wnd.getHeight() )/2;
		wnd.setLocation(x,y);
	
		return true;
	}


	/**
	 * 
	 */
	public SGDrawingWindow getWindow( final int wndID )
	{

		SGDrawingWindow wnd = (SGDrawingWindow)this.mWndMap.get( new Integer(wndID) );

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

		return wnd;		

	}



	/**
	 * 
	 */
	private SGFigure createFigure(
		final int figureID,
		final SGDrawingWindow wnd,
		final SGData data )
	{
//System.out.println("<< createFigure >>");


		SGFigure figure = null;

//System.out.println(data);

		// XY型データの場合
		if( data instanceof SGSXYData || data instanceof SGSXYMultipleData )
		{
			figure = new SGSXYFigure( wnd );
		}
		else if( data instanceof SGVXYData )
		{
			figure = new SGVXYFigure( wnd );
		}
		else
		{
			System.out.println("対応するデータ型がありません。");
			return null;
		}


		//
		figure.setID(figureID);
//		figure.setToolTipText( new Integer(figureID).toString() );


		// SGFigureElementオブジェクトの追加
		if( this.createFigureElements( figure, data ) == false )
		{
			return null;
		}


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

		//
		float w = SGDefaultValues.DEFAULT_FIGURE_WIDTH;
		float h = w/SGConstants.GOLDEN_RATIO;
		figure.setGraphAreaSize( w, h );

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


		return figure;

	}



	/**
	 * 
	 */
	private boolean createFigureElements(
		final SGFigure figure,
		final SGData data )
	{

		try
		{

			SGDrawingWindow wnd = figure.getWindow();


			//
			// create a SGAxisElement
			//

			Object axisObj = this.mClassOfAxisElement.newInstance();

			JComponent axisCom = (JComponent)axisObj;
			axisCom.setBounds( 0, 0, figure.getWidth(), figure.getHeight() );
			axisCom.setVisible(true);
			axisCom.setOpaque(false);
			figure.add(axisCom);
			figure.setLayer(axisCom,SGFigure.LAYER_AXIS);

			SGIAxisElement axisElement = (SGIAxisElement)axisObj;
			figure.setAxisElement(axisElement);
			axisElement.addActionListener(figure);
			axisElement.setDialogOwner(wnd);


			//
			// create a SGGraphElement
			//

			Object graphObj = null;
			if( data instanceof SGSXYData || data instanceof SGSXYMultipleData)
			{
				graphObj = this.mClassOfSXYGraphElement.newInstance();
			}
			else if( data instanceof SGVXYData )
			{
				graphObj = this.mClassOfVXYGraphElement.newInstance();
			}
			else
			{
				System.out.println("対応するデータ型がありません。");
				return false;
			}

			JComponent graphCom = (JComponent)graphObj;
			graphCom.setBounds( 0, 0, figure.getWidth(), figure.getHeight() );
			graphCom.setVisible(true);
			graphCom.setOpaque(false);
			figure.add(graphCom);
			figure.setLayer(graphCom,SGFigure.LAYER_GRAPH);

			SGIGraphElement graphElement = (SGIGraphElement)graphObj;
			figure.setGraphElement(graphElement);
			graphElement.addActionListener(figure);
			graphElement.setDialogOwner(wnd);


			//
			// create a SGLegendElement
			//

			Object legendObj = this.mClassOfLegendElement.newInstance();

			JComponent legendCom = (JComponent)legendObj;
			legendCom.setBounds( 0, 0, figure.getWidth(), figure.getHeight() );
			legendCom.setVisible(true);
			legendCom.setOpaque(false);
			figure.add(legendCom);
			figure.setLayer(legendCom,SGFigure.LAYER_LEGEND);

			SGILegendElement legendElement = (SGILegendElement)legendObj;
			figure.setLegendElement(legendElement);
			legendElement.addActionListener(figure);
			legendElement.setDialogOwner(wnd);


			//
			// create a SGStringElement
			//

			Object stringObj = this.mClassOfStringElement.newInstance();

			JComponent stringCom = (JComponent)stringObj;
			stringCom.setBounds( 0, 0, figure.getWidth(), figure.getHeight() );
			stringCom.setVisible(true);
			stringCom.setOpaque(false);
			figure.add(stringCom);
			figure.setLayer(stringCom,SGFigure.LAYER_STRING);

			SGIStringElement stringElement = (SGIStringElement)stringObj;
			figure.setStringElement(stringElement);
			stringElement.addActionListener(figure);
			stringElement.setDialogOwner(wnd);


			//
			graphElement.setAxisElement( axisElement );


			//
			legendElement.setGraphElement( graphElement );


		}
		catch( Exception ex )
		{
			ex.printStackTrace();
		}
		


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

		return true;
	}







	/**
	 * データファイルを開いて情報を取得し、データを構築する
	 */
	private SGData createDataFromFile(
		final String pathName )
	{
//System.out.println("<< createDataFromFile >>");

		// ファイルの情報リスト
		ArrayList infoList = new ArrayList();

		// ファイルから情報を取得
		boolean flag = this.readFile( pathName, infoList );
		if( !flag )
		{
			return null;
		}

		// データの構築
		if( infoList.size()==0 )
		{
			return null;
		}
		SGData data = this.createData( pathName, infoList );

//System.out.println(data);

		return data;		

	}




	/**
	 * 
	 */
	private SGFigureIDSelectionWizardDialog mFigureIDSelectionWizardDialog = null;


	/**
	 * 
	 */
	private SGMultiDataFileChooserWizardDialog mMultiDataFileChooserWizardDialog = null;


	/**
	 * 
	 */
	private SGSingleDataFileChooserWizardDialog mSingleDataFileChooserWizardDilaog = null;



	/**
	 * 
	 */
	private SGXYDataTypeSelectionWizardDialog mXYDataTypeSelectionWizardDialog = null;



	/**
	 * 
	 */
	private SGXYDataTypeSelectionWizardDialog mXYDataTypeSelectionWizardDialogFromCLorDD = null;


	/**
	 * 
	 */
	private SGPropertyFileChooserWizardDialog mPropertyFileChooserWizardDilaog = null;



	/**
	 * 
	 */
	private boolean createAllWizardDialogsForDataAdditionFromToolBar( final SGDrawingWindow owner )
	{

		//
		// create dialog objects
		//

		final int id = owner.getID();

		// dialog to select ID of window and figure
		this.mFigureIDSelectionWizardDialog
			= new SGFigureIDSelectionWizardDialog( owner, true );


		// dialog to select data files
		this.mSingleDataFileChooserWizardDilaog
			= new SGSingleDataFileChooserWizardDialog( owner, true );
//		this.mSingleDataFileChooserDilaog.setTitle("Choose a data file.");


		// dialog to select data-type
		this.mXYDataTypeSelectionWizardDialog
			= new SGXYDataTypeSelectionWizardDialog( owner, true );


		//
		// next and previous dialog
		//
		
		this.mFigureIDSelectionWizardDialog.setNext( this.mSingleDataFileChooserWizardDilaog );
		this.mSingleDataFileChooserWizardDilaog.setPrevious( this.mFigureIDSelectionWizardDialog );
		this.mSingleDataFileChooserWizardDilaog.setNext( this.mXYDataTypeSelectionWizardDialog );
		this.mXYDataTypeSelectionWizardDialog.setPrevious( this.mSingleDataFileChooserWizardDilaog );


		//
		// add action listener
		//

		this.mFigureIDSelectionWizardDialog.addActionListener(this);
		this.mSingleDataFileChooserWizardDilaog.addActionListener(this);
		this.mXYDataTypeSelectionWizardDialog.addActionListener(this);


		return true;

	}




	/**
	 * 
	 */
	private boolean createAllWizardDialogsToLoadPropertyFromToolBar( final SGDrawingWindow owner )
	{

		//
		// create dialog objects
		//

		final int id = owner.getID();


		// dialog to load property file
		this.mPropertyFileChooserWizardDilaog
			= new SGPropertyFileChooserWizardDialog( owner, true );


		// dialog to select data files
		this.mMultiDataFileChooserWizardDialog
			= new SGMultiDataFileChooserWizardDialog( owner, true );


		//
		// next and previous dialog
		//

		this.mPropertyFileChooserWizardDilaog.setNext( this.mMultiDataFileChooserWizardDialog );
		this.mMultiDataFileChooserWizardDialog.setPrevious( this.mPropertyFileChooserWizardDilaog );				



		//
		// add action listener
		//

		this.mPropertyFileChooserWizardDilaog.addActionListener(this);
		this.mMultiDataFileChooserWizardDialog.addActionListener(this);


		return true;

	}






	/**
	 * determine the data-type from the first line
	 */
	private boolean getFileTypeCandidateList(
		final Window owner,
		final String pathName,
		final ArrayList cList,
		final ArrayList tokenNumList )
	{

		try
		{

			FileInputStream fis = null;
			try
			{
				fis = new FileInputStream( pathName );
			}
			catch( FileNotFoundException ex )
			{
//				Window owner = this.mSingleDataFileChooserWizardDilaog.getOwner();
				SGUtility.showFileNotFoundMessageDialog( owner );
				return false;
			}
			InputStreamReader ir = new InputStreamReader(fis);
			BufferedReader br = new BufferedReader(ir);
			String line = SGUtilityText.readLine(br);
			br.close();
			ir.close();
			fis.close();

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


			// break the string into tokens
			ArrayList tokenList = new ArrayList();
			SGUtilityText.tokenize( line, tokenList );
			int tokenNum = tokenList.size();	// the number of tokens
			if( tokenNum==0 )
			{
				return false;
			}


			// get candidates of data-type
			if( tokenNum==2		// x,y
				|| tokenNum==3		// x,y,string
				|| tokenNum==5		// x,y,e+,e-,string
				)
			{
				if( this.evaluateDataTypeSXY(tokenList) )
				{
					cList.add(SGDataTypeConstants.SXY_DATA);
				}
			}
			else if( tokenNum==4 )
			{
				if( this.evaluateDataTypeSXY(tokenList) )
				{
					cList.add(SGDataTypeConstants.SXY_DATA);
				}

//				cList.add(SGDataTypeConstants.VXY_DATA);
			}
			if( tokenNum>=2 )
			{
				if( this.evaluateDataTypeSXYMultiple(tokenList) )
				{
					cList.add(SGDataTypeConstants.SXY_MULTIPLE_DATA);
				}
			}
			if( tokenNum>=1 )
			{
				if( this.evaluateDataTypeSXYMultiple(tokenList) )
				{
					cList.add(SGDataTypeConstants.SXY_SAMPLING_DATA);
				}
			}

			tokenNumList.add( new Integer(tokenNum) );

		}
		catch( Exception ex )
		{
			ex.printStackTrace();
			return false;
		}


		return true;

	}



	/**
	 * 
	 */
	private boolean evaluateDataTypeSXY( final ArrayList tokenList )
	{

		int num = 0;
		if( tokenList.size()==2 || tokenList.size()==4 )
		{
			num = tokenList.size();
		}
		else if( tokenList.size()==3 )
		{
			num = 2;
		}
		else if( tokenList.size()==5 )
		{
			num = 4;
		}

		for( int ii=0; ii<num; ii++ )
		{
			String str = (String)tokenList.get(ii);
			try
			{
				Double d = Double.valueOf(str);
			}
			catch( NumberFormatException ex )
			{
				return false;
			}
		}

		return true;

	}



	/**
	 * 
	 */
	private boolean evaluateDataTypeSXYMultiple( final ArrayList tokenList )
	{

		for( int ii=0; ii<tokenList.size(); ii++ )
		{
			String str = (String)tokenList.get(ii);
			try
			{
				Double d = Double.valueOf(str);
			}
			catch( NumberFormatException ex )
			{
				return false;
			}
		}

		return true;

	}







	/**
	 * 
	 */
	private String mTempDataFileType = null;



	/**
	 * 
	 */
	private boolean readFile(
		final String pathName,
		final ArrayList infoList )
	{

		final Window owner = this.mXYDataTypeSelectionWizardDialogFromCLorDD.getOwner();

		ArrayList cList = new ArrayList();
		ArrayList tokenNumList = new ArrayList();
		if( this.getFileTypeCandidateList( owner, pathName, cList, tokenNumList ) == false )
		{
			return false;
		}

		if( cList.size() == 0 )
		{
			System.out.println("データファイルが不正です。");
			return false;
		}


		String fileType = null;

		// set candidate data-type to the dialog
		if( this.mXYDataTypeSelectionWizardDialogFromCLorDD.setEffectiveDataType(cList) == false )
		{
			return false;
		}


		// set the location of wizard dialog
//		Window owner = this.mXYDataTypeSelectionWizardDialogFromCLorDD.getOwner();
		final int ox = owner.getX();
		final int oy = owner.getY();
		this.mXYDataTypeSelectionWizardDialogFromCLorDD.setLocation( ox, oy );

	
		// show a modal dialog to choose data-type from candidates
		this.mXYDataTypeSelectionWizardDialogFromCLorDD.show();
//		owner.repaint();


		//
		// A modal dialog is shown.
		//

		// if cancel button is pressed, this flag is false
		if( this.mCarryOnWizardFlag == false )
		{
			return false;
		}
	
	
		// get selected file type
		fileType = this.mXYDataTypeSelectionWizardDialogFromCLorDD.getSelectedDataType();
		if( fileType == null )
		{
			return false;
		}


		// add information to the list
		infoList.add(fileType);


		// create an array for data-retention
		if( fileType.equals(SGDataTypeConstants.SXY_SAMPLING_DATA) )
		{
			// infoList にサンプリングレートの情報を追加する
			Double d = this.mXYDataTypeSelectionWizardDialogFromCLorDD.getSamplingRate();
			if( d==null )
			{
				return false;
			}
			infoList.add(d);
		}


		return true;

	}




	/**
	 * 
	 */
	private boolean readFile2(
		final String pathName,
		final ArrayList infoList )
	{

		// get selected file type
		final String fileType = this.mXYDataTypeSelectionWizardDialog.getSelectedDataType();
		if( fileType == null )
		{
			return false;
		}


		// add information to the list
		infoList.add(fileType);


		// create an array for data-retention
		if( fileType.equals(SGDataTypeConstants.SXY_SAMPLING_DATA) )
		{
			// infoList にサンプリングレートの情報を追加する
			Double d = this.mXYDataTypeSelectionWizardDialog.getSamplingRate();
			if( d==null )
			{
				return false;
			}
			infoList.add(d);
		}


		return true;

	}






	/**
	 * 
	 * @return
	 */
	private SGData createData( final String pathName, final ArrayList infoList )
	{
//System.out.println("<< createData >>");
//System.out.println(infoList);

		if( pathName==null || infoList==null )
		{
			return null;
		}

		if( infoList.size()==0 )
		{
			return null;
		}


		SGData data = null;

		final String dataType = (String)infoList.get(0);
		if( dataType.equals( SGDataTypeConstants.SXY_DATA ) )
		{
			data = this.createSXYData(pathName);
		}
		else if( dataType.equals( SGDataTypeConstants.VXY_DATA ) )
		{
			
		}
		else if( dataType.equals( SGDataTypeConstants.SXY_MULTIPLE_DATA ) )
		{
			data = this.createSXYMultipleData(pathName);
		}
		else if( dataType.equals( SGDataTypeConstants.SXY_SAMPLING_DATA ) )
		{
			if( infoList.size()<=1 )
			{
				return null;
			}

			// 第2引数にはサンプリング周波数
			final double rate = ((Double)infoList.get(1)).doubleValue();

			data = this.createSXYSamplingData(pathName,rate);
		}

//System.out.println("*** "+data);

		return data;
	}



	/**
	 * 
	 */
	private int getColumnNumber( final String pathName )
	{
		// 最初の1行を読み込んで情報を取得する
		int num = -1;
		try
		{
			FileInputStream fis = null;
			try
			{
				fis = new FileInputStream( pathName );
			}
			catch( FileNotFoundException ex )
			{
				Window owner = this.mXYDataTypeSelectionWizardDialog.getOwner();
				SGUtility.showFileNotFoundMessageDialog( owner );
				return num;
			}
			InputStreamReader ir = new InputStreamReader(fis);
			BufferedReader br = new BufferedReader(ir);
	
			String line = SGUtilityText.readLine(br);
			if( line==null )
			{
				return num;
			}

			// break the string into tokens
			final ArrayList tokenList = new ArrayList();
			SGUtilityText.tokenize( line, tokenList );
			num = tokenList.size();

			br.close();
			ir.close();
			fis.close();

		}
		catch( Exception ex )
		{
			ex.printStackTrace();
		}

		return num;
	}



	/**
	 * 
	 */
	private ArrayList[] createListArray( final String pathName, final int num )
	{

		// リストの配列を作成
		ArrayList[] listArray = new ArrayList[num];
		for( int ii=0; ii<listArray.length; ii++ )
		{
			listArray[ii] = new ArrayList();
		}

		try
		{

			FileInputStream fis = null;
			try
			{
				fis = new FileInputStream( pathName );
			}
			catch( FileNotFoundException ex )
			{
				Window owner = this.mXYDataTypeSelectionWizardDialog.getOwner();
				SGUtility.showFileNotFoundMessageDialog( owner );

				return null;
			}
			InputStreamReader ir = new InputStreamReader(fis);
			BufferedReader br = new BufferedReader(ir);
	
			String line = null;
			while(true)
			{
				line = SGUtilityText.readLine(br);
				if( line==null )
				{
					break;
				}
		
				// break the string into tokens
				final ArrayList tokenList = new ArrayList();
				SGUtilityText.tokenize( line, tokenList );
				if( tokenList.size() != num )
				{
					return null;
				}

				// array of the tokens
				final String[] array = new String[num];
				for( int ii=0; ii<num; ii++ )
				{
					String str = (String)tokenList.get(ii);
					listArray[ii].add( str );
				}
	
			}

			br.close();
			ir.close();
			fis.close();

		}
		catch( IOException ex )
		{
			ex.printStackTrace();
			return null;
		}


		return listArray;
	}




	/**
	 * 
	 * @return
	 */
	private SGSXYData createSXYData( final String pathName )
	{
//System.out.println("<< createSXYData >>");

		// ファイルからデータ列数を取得
		final int num = this.getColumnNumber(pathName);
		if( num==-1 )
		{
			return null;
		}
		if( num<2 )
		{
			return null;
		}


		// リストの配列を作成
		ArrayList[] listArray = this.createListArray( pathName, num );
		if( listArray==null )
		{
			return null;
		}


		// check
		final int dataLength = listArray[0].size();
		for( int ii=1; ii<listArray.length; ii++ )
		{
			if( listArray[ii].size()!=dataLength )
			{
				return null;
			}
		}


		//
		// create data object
		//

		SGSXYData data = null;

		try
		{
			double[] xArray = new double[dataLength];
			double[] yArray = new double[dataLength];
			for( int ii=0; ii<dataLength; ii++ )
			{
				xArray[ii] = Double.valueOf( ((String)listArray[0].get(ii)) ).doubleValue();
				yArray[ii] = Double.valueOf( ((String)listArray[1].get(ii)) ).doubleValue();
			}

			double[] lArray = null;
			double[] uArray = null;
			String[] strArray = null;
			switch( num )
			{
				case 2 :
				{
					break;
				}
				case 4 :
				{
					lArray = new double[dataLength];
					uArray = new double[dataLength];
					for( int ii=0; ii<dataLength; ii++ )
					{
						lArray[ii] = Double.valueOf( ((String)listArray[2].get(ii)) ).doubleValue();
						uArray[ii] = Double.valueOf( ((String)listArray[3].get(ii)) ).doubleValue();
					}
					break;
				}
				case 3 :
				{
					strArray = new String[dataLength];
					for( int ii=0; ii<dataLength; ii++ )
					{
						strArray[ii] = (String)listArray[2].get(ii);
					}
					break;
				}
				case 5 :
				{
					lArray = new double[dataLength];
					uArray = new double[dataLength];
					strArray = new String[dataLength];
					for( int ii=0; ii<dataLength; ii++ )
					{
						lArray[ii] = Double.valueOf( ((String)listArray[2].get(ii)) ).doubleValue();
						uArray[ii] = Double.valueOf( ((String)listArray[3].get(ii)) ).doubleValue();
						strArray[ii] = (String)listArray[4].get(ii);
					}
					break;
				}
			
			}

			data = new SGSXYData( xArray, yArray, lArray, uArray, strArray );

		}
		catch( NumberFormatException ex )
		{
			ex.printStackTrace();
		}


		return data;

	}




	/**
	 * 
	 * @return
	 */
	private SGSXYMultipleData createSXYMultipleData( final String pathName )
	{

		// ファイルからデータ列数を取得
		final int num = this.getColumnNumber(pathName);
		if( num==-1 )
		{
			return null;
		}
		if( num < 2 )
		{
			return null;
		}


		// リストの配列を作成
		ArrayList[] listArray = this.createListArray( pathName, num );
		if( listArray==null )
		{
			return null;
		}


		// check
		final int dataLength = listArray[0].size();
		for( int ii=1; ii<listArray.length; ii++ )
		{
			if( listArray[ii].size()!=dataLength )
			{
				return null;
			}
		}



		//
		// create data object
		//

		SGSXYMultipleData data = null;

		try
		{
			double[] xArray = new double[dataLength];
			for( int ii=0; ii<dataLength; ii++ )
			{
				xArray[ii] = Double.valueOf( (String)listArray[0].get(ii) ).doubleValue();
			}

			double[][] yArray = new double[num-1][];
			for( int ii=0; ii<num-1; ii++ )
			{
				yArray[ii] = new double[dataLength];
				for( int jj=0; jj<dataLength; jj++ )
				{
					yArray[ii][jj] = Double.valueOf( (String)listArray[ii+1].get(jj) ).doubleValue();
				}
			}

			data = new SGSXYMultipleData( xArray, yArray );

		}
		catch( NumberFormatException ex )
		{
			ex.printStackTrace();
		}

		return data;

	}



	/**
	 * 
	 * @return
	 */
	private SGSXYMultipleData createSXYSamplingData(
		final String pathName, final double sRate )
	{
//System.out.println("### createSXYSamplingData ###");


		// ファイルからデータ列数を取得
		final int num = this.getColumnNumber(pathName);
		if( num==-1 )
		{
			return null;
		}
		if( num < 1 )
		{
			return null;
		}


		// リストの配列を作成
		ArrayList[] listArray = this.createListArray( pathName, num );
		if( listArray==null )
		{
			return null;
		}


		// check
		final int dataLength = listArray[0].size();
		for( int ii=1; ii<listArray.length; ii++ )
		{
			if( listArray[ii].size()!=dataLength )
			{
				return null;
			}
		}



		//
		// create data object
		//

		SGSXYSamplingData data = null;

		try
		{
			double[][] yArray = new double[num][];
			for( int ii=0; ii<num; ii++ )
			{
				yArray[ii] = new double[dataLength];
				for( int jj=0; jj<dataLength; jj++ )
				{
					yArray[ii][jj] = Double.valueOf( (String)listArray[ii].get(jj) ).doubleValue();
				}
			}

			data = new SGSXYSamplingData( sRate, yArray );
			
		}
		catch( NumberFormatException ex )
		{
			ex.printStackTrace();
		}


		return data;

	}





	/**
	 * 
	 * @return
	 */
	private SGDrawingWindow createWindow()
	{
//System.out.println("*** createWindow() ***");

		final int id = this.getCurrentWindowID();

		SGDrawingWindow wnd = this.createWindow(id);

		return wnd;

	}



	/**
	 * 
	 */
	private SGDrawingWindow createWindow( int id )
	{

		SGDrawingWindow wnd = new SGDrawingWindow();


		this.addWindow(id,wnd);


		this.initWindow(wnd);


		return wnd;

	}



	/**
	 * 
	 */
	private boolean initWindow( final SGDrawingWindow wnd )
	{

		// アクションリスナに追加
		wnd.addActionListener(this);



		// 終了処理を追加
		wnd.addWindowListener(this);
		wnd.setDefaultCloseOperation( JFrame.DISPOSE_ON_CLOSE );


		// ドロップターゲットの作成
		DropTarget target = new DropTarget(
			wnd,
			DnDConstants.ACTION_COPY_OR_MOVE,
			this,
			true
		);
		wnd.setDropTarget(target);


		// set the location of the window
		{
			wnd.setLocation(100,100);
		}


		// initialize
		if( wnd.init() == false )
		{
			return false;
		}


		return true;
	}






	/**
	 * 
	 */
	private boolean addWindow( final SGDrawingWindow wnd )
	{
//System.out.println("addWindow");

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

		boolean flag = this.addWindow( this.getCurrentWindowID(), wnd );
		return flag;
	}



	/**
	 * 
	 */
	private int getCurrentWindowID()
	{
		int id;
		if( this.mWndMap.size()==0 )
		{
			id = 1;
		}
		else
		{
			id = ((Integer)this.mWndMap.lastKey()).intValue() + 1;
		}
		return id;
	}



	/**
	 * 
	 */
	private boolean addWindow( final int id, final SGDrawingWindow wnd )
	{
//System.out.println("addWindow:"+id);

		wnd.setID( id );

		String title = "Window:" + id;
		wnd.setTitle(title);

		this.mWndMap.put( new Integer(id), wnd );

		return true;
	}




	/**
	 * 
	 */
	private int createWindowFromPropertyFile(
		final SGDrawingWindow wnd,
		final InputStream is,
		final InputStreamReader isw,
		final BufferedReader br )
			throws IOException, ClassNotFoundException,
				InstantiationException, IllegalAccessException
	{

		// title
		String line = null;
		if( ( line = SGUtilityText.readLine(br) ) == null )
		{
			return SGConstants.PROPERTY_FILE_INCORRECT;
		}
		if( line.equals( SGDrawingWindow.WINDOW_TITLE ) == false )
		{
			return SGConstants.PROPERTY_FILE_INCORRECT;
		}


		float unit = this.mRulerUnit;


		// width of the paper
		if( (line=SGUtilityText.readLine(br)) == null )
		{
			return SGConstants.PROPERTY_FILE_INCORRECT;
		}
		Double dWidth = SGUtilityText.getDoublePropertyFromLine( line, SGDrawingWindow.KEY_PAPER_WIDTH );
		if( dWidth == null )
		{
			return SGConstants.PROPERTY_FILE_INCORRECT;
		}
		float paperWidth = dWidth.floatValue()/unit;
//System.out.println(paperWidth);


		// height of the paper
		if( (line=SGUtilityText.readLine(br)) == null )
		{
			return SGConstants.PROPERTY_FILE_INCORRECT;
		}
		Double dHeight = SGUtilityText.getDoublePropertyFromLine( line, SGDrawingWindow.KEY_PAPER_HEIGHT );
		if( dHeight == null )
		{
			return SGConstants.PROPERTY_FILE_INCORRECT;
		}
		float paperHeight = dHeight.floatValue()/unit;
//System.out.println(paperHeight);


		// grid interval
		if( (line=SGUtilityText.readLine(br)) == null )
		{
			return SGConstants.PROPERTY_FILE_INCORRECT;
		}
		Double dGridInterval = SGUtilityText.getDoublePropertyFromLine( line, SGDrawingWindow.KEY_GRID_INTERVAL );
		if( dGridInterval == null )
		{
			return SGConstants.PROPERTY_FILE_INCORRECT;
		}
		float gridInterval = dGridInterval.floatValue()/unit;
//System.out.println(gridInterval);


		// grid line width
		if( (line=SGUtilityText.readLine(br)) == null )
		{
			return SGConstants.PROPERTY_FILE_INCORRECT;
		}
		Double dGridLineWidth = SGUtilityText.getDoublePropertyFromLine( line, SGDrawingWindow.KEY_GRID_LINE_WIDTH );
		if( dGridLineWidth == null )
		{
			return SGConstants.PROPERTY_FILE_INCORRECT;
		}
		float gridLineWidth = dGridLineWidth.floatValue();


		// background color
		if( (line=SGUtilityText.readLine(br)) == null )
		{
			return SGConstants.PROPERTY_FILE_INCORRECT;
		}
		Color bgColor = SGUtilityText.getColorPropertyFromLine( line, SGDrawingWindow.KEY_BACKGROUND_COLOR );
		if( bgColor == null )
		{
			return SGConstants.PROPERTY_FILE_INCORRECT;
		}


		// grid line color
		if( (line=SGUtilityText.readLine(br)) == null )
		{
			return SGConstants.PROPERTY_FILE_INCORRECT;
		}
		Color gridColor = SGUtilityText.getColorPropertyFromLine( line, SGDrawingWindow.KEY_GRID_COLOR );
		if( gridColor == null )
		{
			return SGConstants.PROPERTY_FILE_INCORRECT;
		}
//System.out.println(gridColor);


		// create a new window
		wnd.setPaperSize(
			paperWidth, paperHeight
		);
		wnd.setBackgroundColor( bgColor );
		wnd.setGridInterval( gridInterval );
		wnd.setGridLineWidth( gridLineWidth );
		wnd.setGridLineColor( gridColor );



		// add history
		wnd.initPropertiesHistory();


		// create figure objects in a window
//System.out.println("Start: createFiguresFromPropertyFile");
		int ret = this.createFiguresFromPropertyFile( br, wnd );
		if( ret==SGConstants.DATA_NUMBER_SHORTAGE
			|| ret==SGConstants.PROPERTY_FILE_INCORRECT
			|| ret==SGConstants.FILE_OPEN_FAILURE )
		{
			return ret;
		}
//System.out.println("End: createFiguresFromPropertyFile");


// この時点で、１つのウインドウ内のオブジェクトは全て作成されている。



System.out.println("データファイル名の残り："+this.mDataFileNameList.size());


		if( this.mDataFileNameList.size() != 0 )
		{
			ret = SGConstants.DATA_NUMBER_EXCESS;
//System.out.println("データ数が過剰です。");
		}
		else
		{
			ret = SGConstants.SUCCESSFUL_COMPLETION;
//System.out.println("正常終了");
		}


		return ret;

	}



	/**
	 * 
	 */
	public SGDrawingWindow createWindowFromPropertyFile( final String absolutePathName )
		throws IOException, ClassNotFoundException,
			InstantiationException, IllegalAccessException
	{

		// open the property file
		InputStream is = null;
		try
		{
			is = new FileInputStream( absolutePathName );
		}
		catch( FileNotFoundException ex )
		{
			Window owner = this.mPropertyFileChooserWizardDilaog.getOwner();
			SGUtility.showFileNotFoundMessageDialog( owner );
			return null;
		}

		InputStreamReader isw = new InputStreamReader(is);
		BufferedReader br = new BufferedReader(isw);


		// create a window instance
		SGDrawingWindow wnd = this.createWindow();


		// set the property of the created window from property file
//System.out.println("Start: createWindowFromPropertyFile");

		int ret = this.createWindowFromPropertyFile(wnd,is,isw,br);

//System.out.println("End: createWindowFromPropertyFile");


		String msg = null;
		if( ret == SGConstants.SUCCESSFUL_COMPLETION )
		{
			msg = MSG_SUCCESSFUL_COMPLETION;
		}
		else if( ret == SGConstants.DATA_NUMBER_SHORTAGE )
		{
			msg = ERRMSG_DATA_NUMBER_SHORTAGE;
		}
		else if( ret == SGConstants.DATA_NUMBER_EXCESS )
		{
			msg = ERRMSG_DATA_NUMBER_EXCESS;
		}
		else if( ret == SGConstants.FILE_OPEN_FAILURE )
		{
			msg = ERRMSG_FILE_OPEN_FAILURE;
		}
		else if( ret == SGConstants.PROPERTY_FILE_INCORRECT )
		{
			msg = ERRMSG_PROPERTY_FILE_INCORRECT;
		}
		else
		{
			throw new Error();
		}

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


		// show the window
		wnd.show();


		// show the message dialog
		if( msg!=MSG_SUCCESSFUL_COMPLETION )
		{
			SGUtility.showMessageDialog(
				wnd, msg, PROPERTY_FILE_READ_MSG_DIALOG_TITLE,
				JOptionPane.ERROR_MESSAGE
			);
		}
//		wnd.repaint();


		if( ret==SGConstants.PROPERTY_FILE_INCORRECT )
		{
			wnd.hide();
			this.removeWindow(wnd);
		}


		br.close();
		isw.close();
		is.close();


		return wnd;

	}



	/**
	 * １つのウインドウに属するフィギュア群を作成する
	 */
	private int createFiguresFromPropertyFile(
		final BufferedReader br,
		final SGDrawingWindow wnd )
		throws IOException, ClassNotFoundException,
			InstantiationException, IllegalAccessException
	{

		String line = null;

		final float unit = SGConstants.CM_POINT_RATIO;


		// loop for SGFigure
		br.mark(256);
		while(true)
		{

			//
			// title
			//

			if( (line=SGUtilityText.readLine(br)) == null )
			{
//System.out.println("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
				return SGConstants.END_OF_PROPERTY_FILE;
			}
//System.out.println(line);
			if( line.equals( SGFigure.PF_FIGURE_TITLE ) == false )
			{
				br.reset();
				break;
			}


			//
			// the name of instance
			//

			if( (line=SGUtilityText.readLine(br)) == null )
			{
				return SGConstants.PROPERTY_FILE_INCORRECT;
			}
			String cName = SGUtilityText.getPropertyFromLine( line, SGFigure.PF_CLASS_NAME );
			if( cName == null )
			{
				return SGConstants.PROPERTY_FILE_INCORRECT;
			}
			String className;
			if( cName.equals("SXY") )
			{
				className = SGSXYFigure.class.getName();
			}
			else if( cName.equals("VXY") )
			{
				className = SGVXYFigure.class.getName();
			}
			else
			{
				return SGConstants.PROPERTY_FILE_INCORRECT;
			}
//System.out.println(className);



			//
			// create a figure
			//

			Class cl = Class.forName( className );
			SGFigure figure = (SGFigure)cl.newInstance();
			figure.setWindow( wnd );
			final int figureID = wnd.getCurrentFigureId();
			figure.setID(figureID);
//			figure.setToolTipText( new Integer(figureID).toString() );



			//
			// bounds of the figure
			//

			// x
			while( true )
			{
				line = br.readLine();
				if( line == null )
				{
					return SGConstants.PROPERTY_FILE_INCORRECT;
				}

				if( line.length()!=0 )
				{
					break;
				}
			}
			Double dX = SGUtilityText.getDoublePropertyFromLine( line, SGFigure.PF_FIGURE_X_IN_CLIENT );
			if( dX == null )
			{
				return SGConstants.PROPERTY_FILE_INCORRECT;
			}
			float x = dX.floatValue()/unit;
//System.out.println(x);


			// y
			while( true )
			{
				line = br.readLine();
				if( line == null )
				{
					return SGConstants.PROPERTY_FILE_INCORRECT;
				}

				if( line.length()!=0 )
				{
					break;
				}
			}
			Double dY = SGUtilityText.getDoublePropertyFromLine( line, SGFigure.PF_FIGURE_Y_IN_CLIENT );
			if( dY == null )
			{
				return SGConstants.PROPERTY_FILE_INCORRECT;
			}
			float y = dY.floatValue()/unit;
//System.out.println(y);


			// width
			while( true )
			{
				line = br.readLine();
				if( line == null )
				{
					return SGConstants.PROPERTY_FILE_INCORRECT;
				}

				if( line.length()!=0 )
				{
					break;
				}
			}
			Double dW = SGUtilityText.getDoublePropertyFromLine( line, SGFigure.PF_WIDTH );
			if( dW == null )
			{
				return SGConstants.PROPERTY_FILE_INCORRECT;
			}
			float w = dW.floatValue()/unit;
//System.out.println(w);


			// height
			while( true )
			{
				line = br.readLine();
				if( line == null )
				{
					return SGConstants.PROPERTY_FILE_INCORRECT;
				}

				if( line.length()!=0 )
				{
					break;
				}
			}
			Double dH = SGUtilityText.getDoublePropertyFromLine( line, SGFigure.PF_HEIGHT );
			if( dH == null )
			{
				return SGConstants.PROPERTY_FILE_INCORRECT;
			}
			float h = dH.floatValue()/unit;
//System.out.println(h);

			figure.setGraphAreaLocation( x, y );
			figure.setGraphAreaSize( w, h );




			//
			// space
			//

			// line and numbers
			while( true )
			{
				line = br.readLine();
				if( line == null )
				{
					return SGConstants.PROPERTY_FILE_INCORRECT;
				}

				if( line.length()!=0 )
				{
					break;
				}
			}
			Double dSpaceLN = SGUtilityText.getDoublePropertyFromLine( line, SGFigure.PF_SPACE_AXIS_LINE_AND_NUMBER );
			if( dSpaceLN == null )
			{
				return SGConstants.PROPERTY_FILE_INCORRECT;
			}
			float spaceLN = dSpaceLN.floatValue()/unit;
//System.out.println(spaceLN);


			// numbers and title
			while( true )
			{
				line = br.readLine();
				if( line == null )
				{
					return SGConstants.PROPERTY_FILE_INCORRECT;
				}

				if( line.length()!=0 )
				{
					break;
				}
			}
			Double dSpaceNT = SGUtilityText.getDoublePropertyFromLine( line, SGFigure.PF_SPACE_NUMBER_AND_TITLE );
			if( dSpaceNT == null )
			{
				return SGConstants.PROPERTY_FILE_INCORRECT;
			}
			float spaceNT = dSpaceNT.floatValue()/unit;
//System.out.println(spaceNT);


			//
			// Background Color
			//
			while( true )
			{
				line = br.readLine();
				if( line == null )
				{
					return SGConstants.PROPERTY_FILE_INCORRECT;
				}

				if( line.length()!=0 )
				{
					break;
				}
			}
			Color bgColor = SGUtilityText.getColorPropertyFromLine( line, SGFigure.PF_BACKGROUND_COLOR );
			if( bgColor == null )
			{
				return SGConstants.PROPERTY_FILE_INCORRECT;
			}
//System.out.println(bgColor);
			figure.setBackgroundColor( bgColor );


			//
			// Transparency
			//
			while( true )
			{
				line = br.readLine();
				if( line == null )
				{
					return SGConstants.PROPERTY_FILE_INCORRECT;
				}

				if( line.length()!=0 )
				{
					break;
				}
			}
			Boolean bTransparent = SGUtilityText.getBooleanPropertyFromLine( line, SGFigure.PF_TRANSPARENCY );
			if( bTransparent == null )
			{
				return SGConstants.PROPERTY_FILE_INCORRECT;
			}
			boolean transparent = bTransparent.booleanValue();
//System.out.println(transparent);
			figure.setTransparent( transparent );



			//
			// Legend Visible
			//
			while( true )
			{
				line = br.readLine();
				if( line == null )
				{
					return SGConstants.PROPERTY_FILE_INCORRECT;
				}

				if( line.length()!=0 )
				{
					break;
				}
			}
			Boolean bLegendVisible = SGUtilityText.getBooleanPropertyFromLine( line, SGFigure.PF_LEGEND_VISIBLE );
			if( bLegendVisible == null )
			{
				return SGConstants.PROPERTY_FILE_INCORRECT;
			}
			boolean legendVisible = bLegendVisible.booleanValue();
//System.out.println(legendVisible);




			//
			// create SGIFigureElement objects
			//
//System.out.println("create SGIFigureElement objects");

			int ret;

			// SGIAxisElement
			ret = this.createAxisElementFromPropertyFile(figure,br);
			if( ret==SGConstants.PROPERTY_FILE_INCORRECT || ret==SGConstants.END_OF_PROPERTY_FILE )
			{
//System.out.println("!!!!!!!!!!!!!!!!!");
				return ret;
			}
			SGIAxisElement axisElement = figure.getAxisElement();
			axisElement.readProperty(br);

//System.out.println("<< axis_old >>");
//System.out.println(axisElement);
//System.out.println();


			// set the layout
			axisElement.setGraphAreaRect(0.0f,0.0f,w,h);
			figure.setSpaceAxisLineAndNumber( spaceLN );
			figure.setSpaceNumberAndTitle( spaceNT );

//System.out.println("<< axis >>");
//System.out.println(axisElement);
//System.out.println();


//System.out.println("gRect:"+gRect);
//System.out.println();



			// SGIGraphElement
			ret = this.createGraphElementFromPropertyFile(figure,br);
			if( ret==SGConstants.PROPERTY_FILE_INCORRECT || ret==SGConstants.END_OF_PROPERTY_FILE )
			{
				return ret;
			}
//System.out.println("abc");
			SGIGraphElement graphElement = figure.getGraphElement();
			graphElement.readProperty(br);

//System.out.println("<< graph >>");
//System.out.println(graphElement);
//System.out.println();


			// SGILegendElement
			ret = this.createLegendElementFromPropertyFile(figure,br);
			if( ret==SGConstants.PROPERTY_FILE_INCORRECT || ret==SGConstants.END_OF_PROPERTY_FILE )
			{
//System.out.println("def");
				return ret;
			}
			SGILegendElement legendElement = figure.getLegendElement();
			legendElement.readProperty(br);

			//
			figure.setLegendVisible( legendVisible );


//System.out.println("<< legend >>");
//System.out.println(legendElement);
//System.out.println();


			// SGIStringElement
			ret = this.createStringElementFromPropertyFile(figure,br);
			if( ret==SGConstants.PROPERTY_FILE_INCORRECT || ret==SGConstants.END_OF_PROPERTY_FILE )
			{
//System.out.println("ghi");
				return ret;
			}
			SGIStringElement stringElement = figure.getStringElement();
			stringElement.readProperty(br);

//System.out.println("<< string >>");
//System.out.println(stringElement);
//System.out.println();


			//
			graphElement.setAxisElement( axisElement );
			legendElement.setGraphElement( graphElement );


			// add history
			figure.initPropertiesHistory();
			SGIFigureElement[] iArray = figure.getIFigureElementArray();
			for( int ii=0; ii<iArray.length; ii++ )
			{
				iArray[ii].initPropertiesHistory();
			}
			


			// add the figure to the window
			int id = wnd.getCurrentFigureId();
			wnd.addFigure( id, figure );




			//
			// datas on figure
			//

//System.out.println("Start: createDataObjectsFromPropertyFile");

			ret = this.createDataObjectsFromPropertyFile( br, figure );
			if( ret==SGConstants.PROPERTY_FILE_INCORRECT
				|| ret==SGConstants.FILE_OPEN_FAILURE
				|| ret==SGConstants.DATA_NUMBER_SHORTAGE )
			{
				return ret;
			}

//System.out.println("End: createDataObjectsFromPropertyFile");


			//
			figure.notifyFigureElement( figure.getAxisElement() );
			figure.notifyFigureElement( figure.getGraphElement() );


			//
			SGIFigureElement[] array = figure.getIFigureElementArray();
			for( int ii=0; ii<array.length; ii++ )
			{
				array[ii].chkBoundsVisible();
			}
			
			
			// 初期状態を履歴に追加
			for( int ii=0; ii<array.length; ii++ )
			{
				array[ii].initPropertiesHistory();
			}


			br.mark(256);

		}


		return SGConstants.SUCCESSFUL_COMPLETION;

	}




	/**
	 *
	 */
	public boolean createFigureElementFromPropertyFile(
		final SGFigure figure,
		final BufferedReader br )
			throws IOException, ClassNotFoundException,
			InstantiationException, IllegalAccessException
	{

/*
System.out.println("before");
System.out.println(this.mAxisElement);
System.out.println(this.mGraphElement);
System.out.println(this.mLegendElement);
System.out.println(this.mStringElement);
System.out.println();
*/

		int ret;

		ret = this.createAxisElementFromPropertyFile( figure, br );
		if( ret==SGConstants.PROPERTY_FILE_INCORRECT )
		{
			return false;
		}
		SGIAxisElement axisElement = figure.getAxisElement();


		ret = this.createGraphElementFromPropertyFile( figure, br );
		if( ret==SGConstants.PROPERTY_FILE_INCORRECT )
		{
			return false;
		}
		SGIGraphElement graphElement = figure.getGraphElement();
		graphElement.setAxisElement( axisElement );


		ret = this.createLegendElementFromPropertyFile( figure, br );
		if( ret==SGConstants.PROPERTY_FILE_INCORRECT )
		{
			return false;
		}
		SGILegendElement legendElement = figure.getLegendElement();
		legendElement.setGraphElement( graphElement );


		ret = this.createStringElementFromPropertyFile( figure, br );
		if( ret==SGConstants.PROPERTY_FILE_INCORRECT )
		{
			return false;
		}
		SGIStringElement stringElement = figure.getStringElement();

/*
		axisElement.addActionListener(figure);
		graphElement.addActionListener(figure);
		legendElement.addActionListener(figure);
		stringElement.addActionListener(figure);
*/

/*
System.out.println("after");
System.out.println(this.mAxisElement);
System.out.println(this.mGraphElement);
System.out.println(this.mLegendElement);
System.out.println(this.mStringElement);
System.out.println();
*/

		return true;
	}




	/**
	 * 
	 * @return
	 */
	public int createStringElementFromPropertyFile(
		final SGFigure figure,
		final BufferedReader br )
		throws IOException, ClassNotFoundException,
			InstantiationException, IllegalAccessException
	{

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

		String line = null;

		// タイトルの文字列が無ければ終了
		if( ( line = SGUtilityText.readLine(br) ) == null )
		{
//System.out.println("111");
			return SGConstants.PROPERTY_FILE_INCORRECT;
		}
		if( line.equals( SGIStringElement.PF_STRING_TITLE ) == false )
		{
//System.out.println("*"+line+"*");
//System.out.println(SGIStringElement.PF_STRING_TITLE);
//System.out.println("222");
			return SGConstants.PROPERTY_FILE_INCORRECT;
		}


		// create a SGIStringElement object
		final Class cl = this.mClassOfStringElement;
		final Object obj = cl.newInstance();

		final JComponent com = (JComponent)obj;
		com.setBounds( 0, 0, figure.getWidth(), figure.getHeight() );
		com.setVisible(true);
		com.setOpaque(false);
		figure.add(com);
		figure.setLayer(com,SGFigure.LAYER_STRING);

		final SGIStringElement stringElement = (SGIStringElement)obj;
		figure.setStringElement(stringElement);
		stringElement.addActionListener(figure);
		stringElement.setDialogOwner( figure.getWindow() );
		

		return SGConstants.SUCCESSFUL_COMPLETION;

	}


	
	/**
	 * 
	 * @return
	 */
	public int createAxisElementFromPropertyFile(
		final SGFigure figure,
		final BufferedReader br )
		throws IOException, ClassNotFoundException,
			InstantiationException, IllegalAccessException
	{

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

		String line = null;

		// タイトルの文字列が無ければ終了
		if( ( line = SGUtilityText.readLine(br) ) == null )
		{
			return SGConstants.PROPERTY_FILE_INCORRECT;
		}
		if( line.equals( SGIAxisElement.PF_AXIS_TITLE ) == false )
		{
			return SGConstants.PROPERTY_FILE_INCORRECT;
		}
//System.out.println(line);



		// create a SGIAxisElement object
		Class cl = this.mClassOfAxisElement;
		Object obj = cl.newInstance();
	
	
		final JComponent com = (JComponent)obj;
		com.setBounds( 0, 0, figure.getWidth(), figure.getHeight() );
		com.setVisible(true);
		com.setOpaque(false);
		figure.add(com);
		figure.setLayer(com,SGFigure.LAYER_AXIS);
	
		final SGIAxisElement axisElement = (SGIAxisElement)obj;
		figure.setAxisElement(axisElement);
		axisElement.addActionListener(figure);
		axisElement.setDialogOwner( figure.getWindow() );


		return SGConstants.SUCCESSFUL_COMPLETION;

	}




	/**
	 * 
	 * @return
	 */
	public int createGraphElementFromPropertyFile(
		final SGFigure figure,
		final BufferedReader br )
		throws IOException, ClassNotFoundException,
			InstantiationException, IllegalAccessException
	{

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

		String line = null;

/*
		// タイトルの文字列が無ければ終了
		if( ( line = SGUtilityForPropertyFile.readLine(br) ) == null )
		{
			return SGConstants.PROPERTY_FILE_INCORRECT;
		}
		if( line.equals( SGIGraphElement.PF_GRAPH_TITLE ) == false )
		{
			return SGConstants.PROPERTY_FILE_INCORRECT;
		}
*/

		// create a SGIGraphElement object
		final Class cl;
		if( figure instanceof SGSXYFigure )
		{
			cl = this.mClassOfSXYGraphElement;
		}
		else if( figure instanceof SGVXYFigure )
		{
			cl = this.mClassOfVXYGraphElement;
		}
		else
		{
			throw new Error();
		}

		final Object obj = cl.newInstance();
			
		final JComponent com = (JComponent)obj;
		com.setBounds( 0, 0, figure.getWidth(), figure.getHeight() );
		com.setVisible(true);
		com.setOpaque(false);
		figure.add(com);
		figure.setLayer(com,SGFigure.LAYER_GRAPH);
			
		final SGIGraphElement graphElement = (SGIGraphElement)obj;
		figure.setGraphElement(graphElement);
		graphElement.addActionListener(figure);
		graphElement.setDialogOwner( figure.getWindow() );


		return SGConstants.SUCCESSFUL_COMPLETION;

	}



	/**
	 * 
	 * @return
	 */
	public int createLegendElementFromPropertyFile(
		final SGFigure figure,
		final BufferedReader br )
		throws IOException, ClassNotFoundException,
			InstantiationException, IllegalAccessException
	{

		String line = null;

		// タイトルの文字列が無ければ終了
		if( ( line = SGUtilityText.readLine(br) ) == null )
		{
			return SGConstants.PROPERTY_FILE_INCORRECT;
		}
		if( line.equals( SGILegendElement.PF_LEGEND_TITLE ) == false )
		{
			return SGConstants.PROPERTY_FILE_INCORRECT;
		}
		

		// create a SGILegendElement
		final Class cl = this.mClassOfLegendElement;
		final Object obj = cl.newInstance();
					
		final JComponent com = (JComponent)obj;
		com.setBounds( 0, 0, figure.getWidth(), figure.getHeight() );
		com.setVisible(true);
		com.setOpaque(false);
		figure.add(com);
		figure.setLayer(com,SGFigure.LAYER_LEGEND);
					
		final SGILegendElement legendElement = (SGILegendElement)obj;
		figure.setLegendElement(legendElement);
		legendElement.addActionListener(figure);
		legendElement.setDialogOwner( figure.getWindow() );
		

		return SGConstants.SUCCESSFUL_COMPLETION;

	}






	/**
	 * データオブジェクトを作成
	 */
	private int createDataObjectsFromPropertyFile(
		final BufferedReader br,
		final SGFigure figure )
		throws IOException, ClassNotFoundException,
			InstantiationException, IllegalAccessException
	{

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

		String line = null;

		// SGDataオブジェクトに関してループ
		while( true )
		{

			// "[Data]"の文字列が無ければ終了
			if( ( line = SGUtilityText.readLine(br) ) == null )
			{
				return SGConstants.END_OF_PROPERTY_FILE;
			}
//System.out.println(line);
			if( line.equals( SGIGraphElement.PF_DATA_TITLE ) == false )
			{
				br.reset();
				break;
			}


			ArrayList infoList = new ArrayList();

			// the class name
			if( ( line = SGUtilityText.readLine(br) ) == null )
			{
				return SGConstants.PROPERTY_FILE_INCORRECT;
			}

			String dataType = SGUtilityText.getPropertyFromLine(line,SGIGraphElement.PF_CLASS_NAME);
			if( dataType == null )
			{
				return SGConstants.PROPERTY_FILE_INCORRECT;
			}
			infoList.add( dataType );

//System.out.println(infoList);

			String className = null;
			if( dataType.equals(SGDataTypeConstants.SXY_DATA) )
			{
				className = SGSXYData.class.getName();
			}
			else if( dataType.equals(SGDataTypeConstants.VXY_DATA) )
			{
				className = SGVXYData.class.getName();
			}
			else if( dataType.equals(SGDataTypeConstants.SXY_MULTIPLE_DATA) )
			{
				className = SGSXYMultipleData.class.getName();

/*
				if( ( line = SGUtilityText.readLine(br) ) == null )
				{
					return SGConstants.DATA_TYPE_INCORRECT;
				}
				Integer multi = SGUtilityText.getIntegerPropertyFromLine( line, SGIGraphElement.PF_MULTIPLICITY );
				if( multi == null )
				{
					return SGConstants.PROPERTY_FILE_INCORRECT;
				}
*/			}
			else if( dataType.equals(SGDataTypeConstants.SXY_SAMPLING_DATA) )
			{
				className = SGSXYSamplingData.class.getName();


/*				if( ( line = SGUtilityText.readLine(br) ) == null )
				{
					return SGConstants.DATA_TYPE_INCORRECT;
				}
				Integer multi = SGUtilityText.getIntegerPropertyFromLine( line, SGIGraphElement.PF_MULTIPLICITY );
				if( multi == null )
				{
					return SGConstants.PROPERTY_FILE_INCORRECT;
				}
*/
				if( ( line = SGUtilityText.readLine(br) ) == null )
				{
					return SGConstants.DATA_TYPE_INCORRECT;
				}
				Double d = SGUtilityText.getDoublePropertyFromLine( line, SGIGraphElement.PF_SAMPLING_RATE );
				if( d == null )
				{
					return SGConstants.DATA_TYPE_INCORRECT;
				}

				infoList.add(d);

			}
			else
			{
				return SGConstants.DATA_TYPE_INCORRECT;
			}


			// create a new SGData object
			Class cl = Class.forName(className);
			SGData data = (SGData)cl.newInstance();

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

			//
//System.out.println(this.mDataFileNameList);
			if( this.mDataFileNameList.size() == 0 )
			{
				return SGConstants.DATA_NUMBER_SHORTAGE;
			}


			String fileName = (String)this.mDataFileNameList.remove(0);
			SGData data_ = this.createData( fileName, infoList );
			if( data_ == null )
			{
//System.out.println("@@@@@@@@@@@@@@@");
				System.out.println("データの構築に失敗しました。");
				return SGConstants.FILE_OPEN_FAILURE;
			}
//System.out.println(data+"  "+data_);
			boolean dFlag = data.setData(data_);
			if( !dFlag )
			{
				return SGConstants.DATA_TYPE_INCORRECT;
			}


			//
			boolean flag = figure.createDataObjectFromPropertyFile( br, data );
			if( !flag )
			{
				return SGConstants.PROPERTY_FILE_INCORRECT;
			}

			br.mark(256);

		}


//System.out.println(figure.getAxisElement().getDataList());
//System.out.println(figure.getGraphElement().getDataList());
//System.out.println(figure.getLegendElement().getDataList());
//System.out.println(figure.getStringElement().getDataList());
//System.out.println();


		return SGConstants.SUCCESSFUL_COMPLETION;

	}






	/**
	 * create a window using default values
	 */
	public boolean createNewWindow()
	{
//System.out.println("<< createNewWindow >>");

		final SGDrawingWindow wnd = this.createWindow();
		if( wnd==null )
		{
			return false;
		}

		// show the window
		wnd.show();

		return true;
	}



	/**
	 * 
	 */
	private boolean fromWindow( final ActionEvent e )
	{

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

		SGDrawingWindow wnd = (SGDrawingWindow)source;

		if( command.equals( SGDrawingWindow.NOTIFY_OPEN_WINDOW ) )
		{
			this.createNewWindow();
		}
		else if( command.equals( SGDrawingWindow.NOTIFY_ADD_DATA ) )
		{

			// create wizard dialogs
			this.createAllWizardDialogsForDataAdditionFromToolBar( wnd );

			// show the first wizard dialog
			this.mFigureIDSelectionWizardDialog.show();
			
		}
		else if( command.equals( SGDrawingWindow.NOTIFY_LOAD_PROPERTY ) )
		{
			this.createAllWizardDialogsToLoadPropertyFromToolBar( wnd );

			this.mPropertyFileChooserWizardDilaog.show();
		}

//		wnd.repaint();

		return true;
	}




	/**
	 * 
	 */
	private boolean fromCLorDDWizardDialog( final ActionEvent e )
	{
//System.out.println(e);

		Object source = e.getSource();
		SGWizardDialog dg = (SGWizardDialog)source;

		String command = e.getActionCommand();


		// データの型を決定するためのダイアログ
		if( command.equals( SGWizardDialog.OK_BUTTON_TEXT ) )
		{
			this.mCarryOnWizardFlag = true;
			dg.hide();
		}
		else if( command.equals( SGWizardDialog.CANCEL_BUTTON_TEXT ) )
		{
			this.mCarryOnWizardFlag = false;
			dg.hide();
		}


		return true;
	}



	/**
	 * 
	 * @param e
	 * @return
	 */
	private boolean addDataByToolBar( final ActionEvent e )
	{

		Object source = e.getSource();
		SGWizardDialog dg = (SGWizardDialog)source;

		String command = e.getActionCommand();

		// figure ID
		if( source.equals( this.mFigureIDSelectionWizardDialog ) )
		{
			
		}
		// data file
		else if( source.equals( this.mSingleDataFileChooserWizardDilaog ) )
		{

			if( command.equals( SGWizardDialog.NEXT_BUTTON_TEXT ) )
			{
					
				String pathName = this.mSingleDataFileChooserWizardDilaog.getFileName();

				Window owner = this.mSingleDataFileChooserWizardDilaog.getOwner();

				// データファイルを開いて情報を取得し、データを構築する
				// ファイルの情報リスト
				ArrayList infoList = new ArrayList();
				ArrayList cList = new ArrayList();
				ArrayList tokenNumList = new ArrayList();
				if( this.getFileTypeCandidateList( owner, pathName, cList, tokenNumList ) == false )
				{
					return false;
				}
				
				if( cList.size() == 0 )
				{
					System.out.println("データファイルが不正です。");
					return false;
				}
				
				
				// set candidate data-type to the dialog
				if( this.mXYDataTypeSelectionWizardDialog.setEffectiveDataType(cList) == false )
				{
					return false;
				}

			}
	
		}
		// data type
		else if( source.equals( this.mXYDataTypeSelectionWizardDialog ) )
		{

			if( command.equals( SGWizardDialog.OK_BUTTON_TEXT ) )
			{

				SGDrawingWindow wnd = dg.getOwnerWindow();
				final int windowID = wnd.getID();
				final int figureID = this.mFigureIDSelectionWizardDialog.getFigureID();

				String pathName = this.mSingleDataFileChooserWizardDilaog.getFileName();


				// データファイルを開いて情報を取得し、データを構築する
				// ファイルの情報リスト
				ArrayList infoList = new ArrayList();
				
				
				// get selected file type
				String fileType = this.mXYDataTypeSelectionWizardDialog.getSelectedDataType();
				if( fileType == null )
				{
					return false;
				}
				
				
				// add information to the list
				infoList.add(fileType);
				
				
				// create an array for data-retention
				if( fileType.equals(SGDataTypeConstants.SXY_SAMPLING_DATA) )
				{
					// infoList にサンプリングレートの情報を追加する
					Double d = this.mXYDataTypeSelectionWizardDialog.getSamplingRate();
					if( d==null )
					{
						return false;
					}
					infoList.add(d);
				}
				
				
				// データの構築
				if( infoList.size()==0 )
				{
					return false;
				}
				SGData data = this.createData( pathName, infoList );
				if( data == null )
				{
					System.out.println("データの構築に失敗しました。");
					return false;
				}


				// フィギュア
				SGFigure figure = wnd.getFigure( figureID );
				// フィギュアが存在しない場合には、フィギュアを新規作成
				if( figure==null || ( figure!=null && figure.isVisible()==false ) )
				{
					if( this.createNewFigure( wnd, figureID, data, new Point() ) == null )
					{
						return false;
					}
				}
				else
				{
					if( !figure.addData(data) )
					{
						System.out.println("データの型がフィギュアに合いません。");
						return false;
					}
				}


				// hide the dialog present wizard dialog
				dg.hide();


			}

		}


		//
		if( this.commonActionFromWizardDialog(e) == false )
		{
			return false;
		}


		return true;
	}




	/**
	 * determine the data-type from the property file
	 */
	private boolean getFileTypeCandidateListFromPropertyFile(
		final String pathName, final ArrayList cList )
	{

		try
		{

			FileInputStream fis = null;
			try
			{
				fis = new FileInputStream( pathName );
			}
			catch( FileNotFoundException ex )
			{
				Window owner = this.mXYDataTypeSelectionWizardDialog.getOwner();
				SGUtility.showFileNotFoundMessageDialog( owner );
				return false;
			}
			InputStreamReader ir = new InputStreamReader(fis);
			BufferedReader br = new BufferedReader(ir);


			String line = null;
			while( (line=SGUtilityText.readLine(br))!=null )
			{
				if( line.equals( SGIGraphElement.PF_DATA_TITLE ) )
				{
//System.out.println(line);
					while( true )
					{
						line = SGUtilityText.readLine(br);
						String value = SGUtilityText.getPropertyFromLine( line, SGIFigureElement.PF_CLASS_NAME );
						if( value!=null )
						{
							cList.add(value);
							break;
						}
					}
				}
			}

			br.close();
			ir.close();
			fis.close();

		}
		catch( Exception ex )
		{
			ex.printStackTrace();
			return false;
		}


		return true;
	}



	/**
	 * 
	 */
	public static final String TITLE_FILE_CHECK = "ファイルのチェック";


	/**
	 * 
	 * @param e
	 * @return
	 */
	private boolean loadPropertyFromToolBar( final ActionEvent e )
	{

		Object source = e.getSource();
		SGWizardDialog dg = (SGWizardDialog)source;

		String command = e.getActionCommand();


		// dialog to choose a property file
		if( source.equals( this.mPropertyFileChooserWizardDilaog ) )
		{
//System.out.println("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
//System.out.println(e);

			Window wnd = this.mPropertyFileChooserWizardDilaog.getOwner();

			if( command.equals( SGWizardDialog.NEXT_BUTTON_TEXT ) )
			{
				// get file type from the selected file
				File file = this.mPropertyFileChooserWizardDilaog.getSelectedFile();
				String path = SGUtility.getCanonicalPath( file.getPath() );
				if( path==null )
				{
					SGUtility.showMessageDialog( 
						dg, ERRMSG_FILE_OPEN_FAILURE, TITLE_FILE_CHECK, JOptionPane.ERROR_MESSAGE );
					return false;
				}

//
// プロパティファイルの文法をチェックする機構を作る必要があるか？
//

// check the format of the file
// XML ファイルとしての整合性、Window タグがあるか、
// 


				// read the property file and get a list of candidates of data-type
				ArrayList cList = new ArrayList();
				if( this.getFileTypeCandidateListFromPropertyFile( path, cList ) == false )
				{
					SGUtility.showMessageDialog(
						dg, ERRMSG_FILE_OPEN_FAILURE, TITLE_FILE_CHECK, JOptionPane.ERROR_MESSAGE );
					return false;
				}
//System.out.println(cList);
/*				if( cList.size()==0 )
				{
					SGUtility.showMessageDialog(
						dg, ERRMSG_PROPERTY_FILE_INCORRECT, TITLE_FILE_CHECK, JOptionPane.ERROR_MESSAGE );
					return false;
				}
*/


				final int fileNum = cList.size();
				this.mMultiDataFileChooserWizardDialog.setFileNumber( fileNum );


				// create a array of the data-type
				String[] cArray = new String[cList.size()];
				for( int ii=0; ii<cArray.length; ii++ )
				{
					cArray[ii] = (String)cList.get(ii);
				}


				// create a table model
				Object[][] data = new String[cArray.length][];
				for( int ii=0; ii<data.length; ii++ )
				{
					data[ii] = new String[2];
					data[ii][0] = cArray[ii];
					data[ii][1] = null;
				}

				Object[] columnName = { "Data Type", "File Name" };
				DefaultTableModel model	= new DefaultTableModel( data, columnName );

				this.mMultiDataFileChooserWizardDialog.setTableModel(model);

			}


		}
		else if( source.equals( this.mMultiDataFileChooserWizardDialog ) )
		{
			
			if( command.equals( SGWizardDialog.OK_BUTTON_TEXT ) )
			{
				File[] files = this.mMultiDataFileChooserWizardDialog.getSelectedFiles();
				this.mDataFileNameList.clear();	// 一旦、クリアする
				for( int ii=0; ii<files.length; ii++ )
				{
					this.mDataFileNameList.add(files[ii].getAbsolutePath());
				}


				String propertyFileName = this.mPropertyFileChooserWizardDilaog.getSelectedFile().getAbsolutePath();

				try
				{
					// create a window
					SGDrawingWindow wnd = this.createWindowFromPropertyFile(propertyFileName);
					if( wnd==null )
					{
						return false;								
					}
				}
				catch( Exception ex )
				{
					ex.printStackTrace();
					return false;
				}

				dg.hide();				
			}

		}


		if( this.commonActionFromWizardDialog(e) == false )
		{
			return false;
		}


		return true;
	}



	/**
	 * 
	 */
	private boolean commonActionFromWizardDialog( final ActionEvent e )
	{

		Object source = e.getSource();
		SGWizardDialog dg = (SGWizardDialog)source;

		String command = e.getActionCommand();

		if( command.equals( SGWizardDialog.CANCEL_BUTTON_TEXT ) )
		{
			// hide the dialog present wizard dialog
			dg.hide();
		}
		else if( command.equals( SGWizardDialog.PREVIOUS_BUTTON_TEXT ) )
		{
			// hide the dialog present wizard dialog
			dg.hide();

			// show the previous wizard dialog[
			SGWizardDialog prev = dg.getPrevious();
			if( prev!=null )
			{
				prev.show();
			}
		}
		else if( command.equals( SGWizardDialog.NEXT_BUTTON_TEXT ) )
		{
			// hide the dialog present wizard dialog
			dg.hide();

			// show the next wizard dialog
			SGWizardDialog next = dg.getNext();
			if( next!=null )
			{
				next.show();
			}
		}


		return true;
	}




	/**
	 * 
	 */
	private boolean fromWizardDialog( final ActionEvent e )
	{

		Object source = e.getSource();
		SGWizardDialog dg = (SGWizardDialog)source;

		String command = e.getActionCommand();


		//
		// from the command line or drag&drop
		//

		if( source.equals( this.mXYDataTypeSelectionWizardDialogFromCLorDD ) )
		{
			return this.fromCLorDDWizardDialog(e);
		}
		

		//
		// ツールバー
		//

		// グラフ描画
		if( source.equals( this.mFigureIDSelectionWizardDialog )
			|| source.equals( this.mSingleDataFileChooserWizardDilaog )
			|| source.equals( this.mXYDataTypeSelectionWizardDialog ) )
		{
			return this.addDataByToolBar(e);
		}


		// プロパティファイルの読み込み
		if( source.equals( this.mPropertyFileChooserWizardDilaog )
			|| source.equals( this.mMultiDataFileChooserWizardDialog ) )
		{
			return this.loadPropertyFromToolBar(e);	
		}


		return true;
	}




	/**
	 * 
	 */
	public void actionPerformed( final ActionEvent e )
	{
//System.out.println(e);

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

//System.out.println(source);
//System.out.println(command);
//System.out.println();

		// From the windows
		if( source instanceof SGDrawingWindow )
		{
			this.fromWindow(e);
		}
		// From the wizard dialogs
		else if( source instanceof SGWizardDialog )
		{
			this.fromWizardDialog(e);
		}

	}




	/**
	 * 
	 */
	private boolean mCarryOnWizardFlag = true;



	/**
	 * 
	 */
	public void windowOpened( final WindowEvent e )
	{
		
	}


	/**
	 * 
	 */
	public void windowClosed( final WindowEvent e )
	{

	}



	/**
	 * 
	 */
	public void windowClosing( final WindowEvent e )
	{

//System.out.println("<< windowClosing >>");
//System.out.println(this.mWndMap);
//System.out.println(this.mWndMap.size());
//System.out.println();

		Object source = e.getSource();

		if( source instanceof SGDrawingWindow )
		{
			final SGDrawingWindow wnd = (SGDrawingWindow)e.getSource();
			this.removeWindow(wnd);

			if( this.mWndMap.size() == 0 )
			{
//System.out.println("終了します。");
				System.exit(0);
			}
			
		}


	}



	/**
	 * Remove the window from window map.
	 */
	public boolean removeWindow( final SGDrawingWindow wnd )
	{

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

		final int id = wnd.getID();
		this.mWndMap.remove( new Integer(id) );
		wnd.removeWindowListener( this );
		wnd.removeActionListener(this);

		return true;

	}



	/**
	 * 
	 */
	public void windowActivated( final WindowEvent e )
	{
		
	}


	/**
	 * 
	 */
	public void windowDeactivated( final WindowEvent e )
	{
		
	}


	/**
	 * 
	 */
	public void windowIconified( final WindowEvent e )
	{
		
	}


	/**
	 * 
	 */
	public void windowDeiconified( final WindowEvent e )
	{
		
	}



	/**
	 * 
	 */
	public void dragEnter( final DropTargetDragEvent dtde )
	{
//System.out.println("dragEnter");
		dtde.acceptDrag(DnDConstants.ACTION_COPY_OR_MOVE);
	}



	/**
	 * 
	 */
	public void dragExit( final DropTargetEvent dte )
	{
//System.out.println("dragExit");
	}



	/**
	 * 
	 */
	public void dragOver( final DropTargetDragEvent dtde )
	{
//System.out.println("dragOver");
	}



	/**
	 * 
	 */
	public void drop( final DropTargetDropEvent dtde )
	{

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

		DropTarget tg = (DropTarget)dtde.getSource();
		Component com = tg.getComponent();
//System.out.println(com);

		SGDrawingWindow wnd = (SGDrawingWindow)com;


		dtde.acceptDrop( DnDConstants.ACTION_COPY_OR_MOVE );

		try
		{
			if( ( dtde.getDropAction() & DnDConstants.ACTION_COPY_OR_MOVE ) != 0 )
			{
				Transferable trans = dtde.getTransferable();
				java.util.List list
					= (java.util.List)trans.getTransferData( DataFlavor.javaFileListFlavor );
//System.out.println(list);

//				final Point p = dtde.getLocation();
//				this.addDataByDragAndDrop( p.x, p.y, wnd, new ArrayList(list) );


this.mDropTargetDropEvent = dtde;
this.mDroppedFileList = new ArrayList( list );
this.mThread = new ThreadForDropEvent();
this.mThread.start();

			}
			else
			{
				dtde.dropComplete( false );
			}
		}
		catch ( Exception ex )
		{
			ex.printStackTrace();
			dtde.dropComplete( false );
		}

	}


	private DropTargetDropEvent mDropTargetDropEvent = null;
	private ArrayList mDroppedFileList = null;
	private ThreadForDropEvent mThread = null;

	class ThreadForDropEvent extends Thread
	{
		public void run()
		{
//System.out.println("run");
			DropTargetDropEvent dtde = mDropTargetDropEvent;
			DropTarget tg = (DropTarget)dtde.getSource();
			Component com = tg.getComponent();
			SGDrawingWindow wnd = (SGDrawingWindow)com;
			Point p = dtde.getLocation();

			addDataByDragAndDrop( p.x, p.y, wnd, mDroppedFileList );

//System.out.println("added");
wnd.getContentPane().repaint();

			mDropTargetDropEvent = null;
			mDroppedFileList = null;
			mThread = null;	
		}
	}
	



	/**
	 * 
	 */
	public void dropActionChanged( final DropTargetDragEvent dtde )
	{
//System.out.println("dropActionChanged");
	}




	/**
	 * 
	 */
	private boolean addDataByDragAndDrop(
		final int x, final int y,
		final SGDrawingWindow wnd, final ArrayList fileList )
	{
//System.out.println("<< addDataToWindow >>");

		// dialog to select data-type
		this.mXYDataTypeSelectionWizardDialogFromCLorDD
			= new SGXYDataTypeSelectionWizardDialog( wnd, true );
		this.mXYDataTypeSelectionWizardDialogFromCLorDD.addActionListener(this);
		this.mXYDataTypeSelectionWizardDialogFromCLorDD.mPreviousButton.setEnabled(false);


		for( int jj=0; jj<fileList.size(); jj++ )
		{
			File file = (File)fileList.get(jj);
			try
			{
				String fileName = file.getCanonicalPath();
				SGData data = this.createDataFromFile(fileName);

//System.out.println(data);
				if( data == null )
				{
System.out.println("データは追加されませんでした。");
					continue;
				}

				Component com = wnd.getComponent(x,y);
				if( com instanceof SGDrawingWindow )
				{
					// フィギュア番号
					int figureID = wnd.getCurrentFigureId();

					// フィギュア
					SGFigure figure = wnd.getFigure( figureID );
					if( figure==null )
					{
						Point pos = new Point(x,y);
						figure = this.createNewFigure(
							wnd, figureID, data, pos );
						if( figure==null )
						{
							return false;
						}
					}
					else
					{
						// add data to the figure
						if( figure.addData( data ) == false )
						{
							return false;
						}
					}

				}
				else if( com instanceof SGFigure )
				{
					SGFigure fig = (SGFigure)com;
					fig.addData(data);
				}
				else
				{
					return false;
				}


			}
			catch( IOException ex )
			{
				ex.printStackTrace();
				return false;
			}
		}

		return true;
	}




	/**
	 * 
	 * @param wnd
	 * @param figureID
	 * @param data
	 * @param pos
	 * @return
	 */
	private SGFigure createNewFigure(
		final SGDrawingWindow wnd,
		final int figureID,
		final SGData data,
		final Point pos )
	{

		// create a figure instance
		SGFigure figure = this.createFigure( figureID, wnd, data );
		if( figure==null )
		{
			return null;
		}

/*
		SGIFigureElement[] array = figure.getIFigureElementArray();
		for( int ii=0; ii<array.length; ii++ )
		{
			array[ii].initPropertiesHistory();
		}
*/

		// init the history of the properties before the data is added
		if( figure.getGraphElement().initPropertiesHistory() == false )
		{
			return null;
		}


		// ウインドウにフィギュアをaddする
		TreeMap map = wnd.getFigureMap();
		if( map.containsValue(figure) == false )
		{
			wnd.addFigure( figureID, figure, pos );
		}


		//
		wnd.updateHistory();


		// フィギュアにデータを追加
		if( !figure.addData(data) )
		{
			System.out.println("データの型がフィギュアに合いません。");
			return null;
		}


		// init the history of the properties after the data is added
		if( figure.getAxisElement().initPropertiesHistory() == false )
		{
			return null;
		}
		if( figure.getLegendElement().initPropertiesHistory() == false )
		{
			return null;
		}
		if( figure.getStringElement().initPropertiesHistory() == false )
		{
			return null;
		}


		//
//		wnd.drawBackAllVisibleFigures();
		wnd.drawBackFigure( figure );


		// initialize the history of the properties
		// after drawn back
		figure.initPropertiesHistory();


		// show the window
		wnd.show();


		return figure;
	}

}


}

