///////////////////////////////////////////////////////////////////////////////
//                      TGEライブラリー (TGE.dll)
//                     Copyright (c) 2026 by Ysama
//
//                               【概要】
//LOGOベースの描画命令を纏めた「命令セット（TGSet）」、その一覧である「命令リス
//ト（TGList）」、「命令リスト」から指定した命令セットで、繰り返しを含め実行順を
//定める「実行リスト（TGList）」及び編集ダイアログをまとめたNakov.TurtleGraphics
//の命令編集ライブラリー
///////////////////////////////////////////////////////////////////////////////
using System;
using System.Windows.Forms;
using System.Drawing;
using System.Collections;
using System.Collections.Generic;		//Listを使う為
using System.IO;						//FIle関係
using System.Text;  					//Encoding.GetEncoding を使用するのに必要
using Nakov.TurtleGraphics;				//TurtleGraphicsを使う為

namespace TGE
{
	/////////////////////////////////////////////
	//TurtleGraphics命令を編集するラッパークラス
	/////////////////////////////////////////////
	public class TGEdit
	{
		//クラスフィールド
		public TGSet CmdSet;			//命令セット（{コマンド番号, 引数}の整数配列 ）
		public TGList CmdList;			//命令リスト（命令セットの一覧）
		public TGList ExeList;			//実行リスト（指定する命令セットの実行順リスト）

		//コンストラクター
		public TGEdit(Form form = null)
		{
			if(form == null)
				Turtle.Init();
			else
				Turtle.Init(form);
			CmdSet = new TGSet();
			CmdList = new TGList();
			ExeList = new TGList();
		}

		//TurtleGraphicsのDispose/Reset
		public void Reset()
		{
			Turtle.Reset();
		}

		//亀の表示／非表示を確認する
		public bool IsTurtleShown()
		{
			return Turtle.ShowTurtle;
		}

		//亀を表示／非表示する
		public void ShowTurtle(bool flag)
		{
			Turtle.ShowTurtle = flag;
		}
	}

	///////////////////////////////////////////
	//命令リストクラス－命令セットの集合クラス
	///////////////////////////////////////////
	public class TGList
	{
		//クラスメンバー
		List<TGSet> CmdList;
		public string FileName {get; set;}		//ファイル入出力名

		//コンストラクター
		public TGList()
		{
			CmdList = new List<TGSet>();
			FileName = String.Empty;
		}

		//コピーコンストラクター
		public TGList(TGList tgl)
		{
			CmdList = new List<TGSet>(tgl.CmdList);
			FileName = tgl.FileName;
		}

		//TGListの初期化
		public void Clear()
		{
			CmdList.Clear();
			FileName = String.Empty;
		}

		//TGListの命令セット数
		public int CountSets()
		{
			return CmdList.Count;
		}

		//n番目の命令セットを取得
		public TGSet GetSet(int n)
		{
			if(n < 0 || n > CmdList.Count - 1)
				return new TGSet();				//空のTGSetを返す
			return CmdList[n];
		}

		//TGListへのTGSetの追加
		public void AddSet(TGSet tgs)
		{
			CmdList.Add(new TGSet(tgs));		//Deep copy
		}

		//n番目の命令セットの削除
		public bool RemoveAt(int n)
		{
			if(n < 0 || n > CmdList.Count - 1)
				return false;
			else
				CmdList.RemoveAt(n);
			return true;
		}

		//n番目に命令セットを挿入
		public bool InsertSet(int n, TGSet tgs)
		{
			if(n < 0 || n > CmdList.Count - 1)	//最後尾に追加するにはAddを使う
				return false;
			else
				CmdList.Insert(n, tgs);
			return true;
		}

		//CmdListへTGSetを介して命令セット入力
		public bool ReadList(string data)
		{
			//入力用TGSet
			TGSet tgs = new TGSet();
			//文字列の行分割
			string[] lines = data.Split(new[]{"\r\n","\n","\r"}, StringSplitOptions.None);
			//行の語分割と整数配列の作成
			bool Is1stTime = true;			//最初の命令セットの’-1'か否かのフラグ
			foreach(string line in lines)
			{
				if(line == String.Empty)	//（有る筈のない）空行に遭遇したら中止する
					break;
				string[] dt = line.Split(',');
				if(dt[0] == "Name:")		//命令セットデータの最終行は"Name:,(Name),(Description)"とする
				{
					tgs.Name = dt[1];
					tgs.Description = dt[2];
					continue;				//次行へスキップ
				}
				int cmd = 0, arg1 = 0, arg2 = 0, arg3 = 0;	//入力結果
				if(!int.TryParse(dt[0], out cmd))
					return false;
				else
				{
					if(cmd == -1)			//命令'-1'はセット開始（先行セット終了、セットの区切り）
					{
						if(!Is1stTime)		//最初の-1で先行セットがなければAddSet()は不要
							AddSet(tgs);	//CmdListに今迄の命令セットを登録
						else
							Is1stTime = false;
						tgs.Clear();		//次の命令セットの為に入力用tgsを初期化する
					}
				}
				if(!int.TryParse(dt[1], out arg1))
					return false;
				if(!int.TryParse(dt[2], out arg2))
					return false;
				if(!int.TryParse(dt[3], out arg3))
					return false;
				tgs.AddCmd(cmd, arg1, arg2, arg3);
			}
			AddSet(tgs);					//最後の命令セットを登録
			return true;
		}

		//CmdListの命令セットの一覧出力
		public string WriteList()
		{
			string str = String.Empty;
			foreach(TGSet tgs in CmdList)
			{
				str += tgs.WriteSet();
			}
			return str;
		}

		//CmdListの命令セットの実行
		public void DoSet()
		{
			foreach(TGSet tgs in CmdList)
			{
				tgs.DoThis();
			}
		}

		///////////////////////////////////////////////////////////////////////////////////////
		// >>> "*.tge"のファイルについて <<<
		//(1) LOGOベースのTurtleGraphicsの命令に対応した命令番号と引数一つのテキストcsvファイル
		//(2) 命令'-1'はセット開始（先行セット終了、セットの区切り）で引数は繰り返し回数
		//(3) 命令セットデータの最終行は"Name:,(Name),(Description)"とする
		///////////////////////////////////////////////////////////////////////////////////////
		//tgdファイル書き込み（UTF-8：Encoding.UTF8）
		public bool WriteFile()
		{
			if(FileName == String.Empty)
				return false;
			using(StreamWriter file = new StreamWriter(FileName, false, Encoding.UTF8))
			{
				//ファイルを書く
				file.Write(WriteList());
				//ファイルを閉じる
				file.Close();
			}
			return true;
		}

		//tgdファイル読み込み（UTF-8：Encoding.UTF8）
		public bool ReadFile()
		{
			if(FileName == String.Empty)
				return false;
			string data = String.Empty;
			try
			{
				using(StreamReader file = new StreamReader(FileName, Encoding.UTF8))
				{
					data = file.ReadToEnd();
					// ファイルを閉じる
					file.Close();
				}
			}
			catch(Exception e)	//FileNotFoundException e
			{
				//Debug用
				//MessageBox.Show("エラーコード：" + e.ToString(), "初期化ファイル読み込みエラー", MessageBoxButtons.OK, MessageBoxIcon.Error);
				MessageBox.Show("ファイルを読み込めませんでした。\r\n。エラーコード：" + e.ToString(), "確認", MessageBoxButtons.OK, MessageBoxIcon.Information);
				return false;
			}
			return ReadList(data);
		}
	}

	/////////////////////////////////////////////////
	//命令セットクラス（名称と説明付きの命令セット）
	/////////////////////////////////////////////////
	public class TGSet
	{	//クラスメンバー
		List<int[]> CmdSet;						//命令配列
		public string Name {get; set;}			//命令セット名
		public string Description {get; set;}	//説明

		//コンストラクター１
		public TGSet()
		{
			CmdSet = new List<int[]>();
			Name = String.Empty;
			Description = String.Empty;
		}

		//コンストラクター１
		public TGSet(string name, string description)
		{
			CmdSet = new List<int[]>();
			Name = name;						//再設定自由
			Description = description;			//再設定自由
		}

		//コピーコンストラクター
		public TGSet(TGSet copy)
		{
			CmdSet = new List<int[]>(copy.CmdSet);
			Name = copy.Name;
			Description = copy.Description;
		}

		//初期化
		public void Clear()
		{
			CmdSet.Clear();
			Name = String.Empty;
			Description = String.Empty;
		}

		//命令セットの命令数
		public int Count()
		{
			return CmdSet.Count;
		}

		//命令セットの設定（１）
		public void Set(TGSet tgs)
		{
			CmdSet.Clear();
			CmdSet = new List<int[]>(tgs.CmdSet);
			Name = tgs.Name;
			Description = tgs.Description;
		}

		//命令セットの設定（２）
		public void Set(List<int[]> list, string name, string description)
		{
			CmdSet.Clear();
			CmdSet = new List<int[]>(list);
			Name = name;
			Description = description;
		}

		//n番目の命令取得
		public int[] GetCmd(int n)
		{
			if(n < 0 || n > CmdSet.Count - 1)
				return new int[] {-1, -1, -1, -1};			//エラー
			else
				return CmdSet[n];
		}

		//n番目の命令設定（１）（命令番号cmdは必須、定数引数arg1は重要、arg2とarg3はオプション扱い）
		public bool SetCmd(int n, int cmd, int arg1, int arg2 = 0, int arg3 = 0)
		{
			if(n < 0 || n > CmdSet.Count - 1)
				return false;
			CmdSet[n] = new int[] {cmd, arg1, arg2, arg3};	//Deep copy
			return true;
		}

		//n番目の命令設定（２）
		public bool SetCmd(int n, int[] cmd)
		{
			if(n < 0 || n > CmdSet.Count - 1 || cmd.Length != 4)
				return false;
			CmdSet[n] = cmd;
			return true;
		}

		//命令の追加（命令番号cmdは必須、定数引数arg1は重要、arg2とarg3はオプション扱い）
		public void AddCmd(int cmd, int arg1, int arg2 = 0, int arg3 = 0)
		{
			CmdSet.Add(new int[] {cmd, arg1, arg2, arg3});	//Deep copy
		}

		//命令の追加（配列渡し）
		public bool AddCmd(int[] cmdarr)
		{
			if(cmdarr.Length != 4)
				return false;
			else
			{
				CmdSet.Add((int[])cmdarr.Clone());			//Deep copy
				return true;
			}
		}

		//命令の削除
		public bool RemoveAt(int n)
		{
			if(n < 0 || n > CmdSet.Count - 1)
				return false;
			else
				CmdSet.RemoveAt(n);
			return true;
		}

		//n番目に命令を挿入（命令番号cmdは必須、定数引数arg1は重要、arg2とarg3はオプション扱い）
		public bool Insert(int n, int cmd, int arg1, int arg2 = 0, int arg3 = 0)
		{
			if(n < 0 || n > CmdSet.Count - 1)				//最後尾に追加するにはAddを使う
				return false;
			else
				CmdSet.Insert(n, new int[] {cmd, arg1, arg2, arg3});
			return true;
		}

		//n番目に命令を挿入（配列渡し）
		public bool Insert(int n, int[] cmdarr)
		{
			if(n < 0 || n > CmdSet.Count - 1)				//最後尾に追加するにはAddを使う
				return false;
			else
				CmdSet.Insert(n, (int[])cmdarr.Clone());
			return true;
		}

		//命令の一覧出力
		public string WriteSet()
		{
			string str = String.Empty;
			foreach(int[] array in CmdSet)
			{
				//str += array[0].ToString() + "," + array[1].ToString() + ","
				//	+ array[2].ToString() + "," + array[3].ToString() + Environment.NewLine;
				str += string.Join(",", array) + Environment.NewLine;
			}
			str += "Name:" + "," + Name + "," + Description + Environment.NewLine;
			return str;
		}

		//命令（int[4]－コマンド番号、引数1、引数2、引数3）の実行
		public void DoThis()
		{
			int times = 1;
			for(int i = 0; i < times; i++)	//最低でも規定値1回は実行
			{	//cmdは命令（cmd[0]）と引数（cmd[1～3]）の整数配列
				foreach(int[] cmd in CmdSet)
				{	//引数cmd[1]は定数、cmd[2]は回数の倍数、cmd[3]は回数による分数（ともに規定値は0）
					switch(cmd[0])			//引数cmd[0]は命令番号
					{
						case -1:			//命令セット開始
							times = cmd[1];	//引数は繰り返し回数
							cmd[0] = 0;		//繰り返しの為にNOPにする
							break;
						case 0:				//NOP - No OPeration
							break;
						case 1:				//Forward(arg)
							Turtle.Forward(cmd[1] + cmd[2] * i + cmd[3] / (times - i));
							break;
						case 2:				//Backward(arg)
							Turtle.Backward(cmd[1] + cmd[2] * i + cmd[3] / (times - i));
							break;
						case 3:				//MoveTo(arg1, arg2)
							int x = cmd[1] + cmd[3] * i;	//arg1（cmd[3]のループ倍数が加算）
							int y = cmd[2] + cmd[3] * i;	//arg2（cmd[3]のループ倍数が加算）
							Turtle.MoveTo(x, y);
							break;
						case 4:				//Rotate(arg)
							Turtle.Rotate(cmd[1] + cmd[2] * i + cmd[3] / (times - i));
							break;
						case 5:				//RotateTo(arg)
							Turtle.RotateTo(cmd[1] + cmd[2] * i + cmd[3] / (times - i));
							break;
						case 6:				//PenUp()
							Turtle.PenUp();
							break;
						case 7:				//PenDown()
							Turtle.PenDown();
							break;
						case 8:				//X
							Turtle.X = cmd[1] + cmd[2] * i + cmd[3] / (times - i);
							break;
						case 9:				//Y
							Turtle.Y = cmd[1] + cmd[2] * i + cmd[3] / (times - i);
							break;
						case 10:			//Angle
							Turtle.Angle = cmd[1] + cmd[2] * i + cmd[3] / (times - i);
							break;
						case 11:			//PenColor（Color構造体←整数の変換）
							Turtle.PenColor = Color.FromArgb(cmd[1] + cmd[2] * i + cmd[3] / (times - i));
							break;
						case 12:			//PenSize
							Turtle.PenSize = cmd[1];
							break;
						case 13:			//PenVisible (1 - true, 0 - false)
							Turtle.PenVisible = (cmd[1] == 1);
							break;
						case 14:			//Delay
							Turtle.Delay = cmd[1];
							break;
						default:
							break;
					}
				}
			}
			CmdSet[0][0] = -1;				//配列は参照引き渡しの為、値-1に復旧する
		}
	}

	////////////////////
	//CmdListダイアログ
	////////////////////
	public class CmdListDlg : Form
	{
		public int Selection {get; private set;}	//戻り値
		//クラスメンバーフィールド
		int ListType;								//リストタイプ（0－単純選択、1－CmdList、2－ExeList）
		TGEdit Tge;									//TGEditクラス
		TGList Tgl;									//TGListクラス
		Button Btn_Add;								//命令追加ボタン
		Button Btn_Del;								//命令削除ボタン
		Button Btn_Init;							//初期化ボタン
		Button Btn_OK;								//OKボタン
		Button Btn_Cancel;							//Cancelボタン
		ListView listView;							//リストビュー

		//コンストラクター
		public CmdListDlg(TGEdit tge, int type = 0)
		{
			ListType = (type < 0 || type > 2) ? 1 : type;	//規定値はCmdList
			Tge = tge;										//参照渡し
			switch(ListType)
			{	//リストタイプによるタイトルとデータソースの決定
				case 0:		//値渡しによる選択
					this.Text = "命令セット選択";
					Tgl = new TGList(Tge.CmdList);
					break;
				case 1:		//参照渡しによる直接編集
					this.Text = "命令セットライブラリー";
					Tgl = Tge.CmdList;
					break;
				case 2:		//参照渡しによる直接編集
					this.Text = "実行命令セット一覧";
					Tgl = Tge.ExeList;
					break;
			}
			this.ShowIcon = false;
			this.ClientSize = new Size(640, 320);
			this.MinimumSize = new Size(480, 240);
			this.BackColor = SystemColors.Window;
			this.Load += new EventHandler(CmdListDlg_OnLoad);
		}

		//OnLoad時処理
		protected void CmdListDlg_OnLoad(object sender, EventArgs e)
		{
			Btn_Add = new Button();
			Btn_Add.Text = "命令セット追加";
			Btn_Add.TextAlign = ContentAlignment.MiddleCenter;
			Btn_Add.Font = new Font("ＭＳ 明朝", 8);
			Btn_Add.ForeColor = Color.Black;
			Btn_Add.Size = new Size(100, 28);
			Btn_Add.BackColor = SystemColors.Control;
			Btn_Add.Location = new Point(ClientSize.Width - Btn_Add.Width - 10, 10);
			Btn_Add.Anchor = (AnchorStyles.Top | AnchorStyles.Right);
			Btn_Add.Click += new EventHandler(OnClick_Add);
			Btn_Add.Visible = (ListType == 0) ? false : true;

			Btn_Del = new Button();
			Btn_Del.Text = "命令セット削除";
			Btn_Del.TextAlign = ContentAlignment.MiddleCenter;
			Btn_Del.Font = new Font("ＭＳ 明朝", 8);
			Btn_Del.ForeColor = Color.Black;
			Btn_Del.Size = new Size(100, 28);
			Btn_Del.BackColor = SystemColors.Control;
			Btn_Del.Location = new Point(ClientSize.Width - Btn_Del.Width - 10, 20 + Btn_Add.Height);
			Btn_Del.Anchor = (AnchorStyles.Top | AnchorStyles.Right);
			Btn_Del.Click += new EventHandler(OnClick_Del);
			Btn_Del.Visible = (ListType == 0) ? false : true;

			Btn_Init = new Button();
			Btn_Init.Text = "命令リスト初期化";
			Btn_Init.TextAlign = ContentAlignment.MiddleCenter;
			Btn_Init.Font = new Font("ＭＳ 明朝", 8);
			Btn_Init.ForeColor = Color.Black;
			Btn_Init.Size = new Size(100, 28);
			Btn_Init.BackColor = SystemColors.Control;
			Btn_Init.Location = new Point(ClientSize.Width - Btn_Init.Width - 10, 30 + Btn_Add.Height + Btn_Del.Height);
			Btn_Init.Anchor = (AnchorStyles.Top | AnchorStyles.Right);
			Btn_Init.Click += new EventHandler(OnClick_Init);
			Btn_Init.Visible = (ListType == 0) ? false : true;

			Btn_OK = new Button();
			Btn_OK.Text = "OK";
			Btn_OK.TextAlign = ContentAlignment.MiddleCenter;
			Btn_OK.Font = new Font("ＭＳ 明朝", 8);
			Btn_OK.ForeColor = Color.Black;
			Btn_OK.Size = new Size(100, 28);
			Btn_OK.BackColor = SystemColors.Control;
			Btn_OK.Location = new Point(ClientSize.Width - Btn_OK.Width - 10, ClientSize.Height - Btn_OK.Height - 10);
			Btn_OK.Anchor = (AnchorStyles.Bottom | AnchorStyles.Right);
			Btn_OK.Click += new EventHandler(OnClick_OK);

			Btn_Cancel = new Button();
			Btn_Cancel.Text = "Cancel";
			Btn_Cancel.TextAlign = ContentAlignment.MiddleCenter;
			Btn_Cancel.Font = new Font("ＭＳ 明朝", 8);
			Btn_Cancel.ForeColor = Color.Black;
			Btn_Cancel.Size = new Size(100, 28);
			Btn_Cancel.BackColor = SystemColors.Control;
			Btn_Cancel.Location = new Point(ClientSize.Width - Btn_Cancel.Width - 10, ClientSize.Height - Btn_Cancel.Height - Btn_OK.Height - 20);
			Btn_Cancel.Anchor = (AnchorStyles.Bottom | AnchorStyles.Right);
			Btn_Cancel.Click += new EventHandler(OnClick_Cancel);

			this.Controls.Add(Btn_Add);
			this.Controls.Add(Btn_Del);
			this.Controls.Add(Btn_Init);
			this.Controls.Add(Btn_Cancel);
			this.Controls.Add(Btn_OK);

			//リストビュー
			listView = new ListView();
			listView.BorderStyle = BorderStyle.Fixed3D;					//境界
			listView.Location = new Point(10, 10);						//位置
			listView.Width = ClientSize.Width - Btn_Add.Width - 30;		//サイズ
			listView.Height = ClientSize.Height - 20;
			listView.Anchor = (AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Bottom | AnchorStyles.Right);	//アンカー固定
			listView.FullRowSelect = true;								//一行選択
			listView.MultiSelect = true;								//複数選択を許す
			listView.GridLines = true;									//グリッドラインの表示
			listView.HoverSelection = false;							//ポイントで選択できるようにする
			listView.Activation = ItemActivation.OneClick;				//シングルクリック選択;
			listView.CheckBoxes = false;								//チェックボックス無効化
			listView.View = View.Details;								//リストビューの表示方法
			listView.AllowDrop = false;									//listViewへのドロップを受け入れない
			//イベントハンドラの追加
			listView.MouseDoubleClick+= new MouseEventHandler(ListView_DoubleClick);
			if(ListType == 1)	//CmdListの場合
			{
				listView.ColumnClick += new ColumnClickEventHandler(ListView_ColumnClick);
			}
			//ヘッダー定義
			ColumnHeader columnIndex = new ColumnHeader{Text = "Index", Width = 40};
			ColumnHeader columnCmdName = new ColumnHeader{Text = "命令セット名", Width = 100};
			ColumnHeader columnDescription = new ColumnHeader{Text = "説明", Width = 366};
			ColumnHeader[] colHeaderRegValue = {columnIndex, columnCmdName, columnDescription};	//ヘッダー設定
			listView.Columns.AddRange(colHeaderRegValue);	//ヘッダー追加
			//Tglに値がある場合リストビューに読み込む
			int n = Tgl.CountSets();
			if(n > 0)
			{
				for(int i = 0; i < n; i++)
				{
					string[] item = {i.ToString(), Tgl.GetSet(i).Name, Tgl.GetSet(i).Description};
					listView.Items.Add(new ListViewItem(item));
				}
			}
			//FormにListViewを追加
			this.Controls.Add(listView);
		}

		//終了時処理
		protected override void OnFormClosing(FormClosingEventArgs e)
		{
			base.OnFormClosing(e);
			DialogResult dr = MessageBox.Show("「" + this.Text + "」" + "を終了しますか？", "確認", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
			if(dr == DialogResult.No)
			{
				e.Cancel = true;
			}
		}

		//Addボタンがクリックされた時
		protected void OnClick_Add(object sender, EventArgs e)
		{
			if(ListType == 1)		//CmdListの場合
			{
				//CmdSetDlgによる命令セットの作成
				CmdSetDlg csd = new CmdSetDlg();	//引数無し（新規作成）
				if(csd.ShowDialog(this) == DialogResult.OK)
				{
					listView.BeginUpdate();			//描画停止
					Tgl.AddSet(csd.Tgs);
					int last_one = Tgl.CountSets() - 1;	//Tgl最後のTGSet == 最新の命令セット
					string[] item = {last_one.ToString(), Tgl.GetSet(last_one).Name, Tgl.GetSet(last_one).Description};
					listView.Items.Add(new ListViewItem(item));
					listView.EndUpdate();			//描画再開
				}
				csd.Dispose();
			}
			else if(ListType == 2)	//ExeListの場合
			{
				//CmdListDlgによる単純選択
				CmdListDlg cld = new CmdListDlg(Tge, 0);
				if(cld.ShowDialog(this) == DialogResult.OK)
				{
					listView.BeginUpdate();			//描画停止
					Tgl.AddSet(Tge.CmdList.GetSet(cld.Selection));	//TgeのCmdListからDeep copyを追加する
					int last_one = Tgl.CountSets() - 1;	//Tgl最後のTGSet == 最新の命令セット
					string[] item = {last_one.ToString(), Tgl.GetSet(last_one).Name, Tgl.GetSet(last_one).Description};
					listView.Items.Add(new ListViewItem(item));
					listView.EndUpdate();			//描画再開
				}
				cld.Dispose();
			}
		}

		//Delボタンがクリックされた時
		protected void OnClick_Del(object sender, EventArgs e)
		{
			//選択された行を確認する
			if(listView.SelectedItems.Count == 0)
				MessageBox.Show("データが選択されていません", "エラー", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
			//選択があり、CmdList、ExeListの直接編集であるので
			else if(ListType > 0)
			{
				DialogResult dr = MessageBox.Show("命令リストのソースデータが失われます。\r\n本当によろしいですか？", "確認",
									MessageBoxButtons.YesNo, MessageBoxIcon.Question);
				if(dr == DialogResult.Yes)
				{
					int selected_index = listView.SelectedIndices[0];
					listView.Items.RemoveAt(selected_index);
					Tgl.RemoveAt(selected_index);
				}
			}
		}

		//Initボタンがクリックされた時
		protected void OnClick_Init(object sender, EventArgs e)
		{
			if(ListType == 1)		//tge.CmdList（命令セットライブラリー）→システム使用命令リスト
			{
				MessageBox.Show("命令リストライブラリーの消去はできません。", "禁止事項", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
			}
			else if(ListType == 2)	//tge.ExeList（実行命令セット）→個別ユーザーリスト
			{
				DialogResult dr = MessageBox.Show("命令リストのソースデータが失われます。\r\n本当によろしいですか？", "確認",
									MessageBoxButtons.YesNo, MessageBoxIcon.Question);
				if(dr == DialogResult.Yes)
				{
					listView.Items.Clear();
					Tgl.Clear();
				}
			}
		}

		//OKボタンがクリックされた時
		protected void OnClick_OK(object sender, EventArgs e)
		{
			//ListTypeが1、2の場合、CmdListまたはExeListを直接編集するので戻り値は無い
			if(ListType == 0)	//単純選択の場合のみ、Tgs（TGSet）を返す
			{
				//選択された行を確認する
				if(listView.SelectedItems.Count == 0)
				{
					MessageBox.Show("データが選択されていません", "エラー", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
					return;
				}
				else
				{
					Selection = listView.SelectedIndices[0];	//CmdListのSelection番目のTGSet
				}
			}
			//このフォームの戻り値
			DialogResult = DialogResult.OK;
			Close();
		}

		//Cancelボタンがクリックされた時
		protected void OnClick_Cancel(object sender, EventArgs e)
		{
			Selection = -1;		//未選択
			//このフォームの戻り値
			DialogResult = DialogResult.Cancel;
			Close();
		}

		//listViewがダブルクリックされた時
		protected void ListView_DoubleClick(object sender, MouseEventArgs e)
		{
			//選択された項目があるか確認
			if(listView.SelectedIndices.Count > 0)
			{
				Selection = listView.SelectedIndices[0];
				if(ListType == 0)		//命令セット選択
				{
					DialogResult = DialogResult.OK;
					Close();			//Selection設定のみで終了
				}
				else if(ListType == 1 || ListType == 2)	//命令セットライブラリー（CmdList）又は実行リスト一覧（ExeList）
				{
					TGSet copy = new TGSet(Tgl.GetSet(Selection));	//編集用データは直接変更されないようにコピーを渡す
					CmdSetDlg csd = new CmdSetDlg(copy);			//データコピーを使って編集
					if(csd.ShowDialog(this) == DialogResult.OK)		//編集結果がOKなら
					{
						Tgl.GetSet(Selection).Set(csd.Tgs);			//編集結果をオリジナル命令セットに代入する
						listView.SelectedItems[0].Text = Selection.ToString();
						listView.SelectedItems[0].SubItems[1].Text = csd.Tgs.Name;
						listView.SelectedItems[0].SubItems[2].Text = csd.Tgs.Description;
						MessageBox.Show(Selection.ToString() + "番目の命令セットを編集しました。", "確認", MessageBoxButtons.OK, MessageBoxIcon.Information);
					}
					csd.Dispose();
				}
			}
		}

		//listViewのコラムがクリックされた時
		private void ListView_ColumnClick(object sender, ColumnClickEventArgs e)
		{
			//ListViewItemSorterを指定する
			listView.ListViewItemSorter = new ListViewItemComparer(e.Column);
			//並び替える（ListViewItemSorterを設定するとSortが自動的に呼び出される）
		}
	}


	///////////////////////////////////////////
	//ListViewの項目の並び替えに使用するクラス
	///////////////////////////////////////////
	public class ListViewItemComparer : IComparer
	{
		private int m_column;
		private static int m_order = 1;	//毎回呼ばれるたびに正順、逆順を交代させるフラグ

		//ListViewItemComparerクラスのコンストラクタ
		public ListViewItemComparer(int col)
		{
			m_column = col;
			m_order *= -1;	//ListViewItemComparerが呼ばれる度に正順、逆順が変更される
		}

		//xがyより小さいときはマイナスの数、大きいときはプラスの数、同じときは0を返す
		public int Compare(object x, object y)
		{
			//ListViewItemの取得
			ListViewItem itemx = (ListViewItem) x;
			ListViewItem itemy = (ListViewItem) y;
			//xとyを文字列として比較する
			return string.Compare(itemx.SubItems[m_column].Text, itemy.SubItems[m_column].Text) * m_order;
		}
	}

	///////////////////
	//CmdSetダイアログ
	///////////////////
	public class CmdSetDlg : Form
	{
		//クラスメンバーフィールド
		public TGSet Tgs;			//TGSetクラスインスタンス
		Button Btn_Add;				//命令追加ボタン
		Button Btn_Del;				//命令削除ボタン
		Button Btn_Init;			//初期化ボタン
		Button Btn_OK;				//OKボタン
		Button Btn_Cancel;			//Cancelボタン
		ListView listView;			//リストビュー
		Label lblTimes;				//繰り返し回数ラベル
		TextBox txbTimes;			//繰り返し回数入力用
		Button Btn_Name;			//名前・説明ボタン
		Label lblName;				//命令セット名ラベル
		TextBox txbName;			//命令セット名入力用
		Label lblDescription;		//説明ラベル
		TextBox txbDescription;		//説明入力用

		//コンストラクター（１）
		public CmdSetDlg()
		{
			this.ShowIcon = false;
			this.Text = "命令セット入力ダイアログ";
			this.ClientSize = new Size(594, 320);
			this.MinimumSize = new Size(430, 340);
			this.BackColor = SystemColors.Window;
			this.Load += new EventHandler(CmdSetDlg_OnLoad);
			this.Tgs = new TGSet();					//命令セット
			this.Tgs.AddCmd(new int[] {-1,1,0,0});	//命令セット開始
		}

		//コンストラクター（２）
		public CmdSetDlg(TGSet tgs)
		{
			this.ShowIcon = false;
			this.Text = "命令セット編集ダイアログ";
			this.ClientSize = new Size(594, 320);
			this.MinimumSize = new Size(430, 340);
			this.BackColor = SystemColors.Window;
			this.Load += new EventHandler(CmdSetDlg_OnLoad);
			this.Tgs = tgs;							//命令セット参照渡し
		}

		//OnLoad時処理
		protected void CmdSetDlg_OnLoad(object sender, EventArgs e)
		{
			Btn_Add = new Button();
			Btn_Add.Text = "命令追加";
			Btn_Add.TextAlign = ContentAlignment.MiddleCenter;
			Btn_Add.Font = new Font("ＭＳ 明朝", 8);
			Btn_Add.ForeColor = Color.Black;
			Btn_Add.Size = new Size(80, 28);
			Btn_Add.BackColor = SystemColors.Control;
			Btn_Add.Location = new Point(ClientSize.Width - Btn_Add.Width - 10, 10);
			Btn_Add.Anchor = (AnchorStyles.Top | AnchorStyles.Right);
			Btn_Add.Click += new EventHandler(OnClick_Add);	

			Btn_Del = new Button();
			Btn_Del.Text = "命令削除";
			Btn_Del.TextAlign = ContentAlignment.MiddleCenter;
			Btn_Del.Font = new Font("ＭＳ 明朝", 8);
			Btn_Del.ForeColor = Color.Black;
			Btn_Del.Size = new Size(80, 28);
			Btn_Del.BackColor = SystemColors.Control;
			Btn_Del.Location = new Point(ClientSize.Width - Btn_Del.Width - 10, 20 + Btn_Add.Height);
			Btn_Del.Anchor = (AnchorStyles.Top | AnchorStyles.Right);
			Btn_Del.Click += new EventHandler(OnClick_Del);

			Btn_Init = new Button();
			Btn_Init.Text = "命令初期化";
			Btn_Init.TextAlign = ContentAlignment.MiddleCenter;
			Btn_Init.Font = new Font("ＭＳ 明朝", 8);
			Btn_Init.ForeColor = Color.Black;
			Btn_Init.Size = new Size(80, 28);
			Btn_Init.BackColor = SystemColors.Control;
			Btn_Init.Location = new Point(ClientSize.Width - Btn_Init.Width - 10, 30 + Btn_Add.Height + Btn_Del.Height);
			Btn_Init.Anchor = (AnchorStyles.Top | AnchorStyles.Right);
			Btn_Init.Click += new EventHandler(OnClick_Init);

			Btn_OK = new Button();
			Btn_OK.Text = "OK";
			Btn_OK.TextAlign = ContentAlignment.MiddleCenter;
			Btn_OK.Font = new Font("ＭＳ 明朝", 8);
			Btn_OK.ForeColor = Color.Black;
			Btn_OK.Size = new Size(80, 28);
			Btn_OK.BackColor = SystemColors.Control;
			Btn_OK.Location = new Point(ClientSize.Width - Btn_OK.Width - 10, ClientSize.Height - Btn_OK.Height - 10);
			Btn_OK.Anchor = (AnchorStyles.Bottom | AnchorStyles.Right);
			Btn_OK.Click += new EventHandler(OnClick_OK);

			Btn_Cancel = new Button();
			Btn_Cancel.Text = "Cancel";
			Btn_Cancel.TextAlign = ContentAlignment.MiddleCenter;
			Btn_Cancel.Font = new Font("ＭＳ 明朝", 8);
			Btn_Cancel.ForeColor = Color.Black;
			Btn_Cancel.Size = new Size(80, 28);
			Btn_Cancel.BackColor = SystemColors.Control;
			Btn_Cancel.Location = new Point(ClientSize.Width - Btn_Cancel.Width - 10, ClientSize.Height - Btn_Cancel.Height - Btn_OK.Height - 20);
			Btn_Cancel.Anchor = (AnchorStyles.Bottom | AnchorStyles.Right);
			Btn_Cancel.Click += new EventHandler(OnClick_Cancel);

			lblTimes = new Label();
			lblTimes.Size = new Size(80, 28);
			lblTimes.Location = new Point(ClientSize.Width - lblTimes.Width - 10, 40 + Btn_Add.Height + Btn_Del.Height + Btn_Init.Height);
			lblTimes.Anchor = (AnchorStyles.Top | AnchorStyles.Right);
			lblTimes.AutoSize = false;
			lblTimes.TextAlign = ContentAlignment.MiddleCenter;
			lblTimes.Font = new Font("ＭＳ 明朝", 8);
			lblTimes.Text = "繰り返し回数";

			txbTimes = new TextBox();
			txbTimes.Size = new Size(80, 28);
			txbTimes.Location = new Point(ClientSize.Width - lblTimes.Width - 10, 40 + Btn_Add.Height + Btn_Del.Height + Btn_Init.Height + lblTimes.Height);
			txbTimes.Anchor = (AnchorStyles.Top | AnchorStyles.Right);
			txbTimes.TextAlign = HorizontalAlignment.Right;
			txbTimes.Text ="1";

			Btn_Name = new Button();
			Btn_Name.Text = "名前・説明";
			Btn_Name.TextAlign = ContentAlignment.MiddleCenter;
			Btn_Name.Font = new Font("ＭＳ 明朝", 8);
			Btn_Name.ForeColor = Color.Black;
			Btn_Name.Size = new Size(80, 28);
			Btn_Name.BackColor = SystemColors.Control;
			Btn_Name.Location = new Point(ClientSize.Width - Btn_Init.Width - 10, 50 + Btn_Add.Height + Btn_Del.Height + Btn_Init.Height + lblTimes.Height + txbTimes.Height);
			Btn_Name.Anchor = (AnchorStyles.Top | AnchorStyles.Right);
			Btn_Name.Click += new EventHandler(OnClick_Name);

			lblName = new Label();
			lblName.Size = new Size(80, 18);
			lblName.Location = new Point(10, 10);
			lblName.Anchor = (AnchorStyles.Top | AnchorStyles.Left);
			lblName.AutoSize = false;
			lblName.Font = new Font("ＭＳ 明朝", 8);
			lblName.Text = "命令セット名";
			lblName.Visible = false;

			txbName = new TextBox();
			txbName.Size = new Size(ClientSize.Width - Btn_Add.Width - 30, 28);
			txbName.Location = new Point(10, lblName.Height + 10);
			txbName.Anchor = (AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right);
			txbName.Visible = false;

			lblDescription = new Label();
			lblDescription.Size = new Size(80, 18);
			lblDescription.Location = new Point(10, lblName.Height + txbName.Height + 20);
			lblDescription.Anchor = (AnchorStyles.Top | AnchorStyles.Left);
			lblDescription.AutoSize = false;
			lblDescription.Font = new Font("ＭＳ 明朝", 8);
			lblDescription.Text = "説明";
			lblDescription.Visible = false;

			txbDescription = new TextBox();
			txbDescription.Size = new Size(ClientSize.Width - Btn_Add.Width - 30, ClientSize.Height - lblName.Height - txbName.Height - lblDescription.Height - 30);
			txbDescription.Location = new Point(10, lblName.Height + txbName.Height + lblDescription.Height + 20);
			txbDescription.Multiline = true;
			txbDescription.WordWrap = true;
			txbDescription.ScrollBars = ScrollBars.Vertical;
			txbDescription.Anchor = (AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Bottom | AnchorStyles.Right);
			txbDescription.Visible = false;

			this.Controls.Add(Btn_Add);
			this.Controls.Add(Btn_Del);
			this.Controls.Add(Btn_Init);
			this.Controls.Add(lblTimes);
			this.Controls.Add(txbTimes);
			this.Controls.Add(Btn_Name);
			this.Controls.Add(Btn_Cancel);
			this.Controls.Add(Btn_OK);
			this.Controls.Add(lblName);
			this.Controls.Add(txbName);
			this.Controls.Add(lblDescription);
			this.Controls.Add(txbDescription);

			//リストビュー
			listView = new ListView();
			listView.BorderStyle = BorderStyle.Fixed3D;				//境界
			listView.Location = new Point(10, 10);					//位置
			listView.Width = ClientSize.Width - Btn_Add.Width - 30;	//サイズ
			listView.Height = ClientSize.Height - 20;
			listView.Anchor = (AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Bottom | AnchorStyles.Right);	//アンカー固定
			listView.FullRowSelect = true;							//一行選択
			listView.MultiSelect = false;							//複数選択不可
			listView.GridLines = true;								//グリッドラインの表示
			listView.HoverSelection = false;						//ポイントで選択できるようにする
			listView.Activation = ItemActivation.OneClick;			//シングルクリック選択;
			listView.CheckBoxes = false;							//チェックボックス無効化
			listView.View = View.Details;							//リストビューの表示方法
			listView.AllowDrop = false;								//listViewへのドロップを受け入れない
			//イベントハンドラー
			listView.MouseDoubleClick+= new MouseEventHandler(ListView_DoubleClick);
			//ヘッダー定義
			ColumnHeader columnCmd = new ColumnHeader{Text = "命令", Width = 80};
			ColumnHeader columnExp = new ColumnHeader{Text = "説明", Width = 220};
			ColumnHeader columnArg1 = new ColumnHeader{Text = "引数1", Width = 60};
			columnArg1.TextAlign = HorizontalAlignment.Center;
			ColumnHeader columnArg2 = new ColumnHeader{Text = "引数2", Width = 60};
			columnArg2.TextAlign = HorizontalAlignment.Center;
			ColumnHeader columnArg3 = new ColumnHeader{Text = "引数3", Width = 60};
			columnArg3.TextAlign = HorizontalAlignment.Center;
			ColumnHeader columnCmdNo = new ColumnHeader{Text = "命令番号", Width = 60};
			columnCmdNo.TextAlign = HorizontalAlignment.Center;
			ColumnHeader[] colHeaderRegValue = {columnCmd, columnExp, columnArg1, columnArg2, columnArg3, columnCmdNo};	//ヘッダー設定
			listView.Columns.AddRange(colHeaderRegValue);	//ヘッダー追加
			//編集ダイアログの場合の初期設定
			if(Tgs.Count() > 1)
			{
				string[] CmdNameList = new string[15] {"Nop", "Forward()", "Backward()",
												"MoveTo()", "Rotate()", "RotateTo()",
												"PenUp()", "PenDown()", "X",
												"Y", "Angle", "PenColor",
												"PenSize", "PenVisible", "Delay"};
				string[] CmdExplList = new string[15] {"何もしない", "前進する", "後退する",
												"絶対座標へ移動する", "現在の方向から指定角度回転", "絶対角度へ回転（↑0→90↓180←270）",
												"描画停止", "描画開始", "X座標指定（移動）",
												"X座標指定（移動）", "角度指定（↑0→90↓180←270）",
												"描画色指定（Color）", "描画幅指定", "可視可(1)、不可(0)", "中断時間（ms）"};
				for(int i = 1; i < Tgs.Count(); i++)
				{
					int[] cmd = Tgs.GetCmd(i);
					string[] item = {CmdNameList[cmd[0]], CmdExplList[cmd[0]],
									cmd[1].ToString(), cmd[2].ToString(), 
									cmd[3].ToString(), cmd[0].ToString()};
					listView.Items.Add(new ListViewItem(item));
				}
				txbName.Text = Tgs.Name;				//命令セット名
				txbDescription.Text = Tgs.Description;	//説明
				int[] hedder = Tgs.GetCmd(0);			//"-1"のある最初の命令行を取得
				txbTimes.Text = hedder[1].ToString();	//"-1"の次が繰り返し回数
			}
			//FormにListViewを追加
			this.Controls.Add(listView);
		}

		//終了時処理
		protected override void OnFormClosing(FormClosingEventArgs e)
		{
			base.OnFormClosing(e);
			DialogResult dr = MessageBox.Show("終了しますか？", "確認", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
			if(dr == DialogResult.No)
			{
				e.Cancel = true;
			}
		}

		//Addボタンがクリックされた時
		protected void OnClick_Add(object sender, EventArgs e)
		{
			//入力ダイアログによる入力
			InputDlg inpDlg = new InputDlg();
			inpDlg.ShowDialog();
			if(inpDlg.dtData[0] == -1)
				MessageBox.Show("入力がキャンセルされました。", "注意", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
			else
			{
				//原本のリストに追加
				Tgs.AddCmd(inpDlg.dtData);
				//その内容をListViewに表示
				string[] item = {inpDlg.dtCmd[0], inpDlg.dtCmd[1],
								inpDlg.dtData[1].ToString(), inpDlg.dtData[2].ToString(), 
								inpDlg.dtData[3].ToString(), inpDlg.dtData[0].ToString()};
				listView.Items.Add(new ListViewItem(item));
			}
			inpDlg.Dispose();
		}

		//Delボタンがクリックされた時
		protected void OnClick_Del(object sender, EventArgs e)
		{
			//選択された行を確認する
			if(listView.SelectedItems.Count == 0)
				MessageBox.Show("データが選択されていません", "エラー", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
			else
			{
				int selected_index = listView.SelectedIndices[0];
				Tgs.RemoveAt(selected_index + 1);	//Tgs.CmdSetはlistViewよりも1行多い
				listView.Items.RemoveAt(selected_index);
			}
		}

		//Initボタンがクリックされた時
		protected void OnClick_Init(object sender, EventArgs e)
		{
			Tgs.Clear();
			listView.Items.Clear();
		}

		//OKボタンがクリックされた時
		protected void OnClick_OK(object sender, EventArgs e)
		{
			int times = 0;
			if(int.TryParse(txbTimes.Text, out times))
				Tgs.SetCmd(0, -1, times, 0, 0);		//TgsのCmdSet[0]に"-1,回数,0,0"を代入"
			else
			{	//繰り返し回数が異常値の場合は終了させない
				MessageBox.Show("繰り返し回数が整数ではありません。", "エラー", MessageBoxButtons.OK, MessageBoxIcon.Error);
				return;
			}
			//受け渡しデータに値を入れる
			Tgs.Name = txbName.Text;
			Tgs.Description = txbDescription.Text;
			//このフォームの戻り値
			DialogResult = DialogResult.OK;
			Close();
		}

		//Cancelボタンがクリックされた時
		protected void OnClick_Cancel(object sender, EventArgs e)
		{
			//受け渡しデータを初期化する（編集モードでTGSetの参照入力をしている場合、注意が必要！）
			Tgs.Clear();
			Tgs.Name = String.Empty;
			Tgs.Description = String.Empty;
			//このフォームの戻り値
			DialogResult = DialogResult.Cancel;
			Close();
		}

		//Namelボタンがクリックされた時
		protected void OnClick_Name(object sender, EventArgs e)
		{
			if(Btn_Name.Text == "名前・説明")
			{
				Btn_Name.Text = "命令セット";
				listView.Visible = false;
				Btn_Add.Visible = false;
				Btn_Del.Visible = false;
				Btn_Init.Visible = false;
				lblTimes.Visible = false;
				txbTimes.Visible = false;
				lblName.Visible = true;
				txbName.Visible = true;
				lblDescription.Visible = true;
				txbDescription.Visible = true;
			}
			else
			{
				Btn_Name.Text = "名前・説明";
				listView.Visible = true;
				Btn_Add.Visible = true;
				Btn_Del.Visible = true;
				Btn_Init.Visible = true;
				lblTimes.Visible = true;
				txbTimes.Visible = true;
				lblName.Visible = false;
				txbName.Visible = false;
				lblDescription.Visible = false;
				txbDescription.Visible = false;
			}
		}

		//listViewがダブルクリックされた時
		protected void ListView_DoubleClick(object sender, MouseEventArgs e)
		{
			//選択された項目があるか確認
			if(listView.SelectedIndices.Count > 0)
			{
				//入力ダイアログによる入力
				int selected_index = listView.SelectedIndices[0];
				InputDlg inpDlg = new InputDlg(Tgs.GetCmd(selected_index + 1));
				inpDlg.ShowDialog(this);
				//入力ダイアログによる入力
				if(inpDlg.dtData[0] == -1)
					MessageBox.Show("入力がキャンセルされました。", "注意", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
				else
				{
					Tgs.SetCmd(selected_index + 1, (int[])inpDlg.dtData.Clone());	//Tgs.CmdSetはlistViewよりも1行多い
					listView.Items[selected_index].SubItems[0].Text = inpDlg.dtCmd[0];
					listView.Items[selected_index].SubItems[1].Text = inpDlg.dtCmd[1];
					listView.Items[selected_index].SubItems[2].Text = inpDlg.dtData[1].ToString();
					listView.Items[selected_index].SubItems[3].Text = inpDlg.dtData[2].ToString();
					listView.Items[selected_index].SubItems[4].Text = inpDlg.dtData[3].ToString();
					listView.Items[selected_index].SubItems[5].Text = inpDlg.dtData[0].ToString();
				}
				inpDlg.Dispose();
			}
		}
	}

	/////////////////////////
	// Command入力ダイアログ
	/////////////////////////
	class InputDlg : Form
	{
		//クラスフィールド
		string[] CmdNameList = new string[15] {"Nop", "Forward()", "Backward()",
												"MoveTo()", "Rotate()", "RotateTo()",
												"PenUp()", "PenDown()", "X",
												"Y", "Angle", "PenColor",
												"PenSize", "PenVisible", "Delay"};
		string[] CmdExplList = new string[15] {"何もしない", "前進する", "後退する",
												"絶対座標へ移動する", "現在の方向から指定角度回転", "絶対角度へ回転（↑0→90↓180←270）",
												"描画停止", "描画開始", "X座標指定（移動）",
												"X座標指定（移動）", "角度指定（↑0→90↓180←270）",
												"描画色指定（Color）", "描画幅指定", "可視可(1)、不可(0)", "中断時間（ms）"};
		//クラスプロパティ
		public int[] dtData {get; set;}
		public string[] dtCmd;
		//クラスコントロール
		Button BtnOK;
		Button BtnCancel;
		GroupBox gBox;
		ComboBox cbCommands;
		TextBox txbExplanation;
		Label[] labelCmd;
		TextBox[] txbStr;

		//コンストラクター（１）
		public InputDlg()
		{
			dtData = new int[] {-1, 0, 0, 0};		//ComboBoxが選択されていない状態のSelectedIndex値
			dtCmd = new string[] {"", ""};			//命令文と説明文
			InitializeControls();
		}

		//コンストラクター（２）
		public InputDlg(int[] arg_Data)
		{
			//引数の記録
			if(arg_Data[0] >= 0 && arg_Data[0] < CmdNameList.Length)
				dtData = (int[])arg_Data.Clone();	//arg_Data配列のクローンで初期化
			else
				dtData = new int[] {-1, 0, 0, 0};	//ComboBoxが選択されていない状態のSelectedIndex値
			dtCmd = new string[] {"", ""};			//命令文と説明文
			InitializeControls();
		}

		//コントロールの初期化
		private void InitializeControls()
		{
			//ダイアログの属性設定
			if(dtData[0] == -1)
				this.Text = "命令入力ダイアログ";
			else
				this.Text = "命令編集ダイアログ";
			this.ClientSize = new Size(320, 210);
			this.MaximizeBox = false;		//最大化ボタン
			this.MinimizeBox = false;		//最小化ボタン
			this.ShowInTaskbar = false;		//タスクバー上非表示
			this.FormBorderStyle = FormBorderStyle.FixedDialog;		//境界のスタイル
			this.StartPosition = FormStartPosition.CenterScreen;	//画面中央に配置

			//コントロールの属性設定
			BtnOK = new Button();
			BtnOK.Location = new Point(ClientSize.Width - BtnOK.Width - 20, ClientSize.Height - BtnOK.Height - 10);
			BtnOK.Text = "OK";
			BtnOK.AutoSize = true;
			BtnOK.Click += new EventHandler(OnOK_Click);

			BtnCancel = new Button();
			BtnCancel.Location = new Point(20, ClientSize.Height - BtnCancel.Height - 10);
			BtnCancel.Text = "Cancel";
			BtnCancel.AutoSize = true;
			BtnCancel.Click += new EventHandler(OnCancel_Click);

			gBox = new GroupBox();
			gBox.Location = new Point(10, 0);
			gBox.Size = new Size(ClientSize.Width - 20, ClientSize.Height - BtnOK.Height - 20);
			gBox.Text = "命令と引数1～3の設定";

			cbCommands =new ComboBox();
			cbCommands.Location = new Point(10, 16);
			cbCommands.Size = new Size(ClientSize.Width / 2, 28);
			cbCommands.DropDownWidth = ClientSize.Width / 2;
			cbCommands.DropDownHeight = 160;
			cbCommands.DropDownStyle = ComboBoxStyle.DropDownList;
			cbCommands.FormattingEnabled = true;
			cbCommands.TextChanged += Command_TextChanged;

			txbExplanation = new TextBox();
			txbExplanation.Location = new Point(10, 40);
			txbExplanation.Size = new Size(ClientSize.Width / 2, 120);
			txbExplanation.Multiline = true;
			txbExplanation.WordWrap = true;
			txbExplanation.BorderStyle = BorderStyle.Fixed3D;
			txbExplanation.ReadOnly = true;

			labelCmd = new Label[3];
			labelCmd[0] = new Label();
			labelCmd[0].Text = "引数1（定数）";
			labelCmd[0].Size = new Size(80, 18);
			labelCmd[0].Location = new Point(180, 20);
			labelCmd[1] = new Label();
			labelCmd[1].Text = "引数2（倍数）";
			labelCmd[1].Location = new Point(180, 70);
			labelCmd[1].Size = new Size(80, 18);
			labelCmd[2] = new Label();
			labelCmd[2].Text = "引数3（分子）";
			labelCmd[2].Location = new Point(180, 120);
			labelCmd[2].Size = new Size(80, 18);

			txbStr = new TextBox[3];
			txbStr[0] = new TextBox();
			txbStr[0].Location = new Point(180, 38);
			txbStr[0].Size = new Size(100, 28);
			txbStr[0].BorderStyle = BorderStyle.Fixed3D;
			txbStr[0].Text = "0";
			txbStr[0].TextAlign = HorizontalAlignment.Right;
			txbStr[0].Enter += txbStr0_Enter;
			txbStr[1] = new TextBox();
			txbStr[1].Size = new Size(100, 28);
			txbStr[1].Location = new Point(180, 88);
			txbStr[1].BorderStyle = BorderStyle.Fixed3D;
			txbStr[1].Text = "0";
			txbStr[1].TextAlign = HorizontalAlignment.Right;
			txbStr[1].Enter += txbStr1_Enter;
			txbStr[2] = new TextBox();
			txbStr[2].Size = new Size(100, 28);
			txbStr[2].Location = new Point(180, 138);
			txbStr[2].BorderStyle = BorderStyle.Fixed3D;
			txbStr[2].Text = "0";
			txbStr[2].TextAlign = HorizontalAlignment.Right;
			txbStr[2].Enter += txbStr2_Enter;

			gBox.Controls.Add(cbCommands);
			gBox.Controls.Add(txbExplanation);
			gBox.Controls.Add(labelCmd[0]);
			gBox.Controls.Add(labelCmd[1]);
			gBox.Controls.Add(labelCmd[2]);
			gBox.Controls.Add(txbStr[0]);
			gBox.Controls.Add(txbStr[1]);
			gBox.Controls.Add(txbStr[2]);
			this.Controls.Add(BtnOK);
			this.Controls.Add(BtnCancel);
			this.Controls.Add(gBox);

			//cbCommands、txbStrの初期設定
			cbCommands.Items.AddRange(CmdNameList);
			if(dtData[0] >= 0 && dtData[0] < CmdNameList.Length)
			{
				cbCommands.SelectedIndex = dtData[0];
			}
			if(dtData[1] != 0)
			{
				txbStr[0].Text = dtData[1].ToString();
			}
			if(dtData[2] != 0)
			{
				txbStr[1].Text = dtData[2].ToString();
			}
			if(dtData[3] != 0)
			{
				txbStr[2].Text = dtData[3].ToString();
			}
		}

		private void Command_TextChanged(object sender, EventArgs e)
		{
			dtData[0] = cbCommands.SelectedIndex;
			txbExplanation.Text = CmdExplList[dtData[0]];
			if(dtData[0] == 11)
			{
				txbStr[1].Enabled = false;
				txbStr[2].Enabled = false;
			}
		}

		private void txbStr0_Enter(object sender, EventArgs e)
		{
			string msg = "命令に与えられる「引数1（定数） + 引数2 * 繰り返し数（倍数） + 引数3 / (最大繰り返し数 - 繰り返し数）（分子）」の定数部分です。";
			if(dtData[0] == 3)
				msg = "MoveTo(x, y)の場合引数1がx、引数2がyで、引数3の繰り返し回数の倍数が加算されます。（x = 引数1 + 引数3 x 繰り返し数、y = 引数2 + 引数3 x 繰り返し数）";
			else if(dtData[0] == 11)
			{
				msg = "PenColor()の場合、引数1にColor.FromArgb(RGB値)のRGB値が入ります。";
				ColorDialog colDlg = new ColorDialog();
				colDlg.AllowFullOpen = true;
				if(colDlg.ShowDialog() == DialogResult.OK)
				{
					txbStr[0].Text = colDlg.Color.ToArgb().ToString();
					colDlg.Dispose();
				}
				txbStr[1].Enabled = true;
				txbStr[2].Enabled = true;
			}
			txbExplanation.Text = msg;
		}

		private void txbStr1_Enter(object sender, EventArgs e)
		{
			string msg = "命令に与えられる「引数1（定数） + 引数2 * 繰り返し数（倍数） + 引数3 / (最大繰り返し数 - 繰り返し数）（分子）」の倍数部分です。";
			if(dtData[0] == 3)
				msg = "MoveTo(x, y)の場合引数1がx、引数2がyで、引数3の繰り返し回数の倍数が加算されます。（x = 引数1 + 引数3 x 繰り返し数、y = 引数2 + 引数3 x 繰り返し数）";
			txbExplanation.Text = msg;
		}

		private void txbStr2_Enter(object sender, EventArgs e)
		{
			string msg = "命令に与えられる「引数1（定数） + 引数2 * 繰り返し数（倍数） + 引数3 / (最大繰り返し数 - 繰り返し数）（分子）」の分子部分です。";
			if(dtData[0] == 3)
				msg = "MoveTo(x, y)の場合引数1がx、引数2がyで、引数3の繰り返し回数の倍数が加算されます。（x = 引数1 + 引数3 x 繰り返し数、y = 引数2 + 引数3 x 繰り返し数）";
			txbExplanation.Text = msg;
		}

		//OKボタンがクリックされた時
		protected void OnOK_Click(object sender, EventArgs e)
		{
			if(dtData[0] < 0)
				MessageBox.Show("命令が選択されていません。", "エラー", MessageBoxButtons.OK, MessageBoxIcon.Error);
			else
			{
				dtCmd[0] = CmdNameList[dtData[0]];		//命令文
				dtCmd[1] = CmdExplList[dtData[0]];		//説明文
				int dat = 0;
				if(!int.TryParse(txbStr[0].Text, out dat))
					MessageBox.Show("引数1が整数ではありません。", "エラー", MessageBoxButtons.OK, MessageBoxIcon.Error);
				else
				{
					dtData[1] = dat;
					if(!int.TryParse(txbStr[1].Text, out dat))
						MessageBox.Show("引数2が整数ではありません。", "エラー", MessageBoxButtons.OK, MessageBoxIcon.Error);
					else
					{
						dtData[2] = dat;
						if(!int.TryParse(txbStr[2].Text, out dat))
							MessageBox.Show("引数3が整数ではありません。", "エラー", MessageBoxButtons.OK, MessageBoxIcon.Error);
						else
						{
							dtData[3] = dat;
							Close();
						}
					}
				}
			}
		}

		//Cancelボタンがクリックされた時
		protected void OnCancel_Click(object sender, EventArgs e)
		{
			Close();
		}
	}
}
