#pragma warning disable IDE1006 // 명명 스타일

using AR;
using System;
using System.Collections.Generic;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Windows.Forms;

namespace Project
{
	public partial class Model_Motion : Form
	{
		public string Value = string.Empty;
		short axisIndex = -1;
		eAxis axis = eAxis.Z_THETA;//
		Color sbBackColor = Color.FromArgb(200, 200, 200);

		public Model_Motion()
		{
			InitializeComponent();

			if (System.Diagnostics.Debugger.IsAttached == false)
			{
				// fb = new Dialog.fBlurPanel();
				//fb.Show();
			}

			this.KeyPreview = true;
			this.KeyDown += (s1, e1) => { if (e1.KeyCode == Keys.Escape) this.Close(); };
			this.StartPosition = FormStartPosition.CenterScreen;
			this.FormClosed += __Closed;
			this.FormClosing += __Closing;

			var axlist = Enum.GetNames(typeof(eAxis));
			var axvalues = Enum.GetValues(typeof(eAxis));

			var preValueList = new List<ushort>();

			//모터설정값을 보고 해당 모터의 목록을 표시한다.
			//사용하지 않는 축은 표시하지 않는다
			for (int i = 0; i < SETTING.System.MotaxisCount; i++)
			{
				var axis = (eAxis)i;
				var axisname = (eAxisName)i;
				var axTitle = axisname.ToString();// axis.ToString();

				if (PUB.system_mot.UseAxis(i) == false) continue;// axTitle = "Disable";

				if (axisIndex == -1) axisIndex = (short)i;
				if (axTitle.Equals(i.ToString())) axTitle = "(No Name)";
				this.dvMot.Rows.Add(
					new string[] {
						i.ToString(), axTitle, string.Empty, string.Empty, string.Empty,
						string.Empty, string.Empty, string.Empty, string.Empty, string.Empty,
						string.Empty
					});
			}
            dvMot.Columns[10].DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleLeft;
			//링크레이블과 버튼 연결
			AttachEvents();
		}
		Boolean hasChanged()
		{
			this.Validate();
			this.bsPosData.EndEdit();
			var chg = this.ds1.MCModel.GetChanges();
			if (chg == null || chg.Rows.Count < 1) return false;
			return true;
		}

		private void __Closing(object sender, FormClosingEventArgs e)
		{
			if (hasChanged())
			{
				var dlg = UTIL.MsgQ("There are unsaved changes.\n" +
				   "Proceeding will discard the changes\n" +
				   "Do you want to continue?");

				if (dlg != DialogResult.Yes)
				{
					e.Cancel = true;
					return;
				}
			}
		}

		private void __Load(object sender, EventArgs e)
		{
			this.Show();
			////'Application.DoEvents();
			///



			this.ds1.Clear();
			this.ds1.MCModel.Merge(PUB.mdm.dataSet.MCModel);
			this.ds1.MCModel.AcceptChanges();
			this.ds1.MCModel.TableNewRow += Model_TableNewRow;
			//this.ds1.MCModel.AcceptChanges();


			//축이름을 확인 220304
			foreach (DataSet1.MCModelRow dr in ds1.MCModel)
			{
				if (dr.RowState == DataRowState.Deleted || dr.RowState == DataRowState.Detached) continue;
				var curname = dr.MotName;
				var axis = (eAxis)dr.MotIndex;
				if (axis.ToString() != curname)
				{
					dr.MotName = axis.ToString();
					dr.EndEdit();
				}
			}
			this.ds1.MCModel.AcceptChanges();

			//데이터가 안나오게 한다.
			this.bsPosData.Filter = "isnull(title,'') = 'dudrndjqtek' and isnull(motindex,-1) = -1";



			//모델목록을 업데이트한다 (모델은 pidx =-1인데이터를 뜻한다)
			RefreshModelList();


			//현재 선택된 모델정보를 표시한다.
			if (PUB.Result.isSetmModel)
			{
				//모델명을 표시
				lbModelTitle.Text = PUB.Result.mModel.Title;

				//해당모델명을 찾아서 선택해준다.
				foreach (ListViewItem item in this.listView1.Items)
				{
					if (item.Text == PUB.Result.mModel.Title)
					{
						item.Focused = true;
						item.Selected = true;
						break;
					}
				}
			}
			else
			{
				//선택된 모델명이 없다
				lbModelTitle.Text = "--";
			}

			//모델정보가 아에 없다면
			if (this.ds1.MCModel.Rows.Count < 1)
			{
				var newdr = this.ds1.MCModel.NewMCModelRow();
				newdr.Title = "Default";
				newdr.pidx = -1;
				newdr.PosIndex = -1;
				newdr.idx = ds1.MCModel.Rows.Count + 1;
				this.ds1.MCModel.AddMCModelRow(newdr);

				UTIL.MsgI("No registered models found. Creating default model (Default)");
			}

			//this.axisIndex = 0; //기본Z축
			//radClick_MotAxisSelect(this.flowLayoutPanel1.Controls[0], null);
			//var rad = flowLayoutPanel1.Controls[0] as RadioButton;
			//rad.Checked = true;

			//빠른실행폼추가
			var fctl = new Dialog.Quick_Control
			{
				TopLevel = false,
				Visible = true,
				Padding = new Padding(0, 0, 0, 0),
				ForeColor = Color.Black
			};
			fctl.panBG.BackColor = Color.White;
			fctl.panBG.ForeColor = Color.Black;
			//fctl.groupBox2.ForeColor = Color.Black;
			fctl.groupBox3.ForeColor = Color.Black;
			this.tabPage2.Controls.Add(fctl);
			fctl.Dock = DockStyle.Fill;
			fctl.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;
			//fctl.panTopMenuDiv.Visible = false;
			///      fctl.panBG.BackColor = this.panel6.BackColor;
			fctl.panBG.BorderStyle = BorderStyle.None;
			fctl.Show();
			fctl.Dock = DockStyle.Fill;
			PUB.log.RaiseMsg += log_RaiseMsg;
			//PUB.flag.set(eVarBool.JOG, true, "MOTION CONTROL");

			if (PUB.sm.Step != eSMStep.IDLE)
			{
				btDel.Enabled = false;
				btCopy.Enabled = false;
				btSelect.Visible = false;
				btEdit.Enabled = false;
				//Util.MsgE("대기 상태일때만 복사/삭제 기능을 쓸 수 있습니다");
			}

			this.RtLog.ColorList = new arCtl.sLogMessageColor[] {
				new arCtl.sLogMessageColor("BARCODE",Color.DarkMagenta),
				new arCtl.sLogMessageColor("ERR",Color.Red),
				new arCtl.sLogMessageColor("NORMAL", Color.Black),
				new arCtl.sLogMessageColor("WARN", Color.DarkMagenta),
				new arCtl.sLogMessageColor("ATT", Color.MidnightBlue),
				new arCtl.sLogMessageColor("INFO", Color.MidnightBlue),
				new arCtl.sLogMessageColor("VIS", Color.Blue),
				new arCtl.sLogMessageColor("SM", Color.Indigo),
				new arCtl.sLogMessageColor("WATCH", Color.Indigo),
			};

			this.tmDisplay.Start();
		}

		void RefreshModelList()
		{
			this.listView1.Items.Clear();
			var list = this.ds1.MCModel.Where(t => t.pidx == -1).OrderBy(t => t.Title).ToList();
			if (list.Any())
			{
				foreach (var item in list)
				{
					if (item.Title.isEmpty()) continue;
					var lv = this.listView1.Items.Add(item.Title);
					lv.Tag = item.idx;
				}
			}
		}

		void AttachEvents()
		{
			var EventConnectControls = new List<Control>
			{
				tabControl4
			};

			//linklabel 과 button 에 클릭 이벤트 생성
			foreach (Control page in EventConnectControls)
			{
				foreach (var ctl in page.Controls)
				{
					if (ctl.GetType() == typeof(arFrame.Control.MotLinkLabel))
					{
						var label = ctl as arFrame.Control.MotLinkLabel;
						if (label.motValueControl != null) label.LinkClicked += label_LinkClicked;

					}
					else if (ctl.GetType() == typeof(arFrame.Control.MotCommandButton))
					{
						var button = ctl as arFrame.Control.MotCommandButton;
						if (button.motValueControl != null) button.Click += button_Click;
					}
				}
			}
		}

		void button_Click(object sender, EventArgs e)
		{
			var ctl = sender as arFrame.Control.MotCommandButton;
			var nud = ctl.motValueControl as arFrame.Control.MotValueNumericUpDown;
			var nudAcc = ctl.motAccControl;// as arFrame.Control.MotValueNumericUpDown;
			var nudSpd = ctl.motSpdControl;
			if (nud.MotionIndex < 0)
			{
				UTIL.MsgE("Motion axis number is not specified\n\n" +
					"Name : " + ctl.Name + "\n" +
					"Title : " + ctl.Text);
				return;
			}
			if ((nudAcc == null || nudSpd == null) && ctl.motCommand != arFrame.Control.MotCommandButton.eCommand.AcceptPosition)
			{
				UTIL.MsgE("Speed/acceleration control is not specified\n\n" +
					"Name : " + ctl.Name + "\n" +
					"Title : " + ctl.Text);
				return;
			}

			var axis = (eAxis)nud.MotionIndex;
			var pos = (double)nud.Value;

			//모션이 초기화가 안되있다면 오류로 처리한다
			if (PUB.mot.IsHomeSet((short)nud.MotionIndex) == false)
			{
				UTIL.MsgE("Home search for this axis is not completed.\nPlease complete home search first");
				return;
			}



			switch (ctl.motCommand)
			{
				case arFrame.Control.MotCommandButton.eCommand.AcceptPosition:

					var msg1 = string.Format("Do you want to change the motion settings?\n" +
					   "Axis : {0}\n" +
					   "Before : {1}\n" +
					   "After : {2}\n" +
					   "You must press 'Save' after change to record permanently", axis, PUB.mot.GetActPos((short)nud.MotionIndex), pos, nud.Value);

					if (UTIL.MsgQ(msg1) != System.Windows.Forms.DialogResult.Yes) return;

					ChangeCurrentPosition((short)nud.MotionIndex, nud);
					break;
				case arFrame.Control.MotCommandButton.eCommand.AbsoluteMove:
				case arFrame.Control.MotCommandButton.eCommand.RelativeMove:

					var speed = (double)nudSpd.Value;
					var acc = (double)nudAcc.Value;




					var relative = false;
					if (ctl.motCommand == arFrame.Control.MotCommandButton.eCommand.RelativeMove)
						relative = true;

					var msg = string.Format("Do you want to change the motion position?\n" +
						"Axis : {0}\n" +
						"Current position : {1}\n" +
						"Target position : {2}\n" +
						"Please make sure to check for potential collisions during movement", axis, PUB.mot.GetActPos((short)nud.MotionIndex), pos);

					if (UTIL.MsgQ(msg) != System.Windows.Forms.DialogResult.Yes) return;

					if (!MOT.Move(axis, pos, speed, acc, relative))
						PUB.log.AddE("MOT:MOVE_:" + axis.ToString() + ",Msg=" + PUB.mot.ErrorMessage);
					break;
			}
		}

		void label_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
		{
			var ctl = sender as arFrame.Control.MotLinkLabel;
			PUB.ChangeUIPopup(ctl.motValueControl);
		}

		private void __Closed(object sender, FormClosedEventArgs e)
		{
			//this.bs.CurrentChanged -= this.bs_CurrentChanged_1;
			this.tmDisplay.Enabled = false;
			this.ds1.MCModel.TableNewRow -= Model_TableNewRow;
		}

		#region "Mouse Form Move"

		private Boolean fMove = false;
		private Point MDownPos;

		private void LbTitle_DoubleClick(object sender, EventArgs e)
		{
			if (this.WindowState == FormWindowState.Maximized) this.WindowState = FormWindowState.Normal;
			else this.WindowState = FormWindowState.Maximized;
		}
		private void LbTitle_MouseMove(object sender, MouseEventArgs e)
		{
			if (fMove)
			{
				Point offset = new Point(e.X - MDownPos.X, e.Y - MDownPos.Y);
				this.Left += offset.X;
				this.Top += offset.Y;
				offset = new Point(0, 0);
			}
		}
		private void LbTitle_MouseUp(object sender, MouseEventArgs e)
		{
			fMove = false;
		}
		private void LbTitle_MouseDown(object sender, MouseEventArgs e)
		{
			MDownPos = new Point(e.X, e.Y);
			fMove = true;
		}

		#endregion

		void log_RaiseMsg(DateTime LogTime, string TypeStr, string Message)
		{
			if (Message.StartsWith("[EO]") || Message.StartsWith("EO"))
			{
				return;
			}
			this.RtLog.AddMsg(LogTime, TypeStr, Message);
		}

		void Model_TableNewRow(object sender, DataTableNewRowEventArgs e)
		{
			// e.Row["SlotCount"] = 20;
		}

		private void tmDisplay_Tick(object sender, EventArgs e)
		{
			tabControl4.TabPages[0].Text = $"({axisIndex}) JOG";
	
				this.Text = "MODEL(MOTION) SETTING";

			if (PUB.mot.IsInit == false)
			{
				//if (groupBox3.Enabled == true) groupBox3.Enabled = false;
			}
			else
			{
				//if (groupBox3.Enabled == false) groupBox3.Enabled = true;

				//각축별 기본 상태를 표시해준다.
				//dvMot.SuspendLayout();
				for (int r = 0; r < dvMot.RowCount; r++) // 오류수정 2111221
				{
					var row = this.dvMot.Rows[r];
					var axis = short.Parse(row.Cells[0].Value.ToString());
					row.Cells[0].Style.BackColor = PUB.mot.IsServOn(axis) ? Color.Lime : Color.Tomato;
					row.Cells[2].Value = $"{PUB.mot.GetCmdPos(axis)}";
					row.Cells[3].Value = $"{PUB.mot.GetActPos(axis)}";
					row.Cells[4].Style.BackColor = PUB.mot.IsOrg(axis) ? Color.SkyBlue : Color.Gray;
                    row.Cells[4].Value = PUB.mot.IsOrg(axis) ?  "O" : "";
                    row.Cells[5].Style.BackColor = PUB.mot.IsLimitN(axis) ? Color.Red : Color.Gray;
                    row.Cells[5].Value = PUB.mot.IsLimitN(axis) ? "O" : "";
                    row.Cells[6].Style.BackColor = PUB.mot.IsLimitP(axis) ? Color.Red : Color.Gray;
                    row.Cells[6].Value = PUB.mot.IsLimitP(axis) ? "O" : "";
                    row.Cells[7].Style.BackColor = PUB.mot.IsInp(axis) ? Color.SkyBlue : Color.Gray;
                    row.Cells[7].Value = PUB.mot.IsInp(axis) ? "O" : "";
                    row.Cells[8].Style.BackColor = PUB.mot.IsServAlarm(axis) ? Color.Red : Color.Gray;
                    row.Cells[8].Value = PUB.mot.IsServAlarm(axis) ? "O" : "";
                    row.Cells[9].Style.BackColor = PUB.mot.IsHomeSet(axis) ? Color.Green : Color.Gray;
                    row.Cells[9].Value = PUB.mot.IsHomeSet(axis) ? "O" : "";
                    row.Cells[10].Value = PUB.mot.IsServOn(axis) ? "Servo On" : "Servo Off";
                }
				//dvMot.ResumeLayout();
			}
			// this.tblFG.Invalidate();
		}

		private void dv_DataError(object sender, DataGridViewDataErrorEventArgs e)
		{

		}

		#region "jog function"

		private void button1_Click(object sender, EventArgs e)
		{
			//절대값 이동
			var pos = (double)nudPosAbs.Value;
			var vel = (double)nudJogVel.Value;

			var msg = $"Move motion({axis}) coordinate to ({pos})?";
			if (UTIL.MsgQ(msg) != DialogResult.Yes) return;

			MOT.Move(this.axis, pos, vel, 500, false, !chkJogMoveForce.Checked, !chkJogMoveForce.Checked);
			PUB.log.AddI(string.Format("Axis {0} manual movement(ABS) {1}mm", axisIndex, pos));
		}

		private void button3_Click_1(object sender, EventArgs e)
		{

			//상대값 이동
			var pos = (double)nudPosRel.Value;
			var vel = (double)nudJogVel.Value;

			if(pos == 0.0)
			{
				UTIL.MsgE("Value cannot be (0) for relative movement",true);
				return;
			}

			var msg = $"Move motion({axis}) coordinate by ({pos}) from current position?";
			if (UTIL.MsgQ(msg) != DialogResult.Yes) return;

			MOT.Move(this.axis, pos, vel, 500, true, !chkJogMoveForce.Checked, !chkJogMoveForce.Checked);
			PUB.log.AddI(string.Format("Axis {0} manual movement(REL) {1}mm", axisIndex, pos));
		}


		private void btJogHome_Click(object sender, EventArgs e)
		{
			//jog-home
			var dlg = UTIL.MsgQ(string.Format("Execute home search for axis {0}?", this.axis));
			if (dlg != System.Windows.Forms.DialogResult.Yes) return;
			var rlt = MOT.Home("Model(UserControl)", this.axis);
			if (rlt == false)
			{
				UTIL.MsgE(PUB.mot.ErrorMessage);
				return;
			}
			PUB.log.Add(string.Format("user click : home ({0})", axisIndex));
		}

		private void btJogPClear_Click(object sender, EventArgs e)
		{
			var dlg = UTIL.MsgQ("Initialize position values?\n" +
				"Make sure to perform home operation before actual use");
			if (dlg != System.Windows.Forms.DialogResult.Yes) return;
			//jog pos-clear            
			PUB.mot.ClearPosition((short)axisIndex);
			PUB.mot.SetHomeSet(axisIndex, false); //홈셋도 풀어야한다  201222
			PUB.log.Add(string.Format("user click : pos clear ({0})", axisIndex));
		}

		private void btJogAClear_Click(object sender, EventArgs e)
		{
			//jog-alaram clear
			PUB.mot.SetAlarmClearOn(this.axisIndex);
			System.Threading.Thread.Sleep(200);
			PUB.mot.SetAlarmClearOff(this.axisIndex);
			PUB.log.Add(string.Format("user click : alarm clear ({0})", axisIndex));
		}

		private void btJogBrake_Click(object sender, EventArgs e)
		{
			//jog-brake
			//var curstate = Util_DO.GetIOOutput(eDOName.BRAKE_OFF);
			//Util_DO.SetBrake(!curstate);
			//Pub.log.Add(string.Format("user click : set brake ({0})", axisIndex));
		}

		private void btJogSVon_Click(object sender, EventArgs e)
		{
			//jog-svon
			var curstate = PUB.mot.IsServOn(axisIndex);
			if (curstate)
			{
				var dlg = UTIL.MsgQ("Turn OFF SERVO-ON status?\n\nWhen turned OFF, HOME-SET status will also be turned OFF");
				if (dlg != DialogResult.Yes) return;
			}
			PUB.mot.SetServOn((short)axisIndex, !curstate);
			PUB.log.Add(string.Format("user click : servo on ({0})", axisIndex));
		}


		private void btJogStop_Click(object sender, EventArgs e)
		{
			//jog-stop
			PUB.mot.MoveStop("JOG", this.axisIndex);
			PUB.log.Add(string.Format("user click : move stop ({0})", axisIndex));
		}

		private void btJogDown_Click(object sender, MouseEventArgs e)
		{
			//jog-moouse down
			var bt = sender as Button;
			var tag = bt.Tag.ToString();
			var vel1 = (double)this.nudJogVel.Value;
			var acc1 = (double)this.nudJogAcc.Value;

			var motDir = arDev.MOT.MOTION_DIRECTION.Positive;
			if (tag == "CCW") motDir = arDev.MOT.MOTION_DIRECTION.Negative;

			Boolean jogMoveForce = this.chkJogMoveForce.Checked;
			if (!MOT.JOG(this.axisIndex, motDir, vel1, acc1, acc1, false, !jogMoveForce, !jogMoveForce))
				PUB.log.AddE("MOT:JOG:" + tag + ":" + PUB.mot.ErrorMessage);

			PUB.log.Add(string.Format("user click : jog start ({0}) - {1}", axisIndex, tag));
		}

		private void btJogUp_Click(object sender, MouseEventArgs e)
		{
			//jog-mouseup
			var bt = sender as Button;
			var tag = bt.Tag.ToString();
			//Pub.mot.MoveStop("JOG", this.axisIndex);   //선택된 축을 멈춘다.
			MOT.Stop((eAxis)this.axisIndex, "JOG");
			PUB.log.Add(string.Format("user click : jog stop ({0})", axisIndex));
		}

		#endregion

		void ChangeCurrentPosition(short Axis, NumericUpDown valueCtl)
		{
			valueCtl.Value = (decimal)PUB.mot.GetActPos(Axis);
		}
		/// <summary>
		/// 상단목록에서 모션을 선택한 경우
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
		private void MotAxisSelect(int axisindex, string source)
		{
			if (tabControl4.Tag != null && tabControl4.Tag.ToString().Equals(axisindex.ToString()))
				return;

			this.tabControl4.Tag = axisindex;

			//if(this.listView1.FocusedItem == null)
			//{
			//	Util.MsgE("선택된 모델이 없습니다\n\n좌측 목록에서 모델을 선택 하세요");
			//}

			RefreshMotorPosition($"motaxis({source})");
		}

		private void bs_CurrentChanged_1(object sender, EventArgs e)
		{
			//if (pauserefreshmot == true) return;

			//RefreshMotorPosition("bs");
			//BindingData();
		}
		void RefreshMotorPosition(string source)
		{
			if (listView1.FocusedItem == null)
			{
				bsPosData.Filter = "motindex=99 and PosTitle='영구없다'";
				return;
			}
			var lvitem = listView1.FocusedItem; lvitem.Selected = true;
			var idx = int.Parse(listView1.FocusedItem.Tag.ToString());


			var dr = ds1.MCModel.Where(t => t.idx == idx).FirstOrDefault();
			if (dr == null)
			{
				UTIL.MsgE($"No data found for selected index({idx}). \nPlease try again", true);
				bsPosData.Filter = "motindex=99 and PosTitle='영구없다'";
				return;
			}

			if (lvitem.Text != lbModelTitle.Text)
			{
				lbModelTitle.BackColor = Color.Red;
				lbModelTitle.BackColor2 = Color.Tomato;
			}
			else
			{
				lbModelTitle.BackColor = Color.Gray;
				lbModelTitle.BackColor2 = Color.FromArgb(100, 100, 100);
			}
				
			


			this.tabControl5.TabPages[0].Text = $"[{dr.Title}] Motion Status";
			this.tabControl1.TabPages[0].Text = $"[{dr.Title}-M{this.axisIndex}] Position Data";


			RtLog.AddMsg($"Motion coordinate value check ({dr.Title}[{dr.idx}], Axis: {this.axisIndex})");


			//var rowindex = dvMot.SelectedCells[0].RowIndex;
			//var row = dvMot.Rows[rowindex];
			//var axisIndex = short.Parse(row.Cells[0].Value.ToString());
			//var axis = (eAxis)this.axisIndex;
			//var axisTitle = row.Cells[1].Value.ToString();
			{


				//위치정보 표시
				bsPosData.Filter = string.Format("pidx={0} and motindex = {1} and PosTitle not like 'XX_%'", dr.idx, this.axisIndex);

				RtLog.AddMsg($"({bsPosData.Count}) data items confirmed");


				//(위치정보) 데이터수량이 맞지 않으면 재 생성한다
				string[] list = null;
				Array val = null;
				Type axType = null;
				var axis = (eAxis)axisIndex;

				if (axis == eAxis.PX_PICK) axType = typeof(ePXLoc);
				else if (axis == eAxis.PZ_PICK) axType = typeof(ePZLoc);
				else if (axis == eAxis.Z_THETA) axType = typeof(ePTLoc);

				else if (axis == eAxis.PL_MOVE) axType = typeof(eLMLoc);
				else if (axis == eAxis.PL_UPDN) axType = typeof(eLZLoc);
				else if (axis == eAxis.PR_MOVE) axType = typeof(eRMLoc);
				else if (axis == eAxis.PR_UPDN) axType = typeof(eRZLoc);

				if (axType == null)
				{
					UTIL.MsgE("Position information for specified axis is not defined");
					return;
				}

				list = Enum.GetNames(axType);
				val = Enum.GetValues(axType);

				var sb = new System.Text.StringBuilder();
				var cntI = 0;
				var cntE = 0;
				var cntD = 0;

				//posidx == -1인 데이터는 모두 소거한다
				var dellist = ds1.MCModel.Where(t => t.pidx == dr.idx && t.MotIndex == this.axisIndex && t.PosIndex == -1).ToList();
				if (dellist.Any())
				{
					RtLog.AddMsg($"Motion ({axisIndex}) has {dellist.Count} data items with position information -1, deleting them");
					cntD += dellist.Count;
					foreach (var item in dellist)
						ds1.MCModel.RemoveMCModelRow(item);

					//삭제되었으니 적용처리한다
					ds1.MCModel.AcceptChanges();
				}

				//모든데이터의 체크상태를 off한다.
				//작업완료후 CHK가 false 인 데이터는 삭제 처리 한다.
				var alllist = this.ds1.MCModel.Where(t => t.pidx == dr.idx && t.MotIndex == this.axisIndex);
				alllist.ToList().ForEach(t => t.Check = false);
				ds1.MCModel.AcceptChanges();

				//list는 각 모션의 위치정보 enum list 값이다.
				for (int i = 0; i < list.Length; i++)
				{
					var arrTitle = list[i];
					var vv = val.GetValue(i);
					var arrIndex = (byte)vv;// ((eAxis)(val.GetValue(i)));
					//if (arrIndex < 50) continue;     //여기는 예약된 위치값이므로 사용하지 않는다
					var targetem = Enum.Parse(axType, vv.ToString());

					//이 값이 데이터가 없다면 추가하고, 있다면 이름을 검사해서 결과를 안내한다
					var pDr = alllist.Where(t => t.PosIndex == arrIndex).FirstOrDefault();
					if (pDr == null)
					{
						cntI += 1;
						var newdr = this.ds1.MCModel.NewMCModelRow();

						if (ds1.MCModel.Rows.Count == 0) newdr.idx = 1;
						else newdr.idx = ds1.MCModel.Max(t => t.idx) + 1;

						newdr.pidx = dr.idx;
						newdr.MotIndex = this.axisIndex;
						newdr.PosIndex = (short)arrIndex;
						newdr.PosTitle = arrTitle;
						newdr.Position = 0.0;
						newdr.Speed = 50;
						newdr.SpeedAcc = 100;
						newdr.Check = true;
						newdr.Description = targetem.DescriptionAttr();
						newdr.Category = targetem.CategoryAttr();

						this.ds1.MCModel.AddMCModelRow(newdr);
						newdr.EndEdit();
						sb.AppendLine("Item added: " + arrTitle);
					}
					else
					{
						//이름이 다르다면 추가해준다.
						if (pDr.PosTitle != arrTitle)
						{
							sb.AppendLine("(Position) Item changed: " + pDr.PosTitle + " => " + arrTitle);
							cntE += 1;
							pDr.PosTitle = arrTitle;
						}
						pDr.Description = targetem.DescriptionAttr();
						//pDr.Category = targetem.CategoryAttr();
						pDr.Check = true;
						pDr.EndEdit();
					}
				}
				ds1.MCModel.AcceptChanges();

				//미사용개체 삭제한다
				var NotUseList = alllist.Where(t => t.Check == false).ToList();
				if (NotUseList.Any())
				{
					cntD += NotUseList.Count();
					foreach (var item in NotUseList)
						ds1.MCModel.RemoveMCModelRow(item);

					//삭제한 대상이 있으니적용처리
					ds1.MCModel.AcceptChanges();
				}






				if (cntI > 0) sb.AppendLine("Added count: " + cntI.ToString());
				if (cntE > 0) sb.AppendLine("Changed count: " + cntE.ToString());
				if (cntD > 0) sb.AppendLine("Deleted count: " + cntD.ToString());

				//최종 확정
				this.ds1.MCModel.AcceptChanges();

				if (sb.Length > 0)
				{
					UTIL.MsgI(sb.ToString());
				}
			}
		}

		private void chkJogMoveForce_Click(object sender, EventArgs e)
		{
			if (chkJogMoveForce.Checked)
			{
				UTIL.MsgI(
					"Collision conditions are not checked during jog forced movement\n" +
					"Please make sure to check surrounding obstacles when moving shuttle\n" +
					"'Forced movement' should only be used during teaching operations");
			}
		}

		//private void button6_Click(object sender, EventArgs e)
		//{
		//	//적용

		//	this.bs.EndEdit();
		//	this.bsPosData.EndEdit();
		//	this.Validate();

		//	var drv = this.bs.Current as DataRowView;
		//	if (drv == null) return;
		//	var dr = drv.Row as DataSet1.MCModelRow;

		//	this.Value = dr.Title;

		//	if (Pub.LockModel.WaitOne(1) == true)
		//	{
		//		Pub.LockModel.Reset();
		//		Pub.log.AddI("모션모델을 적용 합니다");
		//		Pub.Result.mModel.ReadValue(dr.Title, this.ds1.MCModel);
		//		Pub.LockModel.Set();
		//		if (Pub.Result.mModel.isSet)
		//		{
		//			Pub.log.AddAT("모션모델선택완료 : " + Pub.Result.mModel.Title);
		//		}
		//		else Util.MsgE("적용 실패\n\n대상 모델 명이 없습니다");
		//	}
		//	else
		//	{
		//		Util.MsgE("모션 적용 실패\n잠시 후 다시 시도하세요");
		//	}

		//}



		private void arDatagridView2_CellClick(object sender, DataGridViewCellEventArgs e)
		{
			//position click
			var dv = sender as DataGridView;
			var col = this.dvPosition.Columns[e.ColumnIndex];
			var colName = col.Name.ToLower();
			if (colName == "btgo")
			{
				if (PUB.mot.HasHomeSetOff)
				{
					UTIL.MsgE("Motion home is not completed\nPlease proceed with 'Device Initialization' from main screen");
					return;
				}
				//현재값으로 모터를 이동
				//현재위치값으로 설정
				var cell = dv.Rows[e.RowIndex].Cells["btpos"];
				var value = (double)cell.Value;
				var drv = this.bsPosData.Current as DataRowView;
				var drParent = drv.Row as DataSet1.MCModelRow;

				//일반 속도값을 찾는다
				//var speedDr = drParent.Speed;//  this.ds1.MCModel.Where(t => t.pidx == drParent.idx && t.MotIndex == axisIndex && t.PosIndex == -1 && t.SpdIndex == (int)eAxisSpeed.Normal).FirstOrDefault();
				var speed = drParent.Speed;// speedDr.Speed;// (double)this.nudJogVel.Value;
				var acc = drParent.SpeedAcc;// speedDr.SpeedAcc;// ;  (double)nudAcc.Value;


				var relative = false;
				//if (ctl.motCommand == arFrame.Control.MotCommandButton.eCommand.RelativeMove)
				//    relative = true;

				var msg = string.Format("Do you want to change the motion position?\n" +
					"Axis : {0}\n" +
					"Current position : {1}\n" +
					"Target position : {2}\n" +
					"Movement speed : {3}(Acceleration:{4})\n" +
					"Please make sure to check for potential collisions during movement", axis, PUB.mot.GetActPos(axisIndex), value, speed, acc);

				if (UTIL.MsgQ(msg) != System.Windows.Forms.DialogResult.Yes) return;

				if (!MOT.Move(axis, value, speed, acc, relative, !chkJogMoveForce.Checked, !chkJogMoveForce.Checked))
					PUB.log.AddE("MOT:MOVE_:" + axis.ToString() + ",Msg=" + PUB.mot.ErrorMessage);



			}
			else if (colName == "btset")
			{
				if (PUB.mot.HasHomeSetOff)
				{
					UTIL.MsgE("Motion home is not completed\nPlease proceed with 'Device Initialization' from main screen");
					return;
				}

				//현재위치값으로 설정
				var cell = dv.Rows[e.RowIndex].Cells["btpos"];
				var value = (double)cell.Value;
				var nValue = Math.Round(PUB.mot.GetCmdPos(this.axisIndex), 4); //소수점4자리에서 반올림처리한다 210414

				var msg1 = string.Format("Do you want to change the motion settings?\n" +
					   "Axis : {0}\n" +
					   "Before : {1}\n" +
					   "After : {2}\n" +
					   "You must press 'Save' after change to record permanently", this.axis, value, nValue);

				if (UTIL.MsgQ(msg1) != System.Windows.Forms.DialogResult.Yes) return;
				cell.Value = nValue;
			}
			else if (colName == "btpos")
			{
				//현재값 변경 팝업
				var cell = dv.Rows[e.RowIndex].Cells[e.ColumnIndex];
				var value = (double)cell.Value;
				value = PUB.ChangeValuePopup(value, "Position Input");
				cell.Value = value;
			}
			else if (colName == "btspeed")
			{
				//현재값 변경 팝업
				var cell = dv.Rows[e.RowIndex].Cells[e.ColumnIndex];
				var value = (double)cell.Value;

				var maxvalue = PUB.system_mot.GetMaxSpeed[this.axisIndex];
				if (maxvalue == 0) maxvalue = 1000;
				value = PUB.ChangeValuePopup(value, $"Speed Input(Max:{maxvalue}mm/s)");
				if(value > maxvalue)
				{
					UTIL.MsgE($"Input value({value}) exceeds maximum value({maxvalue}).\nPlease input again");
					//cell.Value = maxvalue;
				}
				else
				{
					cell.Value = value;
				}
				
			}
			else if (colName == "btacc")
			{
				//현재값 변경 팝업
				var cell = dv.Rows[e.RowIndex].Cells[e.ColumnIndex];
				var value = (double)cell.Value;

				var maxvalue = PUB.system_mot.GetMaxAcc[this.axisIndex];
				if (maxvalue == 0) maxvalue = 2000;
				value = PUB.ChangeValuePopup(value, $"Acceleration Input(Max:{maxvalue}mm/s)");
				if (value > maxvalue)
				{
					UTIL.MsgE($"Input value({value}) exceeds maximum value({maxvalue}).\nPlease input again");
					//cell.Value = maxvalue;
				}
				else
				{
					cell.Value = value;
				}
			}
			else if (colName == "btdcc")
			{
				//현재값 변경 팝업
				var cell = dv.Rows[e.RowIndex].Cells[e.ColumnIndex];
				if (cell.Value.ToString().isEmpty()) cell.Value = "0";
				var value = (double)cell.Value;

				var maxvalue = PUB.system_mot.GetMaxAcc[this.axisIndex];
				if (maxvalue == 0) maxvalue = 2000;
				value = PUB.ChangeValuePopup(value, $"Deceleration Input(Max:{maxvalue}mm/s)");
				if (value > maxvalue)
				{
					UTIL.MsgE($"Input value({value}) exceeds maximum value({maxvalue}).\nPlease input again");
					//cell.Value = maxvalue;
				}
				else
				{
					cell.Value = value;
				}
			}

		}

		private void linkLabel8_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
		{
			//jopgspeed
			var value = (double)nudJogVel.Value;
			value = PUB.ChangeValuePopup(value, "Speed Input");
			nudJogVel.Value = (decimal)value;
		}

		private void linkLabel10_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
		{
			//absvalue
			var value = (double)this.nudPosAbs.Value;
			value = PUB.ChangeValuePopup(value, "Speed Input");
			nudPosAbs.Value = (decimal)value;
		}

		private void linkLabel11_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
		{
			//reelvalu
			var value = (double)nudPosRel.Value;
			value = PUB.ChangeValuePopup(value, "Speed Input");
			nudPosRel.Value = (decimal)value;
		}

		private void toolStripButton1_Click(object sender, EventArgs e)
		{
			var maxspeed = PUB.system_mot.GetMaxSpeed[this.axisIndex];
			if (maxspeed == 0) maxspeed = 1000;
			
			var dlg = UTIL.MsgQ($"Change speed of all movement coordinates in batch?\nMax:{maxspeed}mm/s");
			if (dlg != System.Windows.Forms.DialogResult.Yes) return;
			var value = PUB.ChangeValuePopup(100.0, "Batch Speed Change");

			if(value > maxspeed)
			{
				UTIL.MsgE($"Input value({value}) is greater than maximum value({maxspeed}). Please input again");
				return;
			}
			for (int i = 0; i < this.bsPosData.Count; i++)
			{
				this.bsPosData.Position = i;
				var drv = this.bsPosData.Current as DataRowView;
				if (drv == null) return;
				var dr = drv.Row as DataSet1.MCModelRow;
				dr.Speed = value;
				dr.EndEdit();
			}
		}

		private void toolStripButton2_Click_2(object sender, EventArgs e)
		{
			var maxspeed = PUB.system_mot.GetMaxAcc[this.axisIndex];
			if (maxspeed == 0) maxspeed = 2000;

			var dlg = UTIL.MsgQ($"Change acceleration/deceleration of all movement coordinates in batch?\nMax:{maxspeed}mm/s");
			if (dlg != System.Windows.Forms.DialogResult.Yes) return;
			var value = PUB.ChangeValuePopup(100.0, "Batch Acceleration/Deceleration Change");

			if (value > maxspeed)
			{
				UTIL.MsgE($"Input value({value}) is greater than maximum value({maxspeed}). Please input again");
				return;
			}

			for (int i = 0; i < this.bsPosData.Count; i++)
			{
				this.bsPosData.Position = i;
				var drv = this.bsPosData.Current as DataRowView;
				if (drv == null) return;
				var dr = drv.Row as DataSet1.MCModelRow;
				dr.SpeedAcc = value;
				dr.EndEdit();
			}
		}

		private void toolStripButton3_Click_1(object sender, EventArgs e)
		{
			var maxspeed = PUB.system_mot.GetMaxAcc[this.axisIndex];
			if (maxspeed == 0) maxspeed = 2000;

			var dlg = UTIL.MsgQ($"Change deceleration of all movement coordinates in batch?\nMax:{maxspeed}mm/s");
			if (dlg != System.Windows.Forms.DialogResult.Yes) return;
			var value = PUB.ChangeValuePopup(0, "Batch Deceleration Change");

			if (value > maxspeed)
			{
				UTIL.MsgE($"Input value({value}) is greater than maximum value({maxspeed}). Please input again");
				return;
			}

			for (int i = 0; i < this.bsPosData.Count; i++)
			{
				this.bsPosData.Position = i;
				var drv = this.bsPosData.Current as DataRowView;
				if (drv == null) return;
				var dr = drv.Row as DataSet1.MCModelRow;
				dr.SpeedDcc = value;
				dr.EndEdit();
			}
		}


		private void dvMot_SelectionChanged(object sender, EventArgs e)
		{
			if (dvMot.SelectedRows.Count < 1)
			{
				Console.WriteLine("no selecte");
				this.axisIndex = -1;
				this.axis = (eAxis)axisIndex;
			}
			else
			{
				var selrow = dvMot.SelectedRows[0];
				this.axisIndex = short.Parse(selrow.Cells["dvc_axis"].Value.ToString());
				this.axis = (eAxis)axisIndex;
				MotAxisSelect(this.axisIndex, "dvmot");
				Console.WriteLine($"select indx {axisIndex}");
			}
		}

		private void motLinkLabel1_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
		{
			//jopgspeed
			var value = (double)nudJogAcc.Value;
			value = PUB.ChangeValuePopup(value, "Jog Acceleration Input");
			nudJogAcc.Value = (decimal)value;
		}


		private void linkLabel1_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
		{
			System.Windows.Forms.LinkLabel lv = sender as System.Windows.Forms.LinkLabel;
			var speed = int.Parse(lv.Text);
			nudJogVel.Value = speed;

		}

	

		private void toolStripButton6_Click(object sender, EventArgs e)
		{
			var f = new AR.Dialog.fInput("Enter model name",string.Empty);
			if (f.ShowDialog() != DialogResult.OK) return;

			//지정한 이름이있는지 확인한다.
			if (ds1.MCModel.Where(t => t.Title == f.ValueString).Any())
			{
				UTIL.MsgE("Name is already in use\n\n" + f.ValueString);
				return;
			}

			var newdr = this.ds1.MCModel.NewMCModelRow();// this.bs.AddNew() as DataRowView;
			newdr.Title = f.ValueString;
			newdr.pidx = -1; //메인 모델은 pidx값이 -1이다
			newdr.PosIndex = -1;
			newdr.idx = this.ds1.MCModel.Max(t => t.idx) + 1; //현재 인덱스에 더 크게 입력한다
			newdr.EndEdit();
			this.ds1.MCModel.AddMCModelRow(newdr);
			this.ds1.MCModel.AcceptChanges();

			//데이터를 추가 했으니 목록 추가를 해준다.
			var lv = listView1.Items.Add(newdr.Title);
			lv.Tag = newdr.idx;

		}

		private void toolStripButton7_Click(object sender, EventArgs e)
		{
			if (this.listView1.FocusedItem == null)
			{
				UTIL.MsgE("Select target to delete and try again", true);
				return;
			}
			var idx = int.Parse(listView1.FocusedItem.Tag.ToString());
			var dr = this.ds1.MCModel.Where(t => t.idx == idx).FirstOrDefault();
			if (dr == null)
			{
				UTIL.MsgE($"No data found for index({idx}) value.\nPlease try again");
				return;
			}

			var dlg = UTIL.MsgQ("Delete currently selected data?\n\n" +
				$"Model name : {dr.Title}\n" +
				$"Model number : ({dr.idx})");

			if (dlg != System.Windows.Forms.DialogResult.Yes) return;

			this.ds1.MCModel.RemoveMCModelRow(dr);
			this.ds1.MCModel.AcceptChanges();
			this.listView1.Items.Remove(listView1.FocusedItem);

			//데이터가 있다면 첫번쨰 자료를 선택한다.
			RefreshMotorPosition("delete button");
		}

		private void toolStripButton8_Click(object sender, EventArgs e)
		{
			//button - save
			this.Validate();
			this.bsPosData.EndEdit();
			this.Validate();

			if (PUB.PasswordCheck() == false)
			{
				UTIL.MsgE("Password incorrect");
				return;
			}

			//기존의 데이터와 다른점을 표시해준다.
			var sb = new System.Text.StringBuilder();

			//현재 데이터 중 부모데이터가 없는 자료를 삭제한다.
			List<DataSet1.MCModelRow> delrows = new List<DataSet1.MCModelRow>();
			foreach (var grpdata in this.ds1.MCModel.Where(t => t.pidx != -1).GroupBy(t => t.pidx))
			{
				var pidx = grpdata.Key;
				//이 데이터의 부모가 존재하는지 확인
				if (ds1.MCModel.Where(t => t.idx == pidx && t.pidx == -1).Any() == false)
				{
					//삭제 대상에 넣는다.
					foreach (var dr in grpdata)
					{
						delrows.Add(dr);
					}
				}
			}

			//빈데이터삭제
			if (delrows.Any())
			{
				sb.AppendLine($"Empty data deleted {delrows.Count} items");
				for (int i = 0; i < delrows.Count; i++)
					ds1.MCModel.RemoveMCModelRow(delrows[i]);
				ds1.MCModel.AcceptChanges();
			}

			//현재데이터에는 있는데 기존에는 없는 것을 찾는다
			foreach (DataSet1.MCModelRow dr in ds1.MCModel)
			{
				//if (dr.RowState == DataRowState.Detached || dr.RowState == DataRowState.Deleted) continue;
				var mpos = PUB.mdm.dataSet.MCModel.Where(t => t.pidx == dr.pidx && t.MotIndex == dr.MotIndex && t.PosIndex == dr.PosIndex);
				if (mpos.Any() == false)
				{
					sb.AppendLine($"[Added] Mot({dr.MotIndex}) {dr.PosTitle}({dr.Position})");
				}
				else
				{
					var first = mpos.First();
					if (dr.Position != first.Position || dr.PosTitle != first.PosTitle)
					{
						sb.AppendLine($"[Changed] Mot({first.MotIndex}) {first.PosTitle}({first.Position}) => {dr.PosTitle}({dr.Position})");
						//sb.AppendLine($" => {dr.PosTitle}({dr.Position})");
					}
				}
			}

			//삭제건확인
			foreach (DataSet1.MCModelRow dr in PUB.mdm.dataSet.MCModel)
			{
				//if (dr.RowState == DataRowState.Detached || dr.RowState == DataRowState.Deleted) continue;
				//서버데이터인데..나한테 존재하지 않으면 오류 처리핟.
				var mpos = ds1.MCModel.Where(t => t.MotIndex == dr.MotIndex && t.PosIndex == dr.PosIndex);
				if (mpos.Any() == false)
				{
					sb.AppendLine($"[Deleted] M={dr.MotIndex},P={dr.PosIndex},T={dr.PosTitle},V={dr.Position}");
				}
			}

			if (sb.Length > 0)
			{
				UTIL.MsgI("The following items have been changed\n" + sb.ToString());
			}
			else PUB.log.AddI("No motion information changed");

//			if (PUB.LockModel.WaitOne(1000) ==false)
			{
				//PUB.LockModel.Reset();
				try
				{
					this.ds1.AcceptChanges();
					PUB.mdm.dataSet.MCModel.Clear();
					PUB.mdm.dataSet.MCModel.Merge(this.ds1.MCModel);
					PUB.mdm.dataSet.AcceptChanges();
					PUB.mdm.SaveModelM();
					ds1.MCModel.AcceptChanges();

					//변경된데이터를 바로 적용 합니다
					var curmodelnmae = PUB.Result.mModel.Title;
					if (curmodelnmae.isEmpty())
					{
						UTIL.MsgE("No specified model, values will not be applied\nPlease select work model again", true);
					}
					else
					{
						PUB.log.AddI($"Applying motion model ({curmodelnmae})");
						PUB.Result.mModel.ReadValue(curmodelnmae);
						if (PUB.Result.mModel.isSet)
						{
							PUB.log.AddAT("Motion model application completed: " + PUB.Result.mModel.Title);
						}
						else UTIL.MsgE($"Motion model application failed\n\nTarget model name({curmodelnmae}) not found");
					}



				}
				catch (Exception ex)
				{
					PUB.log.AddE(ex.Message);
				}
				finally
				{
					//PUB.LockModel.Set();
				}






			}
			//else Util.MsgE("모델정보 저장 실패\n잠시 후 다시 시도하세요");
		}

		private void btCopy_Click(object sender, EventArgs e)
		{
			if (this.listView1.FocusedItem == null)
			{
				UTIL.MsgE("Select model to copy", true);
				return;
			}

			var idx = int.Parse(this.listView1.FocusedItem.Tag.ToString());
			var dr = ds1.MCModel.Where(t => t.idx == idx).FirstOrDefault();// drv.Row as DataSet1.MCModelRow;
			if (dr == null)
			{
				UTIL.MsgE($"Cannot find data for model number({idx})\n\nPlease try again");
				return;
			}

			var dlg = UTIL.MsgQ(string.Format("Copy the following model information?\n\nModel name : {0}", dr.Title));
			if (dlg != System.Windows.Forms.DialogResult.Yes) return;

			var newdr = this.ds1.MCModel.NewMCModelRow();
			UTIL.CopyData(dr, newdr);

			var newnameidx = 1;
			while (true)
			{
				var newname = dr.Title + $"-Copy({newnameidx++})-";
				if (ds1.MCModel.Where(t => t.Title == newname).Any() == false)
				{
					newdr.Title = newname;
					break;
				}
			}

			newdr.idx = this.ds1.MCModel.Max(t => t.idx) + 1;
			newdr.EndEdit();
			this.ds1.MCModel.AddMCModelRow(newdr);
			this.ds1.MCModel.AcceptChanges();

			//목록추가해준다.
			var lv = this.listView1.Items.Add(newdr.Title);
			lv.Tag = newdr.idx;

			//상세내역 복사해준다.
			var childs = ds1.MCModel.Where(t => t.pidx == dr.idx).ToArray();
			foreach (var dr2 in childs)
			{
				var newdr2 = this.ds1.MCModel.NewMCModelRow();
				UTIL.CopyData(dr2, newdr2); //모든자료를 먼저 복사한다.
				newdr2.pidx = newdr.idx;    //인덱스를 바꿔준다.
				newdr2.EndEdit();
				newdr2.idx = this.ds1.MCModel.Max(t => t.idx) + 1;
				this.ds1.MCModel.AddMCModelRow(newdr2);
			}
			this.ds1.MCModel.AcceptChanges();
			PUB.log.Add($"{dr.Title} model copy => {newdr.Title}");
		}

		private void toolStripButton10_Click(object sender, EventArgs e)
		{
			if (PUB.sm.Step == eSMStep.RUN || PUB.sm.Step == eSMStep.WAITSTART || PUB.sm.Step == eSMStep.PAUSE)
			{
				UTIL.MsgE("Cannot change model because currently operating (waiting)");
				return;
			}
			//select
			this.Validate();
			if (listView1.FocusedItem == null) return;
			if (hasChanged())
			{
				UTIL.MsgE("Cannot select model because there are unsaved changes", true);
				return;
			}

			this.Value = listView1.FocusedItem.Text;
			DialogResult = System.Windows.Forms.DialogResult.OK;
		}

		private void toolStripButton11_Click(object sender, EventArgs e)
		{

		}

		private void 그룹설정ToolStripMenuItem_Click(object sender, EventArgs e)
		{
			var f = new Dialog.Model_Motion_Desc(this.ds1);
			f.ShowDialog();
		}

		private void toolStripButton11_ButtonClick(object sender, EventArgs e)
		{
			if (this.listView1.FocusedItem == null)
			{
				UTIL.MsgE("Select a model", true);
				return;
			}
			var idx = int.Parse(listView1.FocusedItem.Tag.ToString());
			var dr = this.ds1.MCModel.Where(t => t.idx == idx).FirstOrDefault();
			if (dr == null)
			{
				UTIL.MsgE($"No data found for index({idx})\n\nPlease try again", true);
				return;
			}

			using (var f = new Dialog.Motion_MoveToGroup(this.ds1, dr.idx))
				f.ShowDialog();
		}

		private void btJogLeft_Click(object sender, EventArgs e)
		{

		}

		private void dvPosition_DataError(object sender, DataGridViewDataErrorEventArgs e)
		{

		}

		private void listView1_SelectedIndexChanged(object sender, EventArgs e)
		{
			if (listView1.FocusedItem == null)
			{
				//Util.MsgE("모델을 다시 선택하세요");
				return;
			}
			RefreshMotorPosition("listview selinde");
		}

		private void btEdit_Click(object sender, EventArgs e)
		{
			if (this.listView1.FocusedItem == null)
			{
				UTIL.MsgE("Select target to change and try again", true);
				return;
			}
			var idx = int.Parse(listView1.FocusedItem.Tag.ToString());
			var dr = this.ds1.MCModel.Where(t => t.idx == idx).FirstOrDefault();
			if (dr == null)
			{
				UTIL.MsgE($"No data found for index({idx}) value.\nPlease try again");
				return;
			}

			var f = new AR.Dialog.fTouchKeyFull("Change Model Name", dr.Title);
			if (f.ShowDialog() != DialogResult.OK) return;

			var valstr = f.tbInput.Text.Trim();
			if (dr.Title.Equals(valstr))
			{
				UTIL.MsgE("Name has not been changed", true);
				return;
			}

			if (ds1.MCModel.Where(t => t.Title == valstr).Any())
			{
				UTIL.MsgE("Name already exists", true);
				return;
			}

			var dlg = UTIL.MsgQ("Change the name of currently selected model?\n\n" +
				$"Before : {dr.Title}\n" +
				$"After : {valstr}");

			if (dlg != System.Windows.Forms.DialogResult.Yes) return;

			dr.Title = valstr;
			dr.EndEdit();
			this.ds1.MCModel.AcceptChanges();

			this.listView1.FocusedItem.SubItems[0].Text = valstr;

			RefreshMotorPosition("edit button");
		}
	}
}

