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

import java.util.*;
import java.util.prefs.*;
import java.util.zip.*;
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 java.text.*;
import javax.swing.*;
import javax.swing.table.*;
import javax.xml.parsers.*;
import org.w3c.dom.*;
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 MAJOR_VERSION_NUMBER = 0;


	/**
	 * 
	 */
	public static final int MINOR_VERSION_NUMBER = 2;


	/**
	 * 
	 */
	public static final int MICRO_VERSION_NUMBER = 0;


	/**
	 * 
	 */
	public static int PORT_NUMBER = -1;


	/**
	 * 
	 */
	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[] )
	{

		// interpret command lines
		interpretCommands( args );

		try
		{
			if( PORT_NUMBER==-1 )
			{
				// create a new thread
				Connect c = new Connect();
			}
			else
			{
				// create a server socket object
				ServerSocket serverSocket
					= new ServerSocket( SGDrawingServer.PORT_NUMBER );

				// create a new thread
				Connect c = new Connect( serverSocket );
			}
		}
		catch ( Exception ex )
		{
			JOptionPane.showOptionDialog(
				null,
				"Failed to start up application.",
				"Error",
				JOptionPane.DEFAULT_OPTION,
				JOptionPane.WARNING_MESSAGE, 
				null,
				null,
				null
			);
		}

	}



	/**
	 * 
	 */
	private static void 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();
					}
					catch( NumberFormatException ex )
					{
						continue;
					}
				}
			}
		}

	}





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

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 static final String MSG_SUCCESSFUL_COMPLETION
		= "正常終了";


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


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


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


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


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


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


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


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


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



	/**
	 * 
	 *
	 */
	public Connect()
	{
		this.start();
	}


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

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



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

		// create and show the splash window
		SGSplashWindow sw = this.createSplashWindow();
		if( sw==null )
		{
			return;
		}
		sw.setVisible(true);


		// create the figure element
		try
		{
			if( this.setFigureElementClass() == false )
			{
				throw new Exception();
			}
		}
		catch( Exception ex )
		{
			JOptionPane.showMessageDialog(
				null,
				"Failed to create instances of SGFigureElement classes."
			);
			return;
		}


		// create a window
		SGDrawingWindow wnd = this.createWindow();
		if( wnd == null )
		{
			JOptionPane.showMessageDialog(
				null,
				"Failed to create a window"
			);
			return;
		}

/*
		// show startup wizard dialogs
		SGWizardDialog first = this.createStartupWizardDialogs(wnd);
		if( first==null )
		{
			return;
		}
*/

		// hide the splash window
		sw.setVisible(false);


		// show the window and the first wizard dialog
		wnd.setVisible(true);
//		first.setVisible(true);


		// update the preferences
		this.updatePreferences();


		// decide whether to upgrade
		if( this.checkDate() )
		{
			// upgrade
			if( this.upgradeOnStartup(wnd) == false )
			{
				return;
			}
		}



		//
		// infinite loop as a server process
		//
		if( this.mServerSocket!=null )
		{
			while( true )
			{
				try
				{
					// クライアントからの接続を待つ
					Socket socket = mServerSocket.accept();
	
					// 出力ストリームを取得
					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;
					}
					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();
				}
			}
		}

	}


	/**
	 * 
	 * @param element
	 * @param tagList
	 * @param out
	 */
	private void printNode(
		Element element, StringBuffer sb )
	{
		printNodeRecursively( element, sb, -1 );
	}



	/**
	 * 
	 * @param node
	 * @return
	 */
	private void printNodeRecursively(
		Element element, StringBuffer sb, final int depth )
	{
		NodeList childList = element.getChildNodes();
		for( int ii=0; ii<childList.getLength(); ii++ )
		{
			Node child = childList.item(ii);
			if( child instanceof Element )
			{
				Element el = (Element)child;
				String tagName = el.getTagName();
				if( tagName.equals("item") )
				{
					NodeList nList = el.getChildNodes();
					final int num = nList.getLength();
					if( num==1 )
					{
						printFirstChild( el, sb, depth );
					}
					else if( num>1 )
					{
						printFirstChild( el, sb, depth );
						for( int jj=0; jj<num; jj++ )
						{
							Node node = (Node)nList.item(jj);
							if( node instanceof Element )
							{
								Element el_ = (Element)node;
								printNodeRecursively( el_, sb, depth+1 );
							}
						}
					}
				}
				else if( tagName.equals("itemize") )
				{
					printNodeRecursively( el, sb, depth+1 );
				}
			}
			else if( child instanceof Text )
			{
				printText( child, sb, depth );
			}
		}

	}


	/**
	 * 
	 * @param node
	 * @param out
	 * @param depth
	 */
	private void printFirstChild(
		Node node, StringBuffer sb, final int depth )
	{
		Node child = node.getFirstChild();
		printText( child, sb, depth );
	}


	/**
	 * 
	 * @param node
	 * @param out
	 * @param depth
	 */
	private void printText(
		Node node, StringBuffer sb, final int depth )
	{
		String line = node.toString();
		String sub = tokenize(line);
		if( sub.length()!=0 )
		{
			String space = "";
			for( int ii=0; ii<depth; ii++ )
			{
				space += "   ";
			}

			String prefix = "";
			if( depth==0 )
			{
				prefix = "  ";
			}
			if( depth>0 )
			{
				prefix = "- ";
			}

			sub = space + prefix + sub + "\n";

//System.out.println(depth);
//System.out.println(sub);
//System.out.println();

			sb.append( sub );
		}
	}



	/**
	 * 
	 * @param line
	 * @return
	 */
	private String tokenize( String line )
	{
		StringTokenizer tkn = new StringTokenizer(line);
		ArrayList tokenList = new ArrayList();
		while( tkn.hasMoreTokens() )
		{
			tokenList.add( tkn.nextToken() );
		}

		String subStr = "";
		for( int ii=0; ii<tokenList.size(); ii++ )
		{
			String str = (String)tokenList.get(ii);
			subStr += str;
			if( ii!=tokenList.size()-1 )
			{
				subStr += " ";
			}
		}

		return subStr;
	}



	/**
	 * 
	 *
	 */
	private boolean upgradeOnStartup( Window owner )
	{
		return this.upgrade(owner,true);
	}


	/**
	 * 
	 *
	 */
	private boolean upgradeByCommand( Window owner )
	{
		return this.upgrade(owner,false);
	}


	/**
	 * 
	 * @return
	 */
	private Document createProductDocument()
	{
		return SGUtilityText.getDocument( URL_OF_PRODUCT_XML );
	}


	/**
	 * 
	 * @param owner
	 * @param onStartUp
	 */
	private boolean upgrade( final Window owner, final boolean onStartUp )
	{

		// create a Document object
		Document doc = this.createProductDocument();
		if( doc==null )
		{
			JOptionPane.showMessageDialog(
				owner,
				"Failed to get information of the latest version."
			);
			return false;
		}


		// get root element - product
		Element root = doc.getDocumentElement();

		// compare the version number
		if( this.compareVersion( root ) )
		{
			if( this.installLatestVersion(
				root,
				owner,
				onStartUp ) == false )
			{
				return false;
			}
		}
		else
		{
			if( !onStartUp )
			{
				// show a message dialog
				String msg = "The latest version is already installed.";
				JOptionPane.showMessageDialog( owner, msg );
			}
		}
	
		return true;
	}



	// keys for 
	public static final String PREF_KEY_DATE = "Date";
	public static final String PREF_KEY_UPGRADE_CYCLE = "Upgrade Cycle";
	public static final String PREF_KEY_MAJOR_VERSION_NUMBER = "Major Version";
	public static final String PREF_KEY_MINOR_VERSION_NUMBER = "Minor Version";
	public static final String PREF_KEY_MICRO_VERSION_NUMBER = "Micro Version";



	/**
	 * 
	 * @return
	 */
	private void updatePreferences()
	{
		Preferences pref = Preferences.userNodeForPackage( this.getClass() );

		// update the upgrade cycle at the first installation
		final int cycle = pref.getInt( PREF_KEY_UPGRADE_CYCLE, -1 );
		if( cycle==-1 )
		{
			pref.putInt( PREF_KEY_UPGRADE_CYCLE, DEFAULT_UPGRADE_CYCLE );
		}

		// update the version numbers
		final String date = pref.get( PREF_KEY_DATE, null );
		final int major = pref.getInt( PREF_KEY_MAJOR_VERSION_NUMBER, -1 );
		final int minor = pref.getInt( PREF_KEY_MINOR_VERSION_NUMBER, -1 );
		final int micro = pref.getInt( PREF_KEY_MICRO_VERSION_NUMBER, -1 );
		boolean b = false;

		// At the first installation
		if( date==null || major==-1 || minor==-1 || micro==-1 )
		{
			b = true;
		}
		// At the start-up of the application
		else
		{
			b = this.compareVersion(
				major, minor, micro,
				MAJOR_VERSION_NUMBER, MINOR_VERSION_NUMBER, MICRO_VERSION_NUMBER );
		}

		if( b )
		{
			pref.putLong( PREF_KEY_DATE, System.currentTimeMillis() );
			pref.putInt( PREF_KEY_MAJOR_VERSION_NUMBER, MAJOR_VERSION_NUMBER );
			pref.putInt( PREF_KEY_MINOR_VERSION_NUMBER, MINOR_VERSION_NUMBER );
			pref.putInt( PREF_KEY_MICRO_VERSION_NUMBER, MICRO_VERSION_NUMBER );
		}

	}



	private boolean compareVersion(
		final int m1, final int m2, final int m3,
		final int n1, final int n2, final int n3 )
	{
		boolean b;
		if( m1 < n1 )
		{
			b = true;
		}
		else if( m1 == n1 )
		{
			if( m2 < n2 )
			{
				b = true;
			}
			else if( m2 == n2 )
			{
				if( m3 < n3 )
				{
					b = true;
				}
				else
				{
					b = false;
				}
			}
			else
			{
				b = false;
			}
		}
		else
		{
			b = false;
		}

		return b;
	}




	/**
	 * 
	 */
	public static final int NO_UPGRADE = 0;
	public static final int UPGRADE_EVERY_TIME = 1;
	public static final int UPGRADE_EVERY_DAY = 2;
	public static final int UPGRADE_EVERY_WEEK = 3;
	public static final int UPGRADE_EVERY_MONTH = 4;


	// default upgrade cycle
	public static final int DEFAULT_UPGRADE_CYCLE = UPGRADE_EVERY_TIME;


	/**
	 * 
	 * @return
	 */
	private boolean checkDate()
	{
		Preferences pref = Preferences.userNodeForPackage( this.getClass() );
		final long time = pref.getLong( PREF_KEY_DATE, 0 );
		final long current = System.currentTimeMillis();
		final long diff = current - time;

		final long day = 1000*3600*24;
		final long week = 7*day;
		final long month = 30*day;
		final int cycle = pref.getInt( PREF_KEY_UPGRADE_CYCLE, UPGRADE_EVERY_TIME );

		boolean b;
		switch( cycle )
		{
			case NO_UPGRADE :
			{
				b = false;
				break;
			}

			case UPGRADE_EVERY_TIME :
			{
				b = true;
				break;
			}

			case UPGRADE_EVERY_DAY :
			{
				b = ( diff > day );
				break;
			}

			case UPGRADE_EVERY_WEEK :
			{
				b = ( diff > week );
				break;
			}

			case UPGRADE_EVERY_MONTH :
			{
				b = ( diff > month );
				break;
			}

			default :
			{
				b = false;
			}
		}

		return b;
	}



	/**
	 * 
	 */
	public static final String URL_OF_PRODUCT_XML
		= "http:/"+"/samurai-graph.sourceforge.jp/product.xml";


	/**
	 * 
	 * @return
	 */
	private boolean compareVersion( Element root )
	{
		Preferences pref = Preferences.userNodeForPackage( this.getClass() );
		final int major = pref.getInt( PREF_KEY_MAJOR_VERSION_NUMBER, -1 );
		final int minor = pref.getInt( PREF_KEY_MINOR_VERSION_NUMBER, -1 );
		final int micro = pref.getInt( PREF_KEY_MICRO_VERSION_NUMBER, -1 );

		final int nMajor = this.getVersion( root, "majorver" );
		final int nMinor = this.getVersion( root, "minorver" );
		final int nMicro = this.getVersion( root, "microver" );
		final boolean b = this.compareVersion( major, minor, micro, nMajor, nMinor, nMicro );
		return b;
	}



	/**
	 * 
	 * @param root
	 * @param tagName
	 * @return
	 */
	private int getVersion( Element root, String tagName )
	{
		Element ver = (Element)root.getElementsByTagName(tagName).item(0);
		String verString = ver.getFirstChild().getNodeValue();
		final int verNumber = Integer.parseInt( verString );
		return verNumber;
	}



	/**
	 * 
	 * @param root
	 * @return
	 * @throws Exception
	 */
	private boolean installLatestVersion(
		Element root, final Window owner, final boolean onStartUp )
	{

		// get the latest release
		NodeList rList = root.getElementsByTagName("release");
		Element latestRelease = null;
		for( int ii=0; ii<rList.getLength(); ii++ )
		{
			Element el = (Element)rList.item(ii);
			String value = el.getAttribute("latest");
			if( Boolean.TRUE.toString().equals(value) )
			{
				latestRelease = el;
				break;
			}
		}
		if( latestRelease==null )
		{
			JOptionPane.showMessageDialog(
				owner,
				"Statement in the XML file is wrong."
			);
			return false;
		}


		// get the latest version numbers
		final int nMajor = this.getVersion( latestRelease, "majorver" );
		final int nMinor = this.getVersion( latestRelease, "minorver" );
		final int nMicro = this.getVersion( latestRelease, "microver" );

		final String major = new Integer( nMajor ).toString();
		final String minor = new Integer( nMinor ).toString();
		final String micro = new Integer( nMicro ).toString();

		
		// message
		String msg = "Samurai Graph Ver." + major + "." + minor + "." + micro + " is found.\n"
			+ "Upgrade now?\n";

		// get the change log
		NodeList rInfoList = latestRelease.getElementsByTagName("releaseinfo");
		Element rInfo = (Element)rInfoList.item(0);
		NodeList cLogList = rInfo.getElementsByTagName("changelog");
		Element cLog = (Element)cLogList.item(0);
		StringBuffer sb_ = new StringBuffer();
		this.printNode(cLog,sb_);
		StringBuffer sb = new StringBuffer("-- New Features --\n");
		sb.append(sb_);
		
		// create a message dialog
		SGUpgradeConfirmDialog cfDialog = null;
		if( owner instanceof Frame )
		{
			cfDialog = new SGUpgradeConfirmDialog( (Frame)owner, true );
		}
		else if( owner instanceof Dialog )
		{
			cfDialog = new SGUpgradeConfirmDialog( (Dialog)owner, true );
		}
		cfDialog.setMessage(msg);
		cfDialog.setDetailText( new String(sb) );
		cfDialog.pack();
		cfDialog.setCenter(owner);

		// show a message dialog
		cfDialog.setVisible(true);

		// if upgrade is canceled, return true
		if( cfDialog.isCanceled() )
		{
			return true;
		}


		// get OS name
		String name = null;
		String osName = System.getProperty("os.name").toLowerCase();
		if( osName.startsWith("windows") )
		{
			name = "win32";
		}
		else if( osName.startsWith("mac os x") )
		{
			name = "macosx";
		}
		else
		{
			name = "other";
		}


		// upgrade
		NodeList pList = latestRelease.getElementsByTagName("package");
		for( int ii=0; ii<pList.getLength(); ii++ )
		{
			Element el = (Element)pList.item(ii);
			String attr = el.getAttribute("category");

			if( attr.equals("win32") )
			{
				if( name.equals("win32") )
				{
					if( this.forWin32(el,major,minor,micro,owner,onStartUp) )
					{
						break;
					}
					else
					{
						return false;
					}
				}
			}
			else if( attr.equals("macosx") )
			{
				if( name.equals("macosx") )
				{
					if( this.forMacOSX(el,major,minor,micro,owner,onStartUp) )
					{
						break;
					}
					else
					{
						return false;
					}
				}
			}
			else if( attr.equals("bin") )
			{
				if( name.equals("other") )
				{
					if( this.forOtherPlatform(el,major,minor,micro,owner,onStartUp) )
					{
						break;
					}
					else
					{
						return false;
					}
				}
			}
			else if( attr.equals("src") )
			{

			}

		}

		return true;
	}



	/**
	 * 
	 * @param el
	 * @return
	 * @throws Exception
	 */
	private boolean forWin32(
		final Element el, final String major, final String minor, final String micro,
		final Window owner, final boolean onStartUp )
	{

		// show a message dialog
		if( !onStartUp )
		{
			String msg = "This application will be terminated.\n"
				+"Present work will be lost.";
			String title = "Warning";
			Object[] options = { "OK", "Cancel" };
			final int ret = JOptionPane.showOptionDialog(
				owner,
				msg,
				title,
				JOptionPane.DEFAULT_OPTION,
				JOptionPane.WARNING_MESSAGE, 
				null,
				options,
				options[0]
			);
			if( ret==JOptionPane.NO_OPTION || ret==JOptionPane.CLOSED_OPTION )
			{
				return true;
			}
		}


		// download the file
		File file = null;
		try
		{
			file = File.createTempFile( "tmp_", ".exe" );
		}
		catch( IOException ex )
		{
			return false;
		}
		file.deleteOnExit();	// set to be deleted on exit
		if( this.download( el, owner, file ) == false )
		{
			return false;
		}


		// start installer
		try
		{
			String[] cmdArray = new String[2];
			cmdArray[0] = file.getAbsolutePath();
			cmdArray[1] = "/S";
			Process p = Runtime.getRuntime().exec( cmdArray );
			try
			{
				p.waitFor();
			}
			catch( InterruptedException ex )
			{
			}
		}
		catch( IOException ex )
		{
			JOptionPane.showMessageDialog(
				owner,
				"Failed to install the new version."
			);
			return false;
		}


		// show a message dialog
		JOptionPane.showMessageDialog(
			owner,
			"Successfully installed the new version."
		);


		// change directory
		String currentDir = System.getProperty("user.dir");
		String upperDir = SGUtility.getUpperDirectory( currentDir );
		System.setProperty( "user.dir", upperDir );


		// check uninstaller
		String uninstPath = currentDir + "\\Uninstall.exe";
		File uninst = new File( uninstPath );
		if( uninst.exists() == false )
		{
			JOptionPane.showMessageDialog(
				owner,
				"Uninstaller not found.\n"
				+ "Failed to uninstall the old version."
			);
			return false;
		}


		// start uninstaller
		try
		{
			String[] cmdArray = new String[2];
			cmdArray[0] = uninstPath;
			cmdArray[1] = "/S";
			Process p = Runtime.getRuntime().exec( cmdArray );
			try
			{
				p.waitFor();
			}
			catch( InterruptedException ex )
			{
			}
		}
		catch( IOException ex )
		{
			JOptionPane.showMessageDialog(
				owner,
				"Failed to uninstall the old version."
			);
			return false;
		}


		// show a message dialog
		JOptionPane.showMessageDialog(
			owner,
			"Successfully uninstalled the old version."
		);


		// start new version
		try
		{
			String javaw = System.getProperty("java.home") + "\\bin\\javaw.exe";
			String newVersion = upperDir + "\\Samurai-Graph-"
				+ major + "." + minor + "." + micro
				+ "\\samurai-graph.jar";
			String[] cmdArray = new String[4];
			cmdArray[0] = javaw;
			cmdArray[1] = "-Xmx128M";
			cmdArray[2] = "-jar";
			cmdArray[3] = newVersion;
			Process p = Runtime.getRuntime().exec( cmdArray );
		}
		catch( IOException ex )
		{
			JOptionPane.showMessageDialog(
				owner,
				"Failed to start the new version."
			);
			return false;
		}


 		//
		System.exit(0);

		return true;
	}



	/**
	 * 
	 * @param el
	 * @return
	 * @throws Exception
	 */
	private boolean forOtherPlatform(
		final Element el, final String major, final String minor, final String micro,
		final Window owner, final boolean onStartUp )// throws Exception
	{
		return this.downloadWithFileChooser(
			el, major, minor, micro, owner, onStartUp,
			"samurai-graph-bin", "zip" );
	}



	/**
	 * 
	 * @param el
	 * @return
	 * @throws Exception
	 */
	private boolean forMacOSX(
		final Element el, final String major, final String minor, final String micro,
		final Window owner, final boolean onStartUp )// throws Exception
	{
		return this.downloadWithFileChooser(
			el, major, minor, micro, owner, onStartUp,
			"samurai-graph-mac", "dmg.gz" );
	}



	/**
	 * 
	 */
	private String mDirectoryName = null;



	/**
	 * 
	 * @param el
	 * @param major
	 * @param minor
	 * @param micro
	 * @param owner
	 * @param onStartUp
	 * @param extension
	 * @return
	 * @throws Exception
	 */
	private boolean downloadWithFileChooser(
		final Element el, final String major, final String minor, final String micro,
		final Window owner, final boolean onStartUp, final String name, final String extension )
	{
		// create a file filter object
		SGExtensionFileFilter ff = new SGExtensionFileFilter();
		ff.setDescription( extension );
		ff.addExtension( extension );

		// initialize directory name
		if( this.mDirectoryName==null )
		{
			this.mDirectoryName = System.getProperty("user.home");
		}

		// create a file chooser object
		JFileChooser chooser = new JFileChooser( this.mDirectoryName );
		chooser.setFileFilter( ff );


		// set file name
		String fileName = name + "-" + major + "." + minor + "." + micro + "." + extension;
		chooser.setSelectedFile( new File( fileName ) );


		// show save dialog
		final int ret = chooser.showSaveDialog(owner);

		File fileSaved = null;
		switch( ret )
		{
			// selected
			case JFileChooser.APPROVE_OPTION :
			{
				fileSaved = chooser.getSelectedFile();
				break;
			}

			// canceled
			case JFileChooser.CANCEL_OPTION :
			{
				return true;
			}

			// error
			case JFileChooser.ERROR_OPTION :
			{
				throw new Error();
			}

			default :
			{
				
			}
		}

		String path = fileSaved.getAbsolutePath();
		if( path.endsWith( extension ) == false
			&& path.endsWith( extension.toUpperCase() ) == false )
		{
			path += "." + extension;
		}
		File file = new File(path);

		// download
		if( this.download( el, owner, file ) == false )
		{
			return false;
		}

		return true;
	}



	/**
	 * 
	 * @param el
	 * @param owner
	 * @param suffix
	 * @return
	 * @throws Exception
	 */
	private boolean download(
		final Element el, final Window owner, final File file )
	{
		FileOutputStream fos = null;
		BufferedOutputStream out = null;
		InputStream in = null;
		SGProgressMonitorDialog dg = null;

		boolean ret = false;

		try
		{
			// create output stream
			fos = new FileOutputStream(file);
			out = new BufferedOutputStream(fos);
	
			NodeList urlList = el.getElementsByTagName("url");
			for( int ii=0; ii<urlList.getLength(); ii++ )
			{
				Element urlElement = (Element)urlList.item(ii);
				String urlStr = urlElement.getFirstChild().getNodeValue();
	
				// create an URL instance
				URL url = null;
				try
				{
					url = new URL(urlStr);
				}
				catch( MalformedURLException ex )
				{
					continue;
				}
	
				// get input stream
				URLConnection co = null;
				try
				{
					co = url.openConnection();
					in = co.getInputStream();
				}
				catch( IOException ex )
				{
					continue;
				}


				// get file name
				String path = file.getAbsolutePath();
/*				final int nameLen = 20;
				if( path.length() > nameLen )
				{
					path = path.substring(0,nameLen);
					path += "...";
				}
*/

				// get file size
				final int fileSize = co.getContentLength();

				// create a progress monitor dialog
				boolean modal = true;
				if( owner instanceof Dialog )
				{
					dg = new SGProgressMonitorDialog( (Dialog)owner, modal );
				}
				else if( owner instanceof JFrame )
				{
					dg = new SGProgressMonitorDialog( (Frame)owner, modal );
				}


				// set properties of the progress bar
				JProgressBar pBar = dg.getProgressBar();
				pBar.setMinimum(0);
				pBar.setMaximum(fileSize);
				pBar.setStringPainted(true);


				// set properties of the dialog
				dg.setInputSize(fileSize);
				dg.setInputStream(in);
				dg.setOutputStream(out);
				dg.setLabel(path);
				dg.pack();
				dg.setCenter(owner);


				// set the mouse cursor
				owner.setCursor(
					Cursor.getPredefinedCursor( Cursor.WAIT_CURSOR ) );


				// start download
				Thread th = new Thread(dg);
				th.start();

				dg.setVisible(true);


				if( dg.isCanceled() == true )
				{
					return false;
				}

				ret = true;
				break;
			}

		}
		catch( FileNotFoundException ex )
		{
			JOptionPane.showMessageDialog(
				owner,
				"Local file is missing."
			);
			return false;
		}
		finally
		{

			// set default cursor
			owner.setCursor( Cursor.getDefaultCursor() );

			// clear attributes
			dg.setInputStream(null);
			dg.setOutputStream(null);

			// close streams
			if( in!=null )
			{
				try
				{
					in.close();
				}
				catch( IOException ex )
				{
					JOptionPane.showMessageDialog(
						owner,
						"Failed to close the input stream."
					);
					return false;
				}
			}
			
			if( out!=null )
			{
				try
				{
					out.close();
				}
				catch( IOException ex )
				{
					JOptionPane.showMessageDialog(
						owner,
						"Failed to close the output stream."
					);
					return false;
				}
			}

			if( fos!=null )
			{
				try
				{
					fos.close();
				}
				catch( IOException ex )
				{
					JOptionPane.showMessageDialog(
						owner,
						"Failed to close the output stream."
					);
					return false;
				}
			}

		}


		// when connection failed, return false
		if( !ret )
		{
			JOptionPane.showMessageDialog(
				owner,
				"Connection failed."
			);
			return false;
		}

		return true;
	}





	/**
	 * 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";



	/**
	 * Create instances of the figure elements.
	 */
	private boolean setFigureElementClass()
		throws ClassNotFoundException, InstantiationException,
			IllegalAccessException, IOException
	{

		// open the file
		FileInputStream fis = null;

		try
		{
			fis = new FileInputStream("ListOfFigureElement.txt");
		}
		catch( FileNotFoundException ex )
		{
			// If the file is not found, create instances of the default class.
			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;
		}

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

		try
		{
			// 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;

		}
		finally
		{
			br.close();
			isw.close();
			fis.close();
		}

		return true;

	}



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

		// 第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();
		}

		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.setVisible(true);


		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();
		}


		// ウインドウの取得
		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();
		}


		// 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 )
	{

		SGFigure figure = null;

		// 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);


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


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

		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();
		}
		
		return true;
	}







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

		// ファイルの情報リスト
		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 );


		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 );
		this.mFigureIDSelectionWizardDialog.getOKButton().setVisible(false);
		this.mFigureIDSelectionWizardDialog.getPreviousButton().setVisible(false);
		this.mFigureIDSelectionWizardDialog.pack();


		// dialog to select data files
		this.mSingleDataFileChooserWizardDilaog
			= new SGSingleDataFileChooserWizardDialog( owner, true );
		this.mSingleDataFileChooserWizardDilaog.getOKButton().setVisible(false);
		this.mSingleDataFileChooserWizardDilaog.pack();


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


		//
		// set next and previous dialogs
		//
		
		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
		//


		// dialog to load property file
		this.mPropertyFileChooserWizardDilaog
			= new SGPropertyFileChooserWizardDialog( owner, true );
		this.mPropertyFileChooserWizardDilaog.getPreviousButton().setVisible(false);
		this.mPropertyFileChooserWizardDilaog.getOKButton().setVisible(false);
		this.mPropertyFileChooserWizardDilaog.pack();


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


		//
		// 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 )
	{

		FileInputStream fis = null;
		InputStreamReader ir = null;
		BufferedReader br = null;

		try
		{
			fis = new FileInputStream( pathName );
			ir = new InputStreamReader(fis);
			br = new BufferedReader(ir);

			String line = SGUtilityText.readLine(br);
			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( FileNotFoundException ex )
		{
//			Window owner = this.mSingleDataFileChooserWizardDilaog.getOwner();
			SGUtility.showFileNotFoundMessageDialog( owner );
			return false;
		}
		finally
		{
			if( br!=null )
			{
				try
				{
					br.close();
				}
				catch( IOException ex )
				{
					
				}
			}

			if( ir!=null )
			{
				try
				{
					ir.close();
				}
				catch( IOException ex )
				{
					
				}
			}
			
			if( fis!=null )
			{
				try
				{
					fis.close();
				}
				catch( IOException ex )
				{
					
				}
			}
		}

		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
//		final int ox = owner.getX();
//		final int oy = owner.getY();
//		this.mXYDataTypeSelectionWizardDialogFromCLorDD.setLocation( ox, oy );
		this.mXYDataTypeSelectionWizardDialogFromCLorDD.setCenter( owner );


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


		//
		// 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;

		FileInputStream fis = null;
		InputStreamReader ir = null;
		BufferedReader br = null;

		try
		{
			fis = new FileInputStream( pathName );
			ir = new InputStreamReader(fis);
			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();

		}
		catch( FileNotFoundException ex )
		{
			Window owner = this.mXYDataTypeSelectionWizardDialog.getOwner();
			SGUtility.showFileNotFoundMessageDialog( owner );
			return num;
		}
		finally
		{
			if( br!=null )
			{
				try
				{
					br.close();
				}
				catch( IOException ex )
				{
					
				}
			}

			if( ir!=null )
			{
				try
				{
					ir.close();
				}
				catch( IOException ex )
				{
					
				}
			}
			
			if( fis!=null )
			{
				try
				{
					fis.close();
				}
				catch( IOException ex )
				{
					
				}
			}
		}


		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();
		}

		FileInputStream fis = null;
		InputStreamReader ir = null;
		BufferedReader br = null;

		try
		{
			fis = new FileInputStream( pathName );
			ir = new InputStreamReader(fis);
			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 );
				}
			}
		}
		catch( FileNotFoundException ex )
		{
			Window owner = this.mXYDataTypeSelectionWizardDialog.getOwner();
			SGUtility.showFileNotFoundMessageDialog( owner );
			return null;
		}
		finally
		{
			if( br!=null )
			{
				try
				{
					br.close();
				}
				catch( IOException ex )
				{
					
				}
			}

			if( ir!=null )
			{
				try
				{
					ir.close();
				}
				catch( IOException ex )
				{
					
				}
			}

			if( fis!=null )
			{
				try
				{
					fis.close();
				}
				catch( IOException ex )
				{
					
				}
			}
		}

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


/*
		//
		// create wizard dialogs
		//
		
		// to add data
		this.createAllWizardDialogsForDataAdditionFromToolBar( wnd );

		// to load property
		this.createAllWizardDialogsToLoadPropertyFromToolBar( wnd );
*/

		return true;
	}






	/**
	 * 
	 */
	private boolean addWindow( final SGDrawingWindow wnd )
	{
		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 )
	{
		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 SGIConstants.PROPERTY_FILE_INCORRECT;
		}
		if( line.equals( SGDrawingWindow.WINDOW_TITLE ) == false )
		{
			return SGIConstants.PROPERTY_FILE_INCORRECT;
		}


		float unit = SGIConstants.CM_POINT_RATIO;


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


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


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


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


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


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


		// 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
		int ret = this.createFiguresFromPropertyFile( br, wnd );
		if( ret==SGIConstants.DATA_NUMBER_SHORTAGE
			|| ret==SGIConstants.PROPERTY_FILE_INCORRECT
			|| ret==SGIConstants.FILE_OPEN_FAILURE )
		{
			return ret;
		}

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


		return ret;

	}



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

		SGDrawingWindow wnd = null;

		InputStream is = null;
		InputStreamReader isw = null;
		BufferedReader br = null;

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

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


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


			// set the property of the created window from property file
			int ret = this.createWindowFromPropertyFile(wnd,is,isw,br);


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


			// show the window
			wnd.setVisible(true);


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


			if( ret==SGIConstants.PROPERTY_FILE_INCORRECT )
			{
				wnd.setVisible(false);
				this.removeWindow(wnd);
			}

		}
		catch( Exception ex )
		{
			return null;
		}
		finally
		{
			if( br!=null )
			{
				try
				{
					br.close();
				}
				catch( IOException ex )
				{
					
				}
			}

			if( isw!=null )
			{
				try
				{
					isw.close();
				}
				catch( IOException ex )
				{
					
				}
			}
			
			if( is!=null )
			{
				try
				{
					is.close();
				}
				catch( IOException ex )
				{
					
				}
			}
		}


		return wnd;

	}




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

		// check the argument
		if( wnd==null )
		{
			new IllegalArgumentException("wnd==null");
		}

		InputStream is = null;
		InputStreamReader isw = null;
		BufferedReader br = null;

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

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

		try
		{
			// set the property of the created window from property file
			int ret = this.createWindowFromPropertyFile(wnd,is,isw,br);
	
			String msg = null;
			if( ret == SGIConstants.SUCCESSFUL_COMPLETION )
			{
				msg = MSG_SUCCESSFUL_COMPLETION;
			}
			else if( ret == SGIConstants.DATA_NUMBER_SHORTAGE )
			{
				msg = ERRMSG_DATA_NUMBER_SHORTAGE;
			}
			else if( ret == SGIConstants.DATA_NUMBER_EXCESS )
			{
				msg = ERRMSG_DATA_NUMBER_EXCESS;
			}
			else if( ret == SGIConstants.FILE_OPEN_FAILURE )
			{
				msg = ERRMSG_FILE_OPEN_FAILURE;
			}
			else if( ret == SGIConstants.PROPERTY_FILE_INCORRECT )
			{
				msg = ERRMSG_PROPERTY_FILE_INCORRECT;
			}
			else
			{
				throw new Exception();
			}
	
			// show the message dialog
			if( msg!=MSG_SUCCESSFUL_COMPLETION )
			{
				SGUtility.showMessageDialog(
					wnd, msg, PROPERTY_FILE_READ_MSG_DIALOG_TITLE,
					JOptionPane.ERROR_MESSAGE
				);
			}

		}
		catch( Exception ex )
		{
			return null;
		}
		finally
		{
			if( br!=null )
			{
				try
				{
					br.close();
				}
				catch( IOException ex )
				{
					
				}
			}

			if( isw!=null )
			{
				try
				{
					isw.close();
				}
				catch( IOException ex )
				{
					
				}
			}
			
			if( is!=null )
			{
				try
				{
					is.close();
				}
				catch( IOException ex )
				{
					
				}
			}
		}


		return wnd;

	}




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

		String line = null;

		final float unit = SGIConstants.CM_POINT_RATIO;


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

			//
			// title
			//

			if( (line=SGUtilityText.readLine(br)) == null )
			{
				return SGIConstants.END_OF_PROPERTY_FILE;
			}
			if( line.equals( SGFigure.PF_FIGURE_TITLE ) == false )
			{
				br.reset();
				break;
			}


			//
			// the name of instance
			//

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


			//
			// create a figure
			//

			Class cl = Class.forName( className );
			SGFigure figure = (SGFigure)cl.newInstance();
			figure.setWindow( wnd );
			final int figureID = wnd.getCurrentFigureId();
			figure.setID(figureID);



			//
			// bounds of the figure
			//

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

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


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

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


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

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


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

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

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



			//
			// space
			//

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

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


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

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


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

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


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

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



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

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



			//
			// create SGIFigureElement objects
			//

			int ret;

			// SGIAxisElement
			ret = this.createAxisElementFromPropertyFile(figure,br);
			if( ret==SGIConstants.PROPERTY_FILE_INCORRECT || ret==SGIConstants.END_OF_PROPERTY_FILE )
			{
				return ret;
			}
			SGIAxisElement axisElement = figure.getAxisElement();
			axisElement.readProperty(br);


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


			// SGIGraphElement
			ret = this.createGraphElementFromPropertyFile(figure,br);
			if( ret==SGIConstants.PROPERTY_FILE_INCORRECT || ret==SGIConstants.END_OF_PROPERTY_FILE )
			{
				return ret;
			}
			SGIGraphElement graphElement = figure.getGraphElement();
			graphElement.readProperty(br);


			// SGILegendElement
			ret = this.createLegendElementFromPropertyFile(figure,br);
			if( ret==SGIConstants.PROPERTY_FILE_INCORRECT || ret==SGIConstants.END_OF_PROPERTY_FILE )
			{
				return ret;
			}
			SGILegendElement legendElement = figure.getLegendElement();
			legendElement.readProperty(br);

			//
			figure.setLegendVisible( legendVisible );


			// SGIStringElement
			ret = this.createStringElementFromPropertyFile(figure,br);
			if( ret==SGIConstants.PROPERTY_FILE_INCORRECT || ret==SGIConstants.END_OF_PROPERTY_FILE )
			{
				return ret;
			}
			SGIStringElement stringElement = figure.getStringElement();
			stringElement.readProperty(br);


			//
			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
			//

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


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

	}




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

		int ret;

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


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


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


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

		return true;
	}




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

		String line = null;

		// タイトルの文字列が無ければ終了
		if( ( line = SGUtilityText.readLine(br) ) == null )
		{
			return SGIConstants.PROPERTY_FILE_INCORRECT;
		}
		if( line.equals( SGIStringElement.PF_STRING_TITLE ) == false )
		{
			return SGIConstants.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 SGIConstants.SUCCESSFUL_COMPLETION;

	}


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

		String line = null;

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


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

	}




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

		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 SGIConstants.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 SGIConstants.PROPERTY_FILE_INCORRECT;
		}
		if( line.equals( SGILegendElement.PF_LEGEND_TITLE ) == false )
		{
			return SGIConstants.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 SGIConstants.SUCCESSFUL_COMPLETION;

	}






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

		String line = null;

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

			// "[Data]"の文字列が無ければ終了
			if( ( line = SGUtilityText.readLine(br) ) == null )
			{
				return SGIConstants.END_OF_PROPERTY_FILE;
			}
			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 SGIConstants.PROPERTY_FILE_INCORRECT;
			}

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

			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 SGIConstants.DATA_TYPE_INCORRECT;
				}
				Double d = SGUtilityText.getDoublePropertyFromLine( line, SGIGraphElement.PF_SAMPLING_RATE );
				if( d == null )
				{
					return SGIConstants.DATA_TYPE_INCORRECT;
				}

				infoList.add(d);

			}
			else
			{
				return SGIConstants.DATA_TYPE_INCORRECT;
			}


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


			//
			if( this.mDataFileNameList.size() == 0 )
			{
				return SGIConstants.DATA_NUMBER_SHORTAGE;
			}


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


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

			br.mark(256);

		}


		return SGIConstants.SUCCESSFUL_COMPLETION;

	}




	/**
	 * 
	 */
	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 ) )
		{
			SGDrawingWindow wnd2 = this.createWindow();
			wnd2.setVisible( true );
		}
		else if( command.equals( SGDrawingWindow.NOTIFY_ADD_DATA ) )
		{
			// create wizard dialogs
			this.createAllWizardDialogsForDataAdditionFromToolBar( wnd );

			// set location
			this.mFigureIDSelectionWizardDialog.setCenter( wnd );

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

			// set location
			this.mPropertyFileChooserWizardDilaog.setCenter( wnd );

			// show the first wizard dialog
			this.mPropertyFileChooserWizardDilaog.setVisible(true);
		}
		else if( command.equals( SGDrawingWindow.NOTIFY_UPGRADE ) )
		{
			return this.showUpgradeDialog(wnd);
		}
		else if( command.equals( SGDrawingWindow.NOTIFY_SHOW_CHANGE_LOG ) )
		{
			return this.showChangeLogDialog(wnd);
		}

		return true;
	}


	/**
	 * 
	 */
	private SGUpgradeDialog mUpgradeDialog = null;


	/**
	 * 
	 * @param wnd
	 * @return
	 */
	private boolean showUpgradeDialog( Frame wnd )
	{
//		if( this.mUpgradeDialog==null )
		{
			this.mUpgradeDialog = new SGUpgradeDialog(wnd,true);
			this.mUpgradeDialog.addActionListener( this );
		}

		this.mUpgradeDialog.setCenter(wnd);

		Preferences pref = Preferences.userNodeForPackage( this.getClass() );
		final int cycleType = pref.getInt( PREF_KEY_UPGRADE_CYCLE, NO_UPGRADE );

		String cycle = null;
		switch( cycleType )
		{
			case Connect.NO_UPGRADE:
			{
				cycle = SGUpgradeDialog.NO_UPGRADE;
				break;
			}

			case Connect.UPGRADE_EVERY_TIME:
			{
				cycle = SGUpgradeDialog.EVERY_TIME;
				break;
			}

			case Connect.UPGRADE_EVERY_DAY:
			{
				cycle = SGUpgradeDialog.EVERY_DAY;
				break;
			}

			case Connect.UPGRADE_EVERY_WEEK:
			{
				cycle = SGUpgradeDialog.EVERY_WEEK;
				break;
			}

			case Connect.UPGRADE_EVERY_MONTH:
			{
				cycle = SGUpgradeDialog.EVERY_MONTH;
				break;
			}

			default:
			{
				cycle = SGUpgradeDialog.NO_UPGRADE;
			}
		}
		this.mUpgradeDialog.setUpgradeCycle( cycle );


		// show
		this.mUpgradeDialog.setVisible(true);

		return true;
	}



	private SGChangeLogDialog mChangeLogDialog = null;


	/**
	 * 
	 * @return
	 */
	private boolean showChangeLogDialog( Frame owner )
	{
		this.mChangeLogDialog = new SGChangeLogDialog(owner,true);
		this.mChangeLogDialog.addActionListener( this );
		this.mChangeLogDialog.setCenter(owner);

		// create a Document object
		Document doc = this.createProductDocument();
		if( doc==null )
		{
			JOptionPane.showMessageDialog(
				owner,
				"Failed to get log information."
			);
			return false;
		}

		// get root element - product
		Element root = doc.getDocumentElement();

		// get the release node
		NodeList rList = root.getElementsByTagName("release");
		ArrayList sbList = new ArrayList();
		int len = rList.getLength();
		for( int ii=0; ii<len; ii++ )
		{
			Node node = rList.item(ii);
			if( node instanceof Element )
			{
				Element release = (Element)node;

				// get change log
				NodeList rInfoList = release.getElementsByTagName("releaseinfo");
				Element rInfo = (Element)rInfoList.item(0);

				NodeList cLogList = rInfo.getElementsByTagName("changelog");
				Element cLog = (Element)cLogList.item(0);

				NodeList descList = rInfo.getElementsByTagName("releasedesc");
				Element desc = (Element)descList.item(0);
				String descStr = "<< "+ desc.getFirstChild().toString() + " >>\n";

				NodeList dateList = rInfo.getElementsByTagName("releasedate");
				Element date = (Element)dateList.item(0);
				String dateStr = "Released at " + date.getFirstChild().toString() + ".\n";

				StringBuffer sb = new StringBuffer();
				sb.append( descStr );
				sb.append( dateStr );
				this.printNode( cLog, sb );
				if( ii!=len-1 )
				{
					sb.append( "\n" );
				}
				sbList.add( sb );
			}
		}

		String msg = "Change Log of Samurai Graph.";
		this.mChangeLogDialog.setMessage(msg);

		StringBuffer sb = new StringBuffer();
		for( int ii=0; ii<len; ii++ )
		{
			sb.append( (StringBuffer)sbList.get(ii) );
		}
		this.mChangeLogDialog.setDetailText( new String(sb) );

		this.mChangeLogDialog.pack();


		// show
		this.mChangeLogDialog.setVisible(true);

		return true;
	}



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

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

		String command = e.getActionCommand();


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


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


			}

		}


		return true;
	}




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

		FileInputStream fis = null;
		InputStreamReader ir = null;
		BufferedReader br = null;

		try
		{
			fis = new FileInputStream( pathName );
			ir = new InputStreamReader(fis);
			br = new BufferedReader(ir);

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

		}
		catch( FileNotFoundException ex )
		{
			Window owner = this.mXYDataTypeSelectionWizardDialog.getOwner();
			SGUtility.showFileNotFoundMessageDialog( owner );
			return false;
		}
		finally
		{
			if( br!=null )
			{
				try
				{
					br.close();
				}
				catch( IOException ex )
				{
					
				}
			}

			if( ir!=null )
			{
				try
				{
					ir.close();
				}
				catch( IOException ex )
				{
					
				}
			}
			
			if( fis!=null )
			{
				try
				{
					fis.close();
				}
				catch( IOException ex )
				{
					
				}
			}
		}

		return true;
	}



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



	/**
	 * 
	 * @param e
	 * @return
	 */
	private boolean loadProperty( final ActionEvent e )
	{
		Object source = e.getSource();
		SGWizardDialog dg = (SGWizardDialog)source;

		String command = e.getActionCommand();


		if( source instanceof SGPropertyFileChooserWizardDialog )
		{
			this.fromPropertyFileChooserDialog( e, dg );
		}
		else if( source instanceof SGMultiDataFileChooserWizardDialog )
		{
			this.fromMultiDataFileChooser(e);
		}


		return true;
	}



	/**
	 * 
	 * @param e
	 * @param dg
	 * @return
	 */
	private boolean fromPropertyFileChooserDialog( ActionEvent e, SGWizardDialog dg )
	{
		String command = e.getActionCommand();
		Window owner = dg.getOwner();
		SGWizardDialog next = dg.getNext();
		if( ( dg instanceof SGPropertyFileChooserWizardDialog ) == false )
		{
			return false;
		}
		if( ( next instanceof SGMultiDataFileChooserWizardDialog ) == false )
		{
			return false;
		}
		SGPropertyFileChooserWizardDialog pdg = (SGPropertyFileChooserWizardDialog)dg;
		SGMultiDataFileChooserWizardDialog mdg = (SGMultiDataFileChooserWizardDialog)next;

		if( command.equals( SGWizardDialog.NEXT_BUTTON_TEXT ) )
		{
			// get file type from the selected file
			File file = pdg.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;
			}

/*			if( cList.size()==0 )
			{
				SGUtility.showMessageDialog(
					dg, ERRMSG_PROPERTY_FILE_INCORRECT, TITLE_FILE_CHECK, JOptionPane.ERROR_MESSAGE );
				return false;
			}
*/

			final int fileNum = cList.size();
			mdg.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);
			}


			// When the table model does not have any value,
			// set the new table model
			DefaultTableModel tModel = (DefaultTableModel)mdg.getTableModel();
			final int nRow = tModel.getRowCount();
			final int nColumn = tModel.getColumnCount();
			boolean b = true;
			for( int ii=0; ii<nRow; ii++ )
			{
				for( int jj=0; jj<nColumn; jj++ )
				{
					Object obj = tModel.getValueAt( ii, jj );
					if( obj!=null )
					{
						b = false;
						break;
					}
				}
			}
			if(b)
			{
				// 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 );
			
				mdg.setTableModel(model);
			}

		}


		return true;
	}



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

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

		SGMultiDataFileChooserWizardDialog mdg = (SGMultiDataFileChooserWizardDialog)dg;

		SGWizardDialog prev = mdg.getPrevious();
		if( ( prev instanceof SGPropertyFileChooserWizardDialog ) == false )
		{
			return false;
		}

		SGPropertyFileChooserWizardDialog cdg = (SGPropertyFileChooserWizardDialog)prev;


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

			String propertyFileName = cdg.getSelectedFile().getAbsolutePath();

			try
			{
				SGDrawingWindow wnd;
				if( mdg.equals( this.mMultiDataFileChooserWizardDialog ) )
				{
					wnd = this.createWindowFromPropertyFile(propertyFileName);
				}
				else if( mdg.equals( this.mStartupMultiDataFileChooserWizardDialog ) )
				{
					wnd = this.getWindow(1);
					this.createWindowFromPropertyFile( wnd, propertyFileName );
				}
				else
				{
					return false;
				}

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

		}

		return true;
	}




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

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

		String command = e.getActionCommand();


		//
		// from start-up wizard
		//

		if( source.equals( this.mStartupUsePropertyDialog ) )
		{
			if( command.equals( SGStartupUsePropertyDialog.USE_PROPERTY_FILE ) )
			{
				return this.setStartupWizardUseProperty(true);
			}
			else if( command.equals( SGStartupUsePropertyDialog.NOT_USE_PROPERTY_FILE ) )
			{
				return this.setStartupWizardUseProperty(false);
			}
		}

		// Load Property
		if( source.equals( this.mStartupPropertyFileChooserDialog )
			|| source.equals( this.mStartupMultiDataFileChooserWizardDialog ) )
		{
			return this.loadProperty(e);
		}



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

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

		//
		// from the tool bar
		//

		// New Graph
		if( source.equals( this.mFigureIDSelectionWizardDialog )
			|| source.equals( this.mSingleDataFileChooserWizardDilaog )
			|| source.equals( this.mXYDataTypeSelectionWizardDialog ) )
		{
			return this.addDataByToolBar(e);
		}

		// Load Property
		if( source.equals( this.mPropertyFileChooserWizardDilaog )
			|| source.equals( this.mMultiDataFileChooserWizardDialog ) )
		{
			return this.loadProperty(e);
		}

		return true;
	}



	/**
	 * 
	 */
	private boolean fromUpgradeDialog( final ActionEvent e )
	{
		Object source = e.getSource();
		String command = e.getActionCommand();

		int type;
		if( command.equals( SGDialog.OK_BUTTON_TEXT ) )
		{
			String cycle = this.mUpgradeDialog.getUpgradeCycle();

			if( cycle.equals( SGUpgradeDialog.NO_UPGRADE ) )
			{
				type = Connect.NO_UPGRADE;
			}
			else if( cycle.equals( SGUpgradeDialog.EVERY_TIME ) )
			{
				type = Connect.UPGRADE_EVERY_TIME;
			}
			else if( cycle.equals( SGUpgradeDialog.EVERY_DAY ) )
			{
				type = Connect.UPGRADE_EVERY_DAY;
			}
			else if( cycle.equals( SGUpgradeDialog.EVERY_WEEK ) )
			{
				type = Connect.UPGRADE_EVERY_WEEK;
			}
			else if( cycle.equals( SGUpgradeDialog.EVERY_MONTH ) )
			{
				type = Connect.UPGRADE_EVERY_MONTH;
			}
			else
			{
				throw new Error();
			}

			// update the upgrade cycle
			Preferences pref = Preferences.userNodeForPackage( this.getClass() );
			pref.putInt( PREF_KEY_UPGRADE_CYCLE, type );

		}
		else if( command.equals( SGUpgradeDialog.UPGRADE_NOW ) )
		{
			SGUpgradeDialog dg = (SGUpgradeDialog)source;
			if( this.upgradeByCommand(dg) == false )
			{
				return false;
			}
		}

		return true;
	}


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

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


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

	}




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



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


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

	}



	/**
	 * 
	 */
	public void windowClosing( final WindowEvent e )
	{
		Object source = e.getSource();

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

			if( this.mWndMap.size() == 0 )
			{
				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 )
	{
		dtde.acceptDrag(DnDConstants.ACTION_COPY_OR_MOVE);
	}



	/**
	 * 
	 */
	public void dragExit( final DropTargetEvent dte )
	{
	}



	/**
	 * 
	 */
	public void dragOver( final DropTargetDragEvent dtde )
	{
	}



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

		DropTarget tg = (DropTarget)dtde.getSource();
		Component com = tg.getComponent();

		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 );

				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()
		{
			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 );

			wnd.getContentPane().repaint();

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



	/**
	 * 
	 */
	public void dropActionChanged( final DropTargetDragEvent dtde )
	{
	}




	/**
	 * 
	 */
	private boolean addDataByDragAndDrop(
		final int x, final int y,
		final SGDrawingWindow wnd, final ArrayList fileList )
	{

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

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

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


		// 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();

wnd.notifyToRoot();


		// フィギュアにデータを追加
		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.drawBackFigure( figure );


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


		// show the window
		wnd.setVisible(true);


		return figure;

	}



	/**
	 * 
	 */
	private SGStartupWelcomeDialog mStartupWelcomeDialog;


	/**
	 * 
	 */
	private SGStartupUsePropertyDialog mStartupUsePropertyDialog;


	/**
	 * 
	 */
	private SGPropertyFileChooserWizardDialog mStartupPropertyFileChooserDialog;


	/**
	 * 
	 */
	private SGMultiDataFileChooserWizardDialog mStartupMultiDataFileChooserWizardDialog;


	/**
	 * 
	 */
	private SGSingleDataFileChooserWizardDialog mStartupSingleDataFileChooserWizardDialog;


	/**
	 * 
	 */
	private SGXYDataTypeSelectionWizardDialog mStartupXYDataTypeSelectionDialog;


	/**
	 * 
	 */
	private SGStartupFigurePropertySettingDialog mStartupFigurePropertySettingDialog;



	/**
	 * 
	 * @return
	 */
	private SGWizardDialog createStartupWizardDialogs( final SGDrawingWindow wnd )
	{
/*
		// create the welcome dialog
		SGStartupWelcomeDialog wdg = new SGStartupWelcomeDialog( wnd, true );
		this.mStartupWelcomeDialog = wdg;
		wdg.addActionListener( this );
		wdg.getPreviousButton().setVisible(false);
		wdg.getOKButton().setVisible(false);
		wdg.pack();
*/

		// create the dialog to ask to the users whether to use property file
		SGStartupUsePropertyDialog updg
			= new SGStartupUsePropertyDialog( wnd, true );
		this.mStartupUsePropertyDialog = updg;
		updg.addActionListener( this );
		updg.getOKButton().setVisible(false);
updg.getPreviousButton().setVisible(false);
		updg.pack();


		// create the dialog to choose property file
		SGPropertyFileChooserWizardDialog pdg
			= new SGPropertyFileChooserWizardDialog( wnd, true );
		this.mStartupPropertyFileChooserDialog = pdg;
		pdg.addActionListener( this );
		pdg.getOKButton().setVisible(false);
		pdg.pack();


		// create the dialog to choose multiple data files
		SGMultiDataFileChooserWizardDialog mdcdg
			= new SGMultiDataFileChooserWizardDialog( wnd, true );
		this.mStartupMultiDataFileChooserWizardDialog = mdcdg;
		mdcdg.addActionListener( this );
		mdcdg.getNextButton().setVisible(false);
		mdcdg.pack();


		// create the dialog to choose single data files
		SGSingleDataFileChooserWizardDialog dcdg
			= new SGSingleDataFileChooserWizardDialog( wnd, true );
		this.mStartupSingleDataFileChooserWizardDialog = dcdg;
		dcdg.addActionListener( this );
		dcdg.getOKButton().setVisible(false);
		dcdg.pack();


		// create the dialog to select the data type
		SGXYDataTypeSelectionWizardDialog dtsdg
			= new SGXYDataTypeSelectionWizardDialog( wnd, true );
		this.mStartupXYDataTypeSelectionDialog = dtsdg;
		dtsdg.addActionListener( this );


		// create the dialog to set the figure properties
		SGStartupFigurePropertySettingDialog fpsdg
			= new SGStartupFigurePropertySettingDialog( wnd, true );
		this.mStartupFigurePropertySettingDialog = fpsdg;
		fpsdg.addActionListener( this );
		this.setFigureDialogProperties();


		SGWizardDialog first = updg;


		// set the location of the first wizard dialog
		first.setCenter(wnd);


		//
		// set the next and previous dialog
		//

//		wdg.setNext( updg );
//		updg.setPrevious( wdg );


		final boolean usePropertyFile = false;
		this.mStartupUsePropertyDialog.setUsePropertyFile( usePropertyFile );
		this.setStartupWizardUseProperty( usePropertyFile );


		return first;
	}



	/**
	 * 
	 * @param b
	 * @return
	 */
	private boolean setStartupWizardUseProperty( final boolean b )
	{

		SGStartupUsePropertyDialog updg = this.mStartupUsePropertyDialog;
		SGPropertyFileChooserWizardDialog pdg = this.mStartupPropertyFileChooserDialog;
		SGMultiDataFileChooserWizardDialog mdcdg = this.mStartupMultiDataFileChooserWizardDialog;
		SGSingleDataFileChooserWizardDialog dcdg = this.mStartupSingleDataFileChooserWizardDialog;
		SGXYDataTypeSelectionWizardDialog dtsdg = this.mStartupXYDataTypeSelectionDialog;
		SGStartupFigurePropertySettingDialog fpsdg = this.mStartupFigurePropertySettingDialog;


		if( b )
		{
			// Use property files

			updg.setNext( pdg );

			pdg.setPrevious( updg );
			pdg.setNext( mdcdg );

			mdcdg.setPrevious( pdg );

		}
		else
		{
			// Not use property files
			updg.setNext( dcdg );

			dcdg.setPrevious( updg );
			dcdg.setNext( dtsdg );

			dtsdg.setPrevious( dcdg );
			dtsdg.setNext( fpsdg );

			fpsdg.setPrevious( dtsdg );
		}

		return true;
	}



	/**
	 * 
	 * @param wnd
	 * @return
	 */
	private SGSplashWindow createSplashWindow()
	{
		// set the image and the text
		Class inClass = getClass();
		String name = SGIConstants.RESOURCES_DIRNAME+"Splash.png";
		URL url = inClass.getResource(name);
		Image image = Toolkit.getDefaultToolkit().getImage( url );
		SGSplashWindow sw = new SGSplashWindow( image );

		return sw;
	}



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

		final SGStartupFigurePropertySettingDialog dg
			= (SGStartupFigurePropertySettingDialog)this.mStartupFigurePropertySettingDialog;

		// SGFigure
		dg.setFigureX( 0.0f );
		dg.setFigureY( 0.0f );
		final float width = SGDefaultValues.DEFAULT_FIGURE_WIDTH*SGIConstants.CM_POINT_RATIO;
		dg.setFigureWidth( width );
		dg.setFigureHeight( width/SGIConstants.GOLDEN_RATIO );

		dg.setFigureBackgroundColor( SGDefaultValues.FIGURE_BACKGROUND_COLOR );

		dg.setFigureTransparentFlag( false );

		dg.setFigureSpaceLineAndNumber( SGDefaultValues.SPACE_AXIS_LINE_AND_NUMBER*SGIConstants.CM_POINT_RATIO );
		dg.setFigureSpaceNumberAndTitle( SGDefaultValues.SPACE_NUMBER_AND_TITLE*SGIConstants.CM_POINT_RATIO );

		// SGILegendElement
		dg.setFigureLegendVisible( true );

		return true;
	}



}



}

