#ifndef __HCM4A_CalcFS4A_dtCtrl_h_
#define __HCM4A_CalcFS4A_dtCtrl_h_

#include "dtPack.h"

//!---------------------------------------------------------------------------------------------

/// dlg for add value to DropList
String ShowListEditDlg(){
	TopWindow  dlg;
	dlg.Title("Add to the list...");
	dlg.SetRect(0, 0, Zx(200), Zy(20));
	EditString text;
	dlg.Add(text.TopPosZ(0, 20).HSizePos());
	text.SetData("");
	dlg.Run();
	return (String)text.GetData();
}
//!---------------------------------------------------------------------------------------------

class LayGridViewH: public WithLayGrid<ParentCtrl> {
public:
	typedef LayGridViewH CLASSNAME;
	GridCtrl grid;
	void ToCtrl(const HcmData& hcmData);
	void ToCtrl(const HcmPack& hcmPack);
	int GetCurSelID();
	void SetFirstRec();
	void Clear();
	void Serialize(Stream& s);
	LayGridViewH(const Vector<FldCVE>& vec);
protected:
	OneCveList fldCveList;
	void Setup();
};
LayGridViewH::LayGridViewH(const Vector<FldCVE>& vec){
	fldCveList.Set(vec);
	CtrlLayout(*this);
	Add(grid.SizePos());
	Setup();
}
void LayGridViewH::Serialize(Stream& s){
	grid.Serialize(s);
}
void LayGridViewH::Setup(){
	grid.Clear(true);
	grid.ColoringMode(1);
	grid.OddColor().ColoringMode(1);
	grid.EvenColor().ColoringMode(2);
	grid.Indicator(); //---------------
	grid.AddColumn("T_No", String(t_("№"))).Min(50).AlignLeft().SetDisplay(Single<ItemGrid>()).SetHeaderFont(Single<ItemGrid>().headFont);
	if(fldCveList.Get().GetCount()){
		for(int i=0; i<fldCveList.Get().GetCount(); i++){
			String title = "[" << fldCveList.Get()[i].GetCode() << "] " << fldCveList.Get()[i].GetName();
			String code =  fldCveList.Get()[i].GetCode();
			grid.AddColumn((const char *)code, String(t_(title))).Min(150).AlignLeft().SetDisplay(Single<ItemGrid>()).SetHeaderFont(Single<ItemGrid>().headFont);
		}
	}
	grid.RejectNullRow();
	//grid.Navigating();
	grid.SetToolBar();
	grid.Clipboard();
	grid.Absolute();
	grid.SetRowHeight(0, Single<ItemGrid>().headFont.GetHeight()+10); // header height = GridCtrl.height + 10
	grid.WhenMenuBar = Null;
}
void LayGridViewH::ToCtrl(const HcmData& hcmData){
	grid.Clear();
	if(fldCveList.Get().GetCount()){
		fldCveList.Fill(hcmData);
		grid.Add();
		grid("T_No") = 1;
		for(int i=0; i < fldCveList.Get().GetCount(); i++){
			const String code = fldCveList.Get()[i].GetCode();
			grid.Set(0, (const char *)code, fldCveList.Get()[i].GetValue());
		}
		grid.SetRowHeight(grid.GetRowCount(), Single<ItemGrid>().itemFont.GetHeight()*1.5);// row height = GridCtrl.height * 1.5
	}
}
void LayGridViewH::ToCtrl(const HcmPack& hcmPack){
	grid.Clear();
	for(int i=0; i<hcmPack.GetMap().GetCount(); i++){
		grid.Add();
		grid("T_No") = i+1;
		if(fldCveList.Get().GetCount()){
			const HcmData& hcmIN = hcmPack.GetHcmIN(i);
			fldCveList.Fill(hcmIN);
			for(int j=0; j < fldCveList.Get().GetCount(); j++){
				const String code = fldCveList.Get()[j].GetCode();
				grid.Set(i, (const char *)code, hcmIN.GetField(code).GetStr());
				// grid.Set(i, (const char *)code, hcmIN.GetMap()[j].GetStr());
				// LOG(Format("%s - %s", code, hcmIN.GetMap()[j].GetStr()));
			}
		}
		grid.SetRowHeight(grid.GetRowCount(), Single<ItemGrid>().itemFont.GetHeight()*1.5);// row height = GridCtrl.height * 1.5
	}
}
void LayGridViewH::Clear(){
	grid.Clear();
	fldCveList.ClearValue();
}
int LayGridViewH::GetCurSelID(){
	if(!grid.GetRowCount()) return -1;
	Value npp = grid("T_No");
	if(!npp.IsNull()){
		return int(npp)-1;
	}
	return -1;
}
void LayGridViewH::SetFirstRec(){
	if(grid.GetRowCount())
		grid.SetCursor(0);
}
//!---------------------------------------------------------------------------------------

class LayGridCNV: public WithLayGrid<ParentCtrl> {
public:
	typedef LayGridCNV CLASSNAME;
	GridCtrl grid;
	bool IsModified()const{return isModified;}
	void ToCtrl(const HcmData& hcmData);
	void FromCtrl(HcmData& hcmData);
	void Clear();
	void Serialize(Stream& s);
	void Set(const Vector<FldCVE>& vec){fldCveList.Set(vec);}
	LayGridCNV(bool isEditable);
	LayGridCNV(bool isEditable, const Vector<FldCVE>& vec);
protected:
	bool isEditable = false;
	bool isModified = false;
	OneCveList fldCveList;
	Array<Convert> lstConv;
	Array<DropList> lstDLST;
	Array<EditString> lstSTR;
	Array<EditInt> lstINT;
	Array<EditDouble> lstDBL;
	Array<DropDate> lstDATE;
	Array<Button> lstBTN;
	bool FillDropList(const String& code, DropList& dl);
	bool FillDropGrid(const String& code, DropGrid& dg);
	void CreateEdCtrl(const FldCVE& fld, const HcmEntity hcmEntity);
	void Setup();
};
LayGridCNV::LayGridCNV(bool isEditable):isEditable(isEditable){
	CtrlLayout(*this);
	Add(grid.SizePos());
	Setup();
}
LayGridCNV::LayGridCNV(bool isEditable, const Vector<FldCVE>& vec):isEditable(isEditable){
	CtrlLayout(*this);
	fldCveList.Set(vec);
	Add(grid.SizePos());
	Setup();
}
void LayGridCNV::Serialize(Stream& s){
	grid.Serialize(s);
}
void LayGridCNV::Setup(){
	grid.Clear(true);
	grid.ColoringMode(1);
	grid.OddColor().ColoringMode(1);
	grid.EvenColor().ColoringMode(2);
	grid.Indicator(); //---------------
	grid.AddColumn("T_CODE", String("")).Min(50).AlignLeft().SetDisplay(Single<ItemGrid>()).SetHeaderFont(Single<ItemGrid>().headFont);
	grid.AddColumn("T_NAME", String("")).Min(250).AlignLeft().SetDisplay(Single<ItemGrid>()).HeaderAlignCenter().SetHeaderFont(Single<ItemGrid>().headFont);
	//grid.AddColumn("T_VALUE", String("")).Min(250).AlignCenter().SetDisplay(Single<ItemGrid>()).HeaderAlignCenter().SetHeaderFont(Single<ItemGrid>().headFont);
	grid.AddColumn("T_VALUE", String("")).Min(250).AlignLeft().SetDisplay(Single<ItemGrid>()).HeaderAlignCenter().SetHeaderFont(Single<ItemGrid>().headFont);
	grid.RejectNullRow();
	grid.Navigating();
	grid.SetToolBar();
	grid.Clipboard();
	grid.Absolute();
	grid.SetRowHeight(0, Single<ItemGrid>().headFont.GetHeight()+10); // header height = GridCtrl.height + 10
}
void LayGridCNV::ToCtrl(const HcmData& hcmData){
	grid.Clear();
	if(fldCveList.Get().GetCount()){
		fldCveList.Fill(hcmData);
		for(int i=0; i < fldCveList.Get().GetCount(); i++){
			if(!isEditable){
				grid.Add();
				grid("T_CODE")  = fldCveList.Get()[i].GetCode();
				grid("T_NAME")  = fldCveList.Get()[i].GetName();
				grid("T_VALUE") = fldCveList.Get()[i].GetValue();
			}
			else{
				CreateEdCtrl(fldCveList.Get()[i], hcmData.GetEntity());
			}
			grid.SetRowHeight(grid.GetRowCount(), Single<ItemGrid>().itemFont.GetHeight()*1.5);// row height = GridCtrl.height * 1.5
		}
		isModified = false;
	}
}
void LayGridCNV::FromCtrl(HcmData& hcmData){
	if(!isEditable) return;
	isModified = false;
	for(int i = 0; i < grid.GetRowCount(); i++){
		if(grid.GetCtrl(i, 2) != nullptr){
			if(fldCveList.GetFld(grid.GetCell(i, "T_CODE").val).GetValue().ToString() != grid.GetCtrl(i, 2)->GetData().ToString()){
				isModified = true;
			}
			fldCveList.GetFld(grid.GetCell(i, "T_CODE").val.ToString()).SetValue(grid.GetCtrl(i, 2)->GetData());
		}
		else{
			if(fldCveList.GetFld(grid.GetCell(i, "T_CODE").val).GetValue().ToString() != grid.GetCell(i, "T_VALUE").val.ToString()){
				isModified = true;
			}
			fldCveList.GetFld(grid.GetCell(i, "T_CODE").val.ToString()).SetValue(grid.GetCell(i, "T_VALUE").val.ToString());
		}
	}
	if(isModified){
		// save to hcmData
		for(int i=0; i < fldCveList.Get().GetCount(); i++){
			hcmData.EditVal(fldCveList.Get()[i].GetCode(), fldCveList.Get()[i].GetValue().ToString());
		}
	}
}
bool LayGridCNV::FillDropList(const String& code, DropList& dl){
	Single<HcmLstData>().GetLst(code).Fill(dl);
	return dl.GetCount();
}
bool LayGridCNV::FillDropGrid(const String& code, DropGrid& dg){
	Single<HcmLstData>().GetLst(code).Fill(dg);
	return dg.GetCount();
}
void LayGridCNV::CreateEdCtrl(const FldCVE& fcve, const HcmEntity hcmEntity){
	Font vFont = StdFont().Height(StdFont().GetHeight()+3).Bold();
	grid.Add();
	grid("T_CODE") = fcve.GetCode();
	grid("T_NAME") = fcve.GetName();
	bool isCheckMandat = Single<AppCFG>().cfgEditRec.GetIsInControl() && fcve.GetDescr().IsMandat();
	switch(fcve.GetDescr().GetFldEditType()){
		case FldEditType::NONE:
			grid("T_VALUE") = fcve.GetValue();
		break;
		case FldEditType::STR:
		{
			if(!fcve.GetIsEdit()){
				grid("T_VALUE") = fcve.GetValue();
				break;
			}
			if(grid.GetCtrl(2) == NULL){
				grid.SetCtrl(2, lstSTR.Add().SetConvert(lstConv.Add(new HcmConvert(fcve, hcmEntity, isCheckMandat))).SetFont(vFont));
			}
			grid("T_VALUE") = fcve.GetValue().ToString();
			if(grid.GetCtrl(2) != NULL){
				grid.GetCtrl(2)->SetData(fcve.GetValue().ToString());
				grid.GetCtrl(2)->Refresh();
			}
		}
		break;
		case FldEditType::INT:
			if(!fcve.GetIsEdit()){
				grid("T_VALUE") = fcve.GetValue();
				break;
			}
			if(grid.GetCtrl(2) == NULL){
				if(grid.GetCtrl(2) == NULL){
					if(fcve.GetDescr().GetMin()!=0 ||fcve.GetDescr().GetMax()!=0)
						grid.SetCtrl(2, lstINT.Add().Min(fcve.GetDescr().GetMin()).Max(fcve.GetDescr().GetMax()).NotNull(isCheckMandat).SetFont(vFont));
					else
						grid.SetCtrl(2, lstINT.Add().NotNull(isCheckMandat).SetFont(vFont));
				}
			}
			grid("T_VALUE") = StrInt(fcve.GetValue().ToString());
			if(grid.GetCtrl(2) != NULL){
				grid.GetCtrl(2)->SetData(StrInt(fcve.GetValue().ToString()));
				grid.GetCtrl(2)->Refresh();
			}
		break;
		case FldEditType::FLOAT:
			if(!fcve.GetIsEdit()){
				grid("T_VALUE") = fcve.GetValue();
				break;
			}
			if(grid.GetCtrl(2) == NULL){
				grid.SetCtrl(2, lstDBL.Add().Min(fcve.GetDescr().GetMin()).Max(fcve.GetDescr().GetMax()).NotNull(isCheckMandat).SetFont(vFont));
			}
			grid("T_VALUE") = StrDbl(fcve.GetValue().ToString());
			if(grid.GetCtrl(2) != NULL){
				grid.GetCtrl(2)->SetData(StrDbl(fcve.GetValue().ToString()));
				grid.GetCtrl(2)->Refresh();
			}
		break;
		case FldEditType::DATE:
			if(!fcve.GetIsEdit()){
				grid("T_VALUE") = fcve.GetValue();
				break;
			}
			if(grid.GetCtrl(2) == NULL){
				DropDate& drDate = lstDATE.Add();
				drDate.NotNull(isCheckMandat).SetFont(vFont);
				grid.SetCtrl(2, drDate);
			}
			grid("T_VALUE") = fcve.GetValue();
			if(grid.GetCtrl(2) != NULL){
				grid.GetCtrl(2)->SetData(fcve.GetValue());
				grid.GetCtrl(2)->Refresh();
			}
		break;
		case FldEditType::LIST:
		{
			if(!fcve.GetIsEdit()){
				grid("T_VALUE") = fcve.GetValue();
				break;
			}
			if(grid.GetCtrl(2) == NULL){
				DropList& dl = lstDLST.Add(new DropList());
				dl.NotNull(isCheckMandat);
				dl.AddButton().Main(false).SetImage(Images::ADD_2()).WhenClick  << [&dl]{
					String str = ShowListEditDlg();
					if(dl.Find(str) == -1) dl.Add(str);
				};
				dl.SetDisplay(Single<NotNullBackGround>());
				if(!FillDropList(fcve.GetCode(), dl)) FillDropList(fcve.GetDescr().GetLst(), dl);
				if(dl.Find(fcve.GetValue()) == -1) dl.Add(fcve.GetValue());
				grid.SetCtrl(2, dl.NotNull(isCheckMandat).DisplayAll(isCheckMandat));
			}
			grid("T_VALUE") = fcve.GetValue().ToString();
			if(grid.GetCtrl(2) != NULL){
				grid.GetCtrl(2)->SetData(TrimBoth(fcve.GetValue().ToString()));
				grid.GetCtrl(2)->Refresh();
			}
		}
		break;
		case FldEditType::BTN:
		{
			if(!fcve.GetIsEdit()){
				grid("T_VALUE") = fcve.GetValue();
				break;
			}
			if(grid.GetCtrl(2) == NULL){
				if(grid.GetCtrl(2) == NULL){
					Button& btn = lstBTN.Add(new Button());
					btn.SetImage(Images::EDIT());
					grid.SetCtrl(2, btn);
				}
			}
		}
		break;
	}
}
void LayGridCNV::Clear(){
	grid.Clear();
	lstConv.Clear();
	lstDLST.Clear();
	lstSTR.Clear();
	lstINT.Clear();
	lstDBL.Clear();
	lstDATE.Clear();
	lstBTN.Clear();
	fldCveList.ClearValue();
}
//!---------------------------------------------------------------------------------------------
//!---------------------------------------------------------------------------------------------

// FA: Frequency; Attenuation
class LayGridFA: public WithLayGrid_FA<ParentCtrl> {
public:
	typedef LayGridFA CLASSNAME;
	bool IsModified()const{return isModified;}
	void ToCtrl(const HcmData& hcmData);
	void ToCtrl(const TwoCveList& twoCveList);
	void FromCtrl(HcmData& hcmData);
	void Clear();
	void Serialize(Stream& s);
	void Set(const Vector<Tuple<FldCVE, FldCVE>>& vec){fldTwoCveList.Set(vec);}
	TwoCveList& Get(){return fldTwoCveList;}
	void BeforeFrmShow(const String& nameCtrl, VectorMap<String, String>& sMap);
	void BeforeFrmClose(const String& nameCtrl, VectorMap<String, String>& sMap);
	LayGridFA(bool isEditable);
protected:
	bool isEditable = false;
	bool isModified = false;
	TwoCveList fldTwoCveList;
	Array<EditDouble> lstDBL;
	void CreateEdCtrl(const FldCVE& fld, const HcmEntity hcmEntity);
	void Setup();
};
LayGridFA::LayGridFA(bool isEditable):isEditable(isEditable){
	CtrlLayout(*this);
	Setup();
}
void LayGridFA::Serialize(Stream& s){
	grid.Serialize(s);
}
void LayGridFA::BeforeFrmShow(const String& nameCtrl, VectorMap<String, String>& sMap){
	int idx = sMap.Find(nameCtrl);
	if(idx != -1) LoadFromString(*this, sMap[idx]);
}
void LayGridFA::BeforeFrmClose(const String& nameCtrl, VectorMap<String, String>& sMap){
	int idx = sMap.Find(nameCtrl);
	if(idx == -1)
		sMap.Add(nameCtrl, StoreAsString(*this));
	else
		sMap[idx] = StoreAsString(*this);
}
void LayGridFA::Setup(){
	grid.Clear(true);
	grid.ColoringMode(1);
	grid.OddColor().ColoringMode(1);
	grid.EvenColor().ColoringMode(2);
	grid.Indicator(); //---------------
	grid.AddColumn("T_A_CODE", String(t_("Code"))).Min(50).AlignCenter().SetDisplay(Single<ItemGrid>()).SetHeaderFont(Single<ItemGrid>().headFont);
	grid.AddColumn("T_A_VALUE", String(t_("Frequency, MHz"))).Min(250).AlignCenter().SetDisplay(Single<ItemGrid>()).HeaderAlignCenter().SetHeaderFont(Single<ItemGrid>().headFont);
	grid.AddColumn("T_B_CODE", String(t_("Code"))).Min(50).AlignCenter().SetDisplay(Single<ItemGrid>()).SetHeaderFont(Single<ItemGrid>().headFont);
	grid.AddColumn("T_B_VALUE", String(t_("Attenuation, bB"))).Min(250).AlignCenter().SetDisplay(Single<ItemGrid>()).HeaderAlignCenter().SetHeaderFont(Single<ItemGrid>().headFont);
	grid.RejectNullRow();
	grid.Navigating();
	grid.SetToolBar();
	grid.Clipboard();
	grid.Absolute();
	grid.SetRowHeight(0, Single<ItemGrid>().headFont.GetHeight()+10); // header height = GridCtrl.height + 10
}
void LayGridFA::ToCtrl(const HcmData& hcmData){
	grid.Clear();
	lstDBL.Clear();
	fldTwoCveList.Fill(hcmData);
	if(!isEditable){
		for(int i=0; i < fldTwoCveList.Get().GetCount(); i++){
			grid.Add();
			grid("T_A_CODE") = fldTwoCveList.Get()[i].a.GetCode();
			grid("T_A_VALUE") = fldTwoCveList.Get()[i].a.GetValue();
			grid("T_B_CODE") = fldTwoCveList.Get()[i].b.GetCode();
			grid("T_B_VALUE") = fldTwoCveList.Get()[i].b.GetValue();
			grid.SetRowHeight(grid.GetRowCount(), Single<ItemGrid>().itemFont.GetHeight()*1.5);// row height = GridCtrl.height * 1.5
		}
	}else{
		for(int i=0; i < fldTwoCveList.Get().GetCount(); i++){
			grid.Add();
			grid("T_A_CODE") = fldTwoCveList.Get()[i].a.GetCode();
			EditDouble& edA = lstDBL.Add(new EditDouble());
			grid.SetCtrl(1, edA);
			grid("T_A_VALUE") = StrDbl(fldTwoCveList.Get()[i].a.GetValue().ToString());
			grid("T_B_CODE") = fldTwoCveList.Get()[i].b.GetCode();
			EditDouble& edB = lstDBL.Add(new EditDouble());
			grid.SetCtrl(3, edB);
			grid("T_B_VALUE") = StrDbl(fldTwoCveList.Get()[i].b.GetValue().ToString());
			grid.SetRowHeight(grid.GetRowCount(), Single<ItemGrid>().itemFont.GetHeight()*1.5);// row height = GridCtrl.height * 1.5
		}
	}
	isModified = false;
}
void LayGridFA::ToCtrl(const TwoCveList& twoCveList){
	grid.Clear();
	lstDBL.Clear();
	if(!isEditable){
		for(int i=0; i < twoCveList.Get().GetCount(); i++){
			grid.Add();
			grid("T_A_CODE") = twoCveList.Get()[i].a.GetCode();
			grid("T_A_VALUE") = twoCveList.Get()[i].a.GetValue();
			grid("T_B_CODE") = twoCveList.Get()[i].b.GetCode();
			grid("T_B_VALUE") = twoCveList.Get()[i].b.GetValue();
			grid.SetRowHeight(grid.GetRowCount(), Single<ItemGrid>().itemFont.GetHeight()*1.5);// row height = GridCtrl.height * 1.5
		}
	}else{
		for(int i=0; i < twoCveList.Get().GetCount(); i++){
			grid.Add();
			grid("T_A_CODE") = twoCveList.Get()[i].a.GetCode();
			EditDouble& edA = lstDBL.Add(new EditDouble());
			grid.SetCtrl(1, edA);
			grid("T_A_VALUE") = StrDbl(twoCveList.Get()[i].a.GetValue().ToString());
			grid("T_B_CODE") = twoCveList.Get()[i].b.GetCode();
			EditDouble& edB = lstDBL.Add(new EditDouble());
			grid.SetCtrl(3, edB);
			grid("T_B_VALUE") = StrDbl(twoCveList.Get()[i].b.GetValue().ToString());
			grid.SetRowHeight(grid.GetRowCount(), Single<ItemGrid>().itemFont.GetHeight()*1.5);// row height = GridCtrl.height * 1.5
		}
	}
	isModified = false;
}
void LayGridFA::FromCtrl(HcmData& hcmData){
	if(!isEditable) return;
	isModified = false;
	for(int i = 0; i < grid.GetRowCount(); i++){
		if(grid.GetCtrl(i, 1) != nullptr){
			if(fldTwoCveList.GetFld(grid.GetCell(i, "T_A_CODE").val).GetValue().ToString() != grid.GetCtrl(i, 1)->GetData().ToString()){
				isModified = true;
			}
			fldTwoCveList.GetFld(grid.GetCell(i, "T_A_CODE").val.ToString()).SetValue(grid.GetCtrl(i, 1)->GetData());
		}
		else
			fldTwoCveList.GetFld(grid.GetCell(i, "T_A_CODE").val.ToString()).SetValue(grid.GetCell(i, "T_A_VALUE").val);

		if(grid.GetCtrl(i, 3) != nullptr){
			if(fldTwoCveList.GetFld(grid.GetCell(i, "T_B_CODE").val).GetValue().ToString() != grid.GetCtrl(i, 3)->GetData().ToString()){
				isModified = true;
			}
			fldTwoCveList.GetFld(grid.GetCell(i, "T_B_CODE").val.ToString()).SetValue(grid.GetCtrl(i, 3)->GetData());
		}
		else
			fldTwoCveList.GetFld(grid.GetCell(i, "T_B_CODE").val.ToString()).SetValue(grid.GetCell(i, "T_B_VALUE").val);
	}
	if(isModified){
		// save to hcmData
		for(int i=0; i < fldTwoCveList.Get().GetCount(); i++){
			hcmData.EditVal(fldTwoCveList.Get()[i].a.GetCode(), fldTwoCveList.Get()[i].a.GetValue().ToString());
			hcmData.EditVal(fldTwoCveList.Get()[i].b.GetCode(), fldTwoCveList.Get()[i].b.GetValue().ToString());
		}
	}
}
void LayGridFA::Clear(){
	grid.Clear();
	fldTwoCveList.ClearValue();
}
//!---------------------------------------------------------------------------------------------


struct AntCpXpEditDlg: public WithAntCpXpEditDlg<TopWindow>{
public:
	void ToCtrl(const Tuple<double, double>& tval);
	void FromCtrl(Tuple<double, double>& tval);
	bool IsModified()const{return isModified;}
	void Clear();
	void Serialize(Stream& s);
	void BeforeFrmShow(const String& nameCtrl, VectorMap<String, String>& sMap);
	void BeforeFrmClose(const String& nameCtrl, VectorMap<String, String>& sMap);
	AntCpXpEditDlg();
protected:
	void Setup();
	bool isModified;
};
AntCpXpEditDlg::AntCpXpEditDlg(){
	CtrlLayoutOKCancel(*this, "Edit...");
	Sizeable();
	Setup();
}
void AntCpXpEditDlg::Serialize(Stream& s){
    int version = 1;
    s / version;
	SerializePlacement(s);
}
void AntCpXpEditDlg::BeforeFrmShow(const String& nameCtrl, VectorMap<String, String>& sMap){
	int idx = sMap.Find(nameCtrl);
	if(idx != -1) LoadFromString(*this, sMap[idx]);
}
void AntCpXpEditDlg::BeforeFrmClose(const String& nameCtrl, VectorMap<String, String>& sMap){
	int idx = sMap.Find(nameCtrl);
	if(idx == -1)
		sMap.Add(nameCtrl, StoreAsString(*this));
	else
		sMap[idx] = StoreAsString(*this);
}
void AntCpXpEditDlg::Setup(){
	ed_Angle.SetConvert(Single<ConvDouble>());
	ed_Attenuation.SetConvert(Single<ConvDouble>());
}
void AntCpXpEditDlg::ToCtrl(const Tuple<double, double>& tval){
	ed_Angle.SetData(tval.a);
	ed_Attenuation.SetData(tval.b);
	isModified = false;
}
void AntCpXpEditDlg::FromCtrl(Tuple<double, double>& tval){
	tval.a = double(ed_Angle.GetData());
	tval.b = double(ed_Attenuation.GetData());
	isModified = false;
}
void AntCpXpEditDlg::Clear(){
	ed_Angle.SetData(0.0);
	ed_Attenuation.SetData(0.0);
}
//!---------------------------------------------------------------------------------------


class LayGridCpXp: public WithLayGrid<ParentCtrl> {
public:
	typedef LayGridCpXp CLASSNAME;
	GridCtrl grid;
	bool IsModified()const{return isModified;}
	void GrPopMenu(Bar& bar);
	void ToCtrl(const HcmData& hcmData);
	void ToCtrl();
	void FromCtrl(HcmData& hcmData);
	void Clear();
	void Serialize(Stream& s);
	void Set(const Tuple<String, String>& vecCode){tvList.Set(vecCode);}
	void Ins();
	void Edit();
	void Del();
	void BeforeFrmShow(const String& nameCtrl, VectorMap<String, String>& sMap);
	void BeforeFrmClose(const String& nameCtrl, VectorMap<String, String>& sMap);
	LayGridCpXp(bool isEditable);
protected:
	VectorMap<String, String> seriaMap;
	bool isEditable = false;
	bool isModified = false;
	CpXpVecList tvList;
	void Setup();
};
LayGridCpXp::LayGridCpXp(bool isEditable):isEditable(isEditable){
	CtrlLayout(*this);
	Add(grid.SizePos());
	Setup();
}
void LayGridCpXp::Serialize(Stream& s){
	grid.Serialize(s);
}
void LayGridCpXp::Setup(){
	grid.Clear(true);
	grid.ColoringMode(1);
	grid.OddColor().ColoringMode(1);
	grid.EvenColor().ColoringMode(2);
	grid.Indicator(); //---------------
	grid.AddColumn("T_ANGLE", String(t_("Angle"))).Min(250).AlignCenter().SetDisplay(Single<ItemGrid>()).HeaderAlignCenter().SetHeaderFont(Single<ItemGrid>().headFont);
	grid.AddColumn("T_ATTEN", String(t_("Attenuation"))).Min(250).AlignCenter().SetDisplay(Single<ItemGrid>()).HeaderAlignCenter().SetHeaderFont(Single<ItemGrid>().headFont);
	grid.RejectNullRow();
	grid.Navigating();
	grid.SetToolBar();
	grid.Clipboard();
	grid.Absolute();
	grid.SetRowHeight(0, Single<ItemGrid>().headFont.GetHeight()+10); // header height = GridCtrl.height + 10
	grid.WhenMenuBar = THISBACK(GrPopMenu);
}
void LayGridCpXp::GrPopMenu(Bar& bar){
	if(!isEditable) return;
	bar.Add(t_("Edit .."), Images::EDIT(), THISBACK(Edit));
	bar.Add(t_("Add .."), Images::ADD(), THISBACK(Ins));
	bar.Separator();
	bar.Add(t_("Del .."), Images::DEL(), THISBACK(Del));
}
void LayGridCpXp::ToCtrl(const HcmData& hcmData){
	grid.Clear();
	tvList.Fill(hcmData);
	for(int i=0; i < tvList.Get().GetCount(); i++){
		grid.Add();
		grid("T_ANGLE") = tvList.Get()[i].a;
		grid("T_ATTEN") = tvList.Get()[i].b;
		grid.SetRowHeight(grid.GetRowCount(), Single<ItemGrid>().itemFont.GetHeight()*1.5);// row height = GridCtrl.height * 1.5
	}
	isModified = false;
}
void LayGridCpXp::ToCtrl(){
	grid.Clear();
	for(int i=0; i < tvList.Get().GetCount(); i++){
		grid.Add();
		grid("T_ANGLE") = tvList.Get()[i].a;
		grid("T_ATTEN") = tvList.Get()[i].b;
		grid.SetRowHeight(grid.GetRowCount(), Single<ItemGrid>().itemFont.GetHeight()*1.5);// row height = GridCtrl.height * 1.5
	}
	isModified = false;
}
void LayGridCpXp::FromCtrl(HcmData& hcmData){
	if(!isEditable) return;
	tvList.Save(hcmData);
}
void LayGridCpXp::Ins(){
	if(!isEditable) return;
	Tuple<double, double> tmpVal;
	tmpVal.a = 0.0; // StrDbl(grid("T_ANGLE").ToString());
	tmpVal.b = 0.0; // StrDbl(grid("T_ATTEN").ToString());
	AntCpXpEditDlg dlg;
	dlg.BeforeFrmShow("EditAntCP", seriaMap);
	dlg.ToCtrl(tmpVal);
	if(dlg.Execute() == IDOK){
		dlg.FromCtrl(tmpVal);
		tvList.Add(tmpVal);
		isModified = true;
		ToCtrl();
	}
	dlg.BeforeFrmClose("EditAntCP", seriaMap);
}
void LayGridCpXp::Edit(){
	if(!isEditable) return;
	Tuple<double, double> tmpVal;
	tmpVal.a = StrDbl(grid("T_ANGLE").ToString());
	tmpVal.b = StrDbl(grid("T_ATTEN").ToString());
	AntCpXpEditDlg dlg;
	dlg.BeforeFrmShow("EditAntCP", seriaMap);
	dlg.ToCtrl(tmpVal);
	if(dlg.Execute() == IDOK){
		double a = tmpVal.a;
		dlg.FromCtrl(tmpVal);
		tvList.Edit(a, tmpVal);
		isModified = true;
		ToCtrl();
	}
	dlg.BeforeFrmClose("EditAntCP", seriaMap);
}
void LayGridCpXp::Del(){
	if(!isEditable) return;
	Tuple<double, double> tmpVal;
	tmpVal.a = StrDbl(grid("T_ANGLE").ToString());
	tmpVal.b = StrDbl(grid("T_ATTEN").ToString());
	if(PromptYesNo(t_("Delete?"))){
		tvList.Del(tmpVal.a);
		isModified = true;
		ToCtrl();
	}
}
void LayGridCpXp::Clear(){
	grid.Clear();
	tvList.Clear();
}
//!---------------------------------------------------------------------------------------


//!=============================================================================================


class LayEntryGeneral: public WithLayEntryGeneral<ParentCtrl> {
public:
	typedef LayEntryGeneral CLASSNAME;
	void ToCtrl(const HcmIN& hcmIN){layGridCNV.ToCtrl(hcmIN);};
	void FromCtrl(HcmIN& hcmIN){layGridCNV.FromCtrl(hcmIN);};
	void Clear(){layGridCNV.Clear();};
	bool IsModified()const{return layGridCNV.IsModified();}
	void Serialize(Stream& s);
	LayEntryGeneral(const bool isEditable);
protected:
	bool isEditable;
	LayGridCNV layGridCNV = isEditable;
};
LayEntryGeneral::LayEntryGeneral(const bool isEditable):isEditable(isEditable){
	CtrlLayout(*this);
	Add(layGridCNV.SizePos());
	Vector<FldCVE> cvList(
	{
		FldCVE("4A"),
		FldCVE("1A"),
		FldCVE("1A1"),
		FldCVE("0A"),
		FldCVE("4C1"),
		FldCVE("4C2"),
		FldCVE("9A"),
		FldCVE("9B"),
		FldCVE("9D"),
		FldCVE("4Z"),
		FldCVE("9L"),
		FldCVE("6A"),
		FldCVE("6B"),
		FldCVE("6Z"),
		FldCVE("1Z"),
		FldCVE("4B"),
		FldCVE("13X"),
		FldCVE("2C"),
		FldCVE("13Y"),
		FldCVE("2W"),
		FldCVE("2Z"),
		FldCVE("13Z")
	});
	layGridCNV.Set(cvList);
}
void LayEntryGeneral::Serialize(Stream& s){
	layGridCNV.Serialize(s);
}
//!---------------------------------------------------------------------------------------

class LayEntryEquip: public WithLayEntryEquip<ParentCtrl> {
public:
	typedef LayEntryEquip CLASSNAME;
	WithLayGridCaption<ParentCtrl> layCaption;				// layout для размещения grd_Title
	FrameTop<WithLayGridCaption<ParentCtrl>> frameCaption;
	Splitter spl;
	Label  lbCaption;
	void ToCtrl(const HcmIN& hcmIN){layEquip.ToCtrl(hcmIN); layFrecAtten.ToCtrl(hcmIN);};
	void ToCtrl(const TwoCveList& twoCveList){layFrecAtten.ToCtrl(twoCveList);};
	void FromCtrl(HcmIN& hcmIN){
		layEquip.FromCtrl(hcmIN);
		layFrecAtten.FromCtrl(hcmIN);
	};
	void Clear(){layEquip.Clear(); layFrecAtten.Clear();};
	bool IsModified()const{return layEquip.IsModified() || layFrecAtten.IsModified();}

	void Serialize(Stream& s);
	LayEntryEquip(const bool isEditable);
//protected:
	bool isEditable;
	LayGridCNV layEquip = isEditable;
	LayGridFA layFrecAtten = isEditable;
};
LayEntryEquip::LayEntryEquip(const bool isEditable):isEditable(isEditable){
	CtrlLayout(*this);
	Add(spl.Vert(layEquip.SizePos(), layFrecAtten.SizePos()));
	lbCaption.SetFrame(BlackFrame());
	layCaption.Add(lbCaption.SizePos());
	frameCaption.Add(layCaption.SizePos());
	frameCaption.Height(Single<ItemGrid>().headFont.GetHeight()*2);
	layFrecAtten.AddFrame(frameCaption);
	lbCaption.SetFont(Single<ItemGrid>().headFont);
	lbCaption.SetText(t_(" Transmitter spectrum mask or receiver selectivity mask:"));
	Vector<FldCVE> cvList(
	{
		FldCVE("7H"),
		FldCVE("7I"),
		FldCVE("8B"),
		FldCVE("8B3"),
		FldCVE("7G1"),
		FldCVE("7G2"),
		FldCVE("9H"),
		FldCVE("7K"),
		FldCVE("7A"),
		FldCVE("7G3"),
	});
	layEquip.Set(cvList);
	Vector<Tuple<FldCVE, FldCVE>> tcvList(
	{
		MakeTuple(FldCVE("7Gf1"), FldCVE("7Ga1")),
		MakeTuple(FldCVE("7Gf2"), FldCVE("7Ga2")),
		MakeTuple(FldCVE("7Gf3"), FldCVE("7Ga3")),
		MakeTuple(FldCVE("7Gf4"), FldCVE("7Ga4")),
		MakeTuple(FldCVE("7Gf5"), FldCVE("7Ga5")),
		MakeTuple(FldCVE("7Gf6"), FldCVE("7Ga6")),
	});
	layFrecAtten.Set(tcvList);
}
void LayEntryEquip::Serialize(Stream& s){
	layEquip.Serialize(s);
	layFrecAtten.Serialize(s);
	spl.Serialize(s);
}
//!---------------------------------------------------------------------------------------

class LayEntryAnt: public WithLayEntryAnt<ParentCtrl> {
public:
	typedef LayEntryAnt CLASSNAME;
	Splitter spl;
	TabCtrl tab;
	void ToCtrl(const HcmIN& hcmIN){layAnt.ToCtrl(hcmIN); layCP.ToCtrl(hcmIN); layXP.ToCtrl(hcmIN);};
	void FromCtrl(HcmIN& hcmIN){layAnt.FromCtrl(hcmIN); layCP.FromCtrl(hcmIN); layXP.FromCtrl(hcmIN);};
	void Clear(){layAnt.Clear(); layCP.Clear(); layXP.Clear();};
	bool IsModified()const{return layAnt.IsModified() || layCP.IsModified() || layXP.IsModified();}
	void Serialize(Stream& s);
	LayEntryAnt(const bool isEditable);
protected:
	bool isEditable;
	LayGridCNV layAnt = isEditable;
	LayGridCpXp layCP = isEditable;
	LayGridCpXp layXP = isEditable;
};
LayEntryAnt::LayEntryAnt(const bool isEditable):isEditable(isEditable){
	CtrlLayout(*this);
	Add(spl.Vert(layAnt.SizePos(), tab.SizePos()));
	tab.Add(layCP.SizePos(), t_("\1[ [ [3*!Arial! Co-polar]]]"));
	tab.Add(layXP.SizePos(), t_("\1[ [ [3*!Arial! Cross-polar]]]"));
	Vector<FldCVE> antList(
	{
		FldCVE("9XM"),
		FldCVE("9XT"),
		FldCVE("9Y"),
		FldCVE("9XFU"),
		FldCVE("9XFL"),
		FldCVE("9X1"),

		FldCVE("9Xptcp"),
		FldCVE("9Xcpsize"),

		FldCVE("9Xptxp"),
		FldCVE("9Xxpsize"),
	});
	layAnt.Set(antList);

	Tuple<String, String> cpCode = MakeTuple("9XCPan", "9XCPat");
	layCP.Set(cpCode);

	Tuple<String, String> xpCode = MakeTuple("9XXPan", "9XXPat");
	layXP.Set(xpCode);
}
void LayEntryAnt::Serialize(Stream& s){
	spl.Serialize(s);
	layAnt.Serialize(s);
	spl.Serialize(s);
	tab.Serialize(s);
	layCP.Serialize(s);
	layXP.Serialize(s);
}
//!---------------------------------------------------------------------------------------------

/// layer to view the pack header: horiz grid
class LayViewHeadH: public WithLayHcmHeadH<ParentCtrl> {
public:
	typedef LayViewHeadH CLASSNAME;
	LayGridViewH layHead = CveHeaderList().GetList();
	bool IsCurSel();
	void ToCtrl(const HcmHeader& header);
	void Clear();
	void Serialize(Stream& s);
	LayViewHeadH();
};
LayViewHeadH::LayViewHeadH(){
	CtrlLayout(*this);
	Add(layHead.SizePos());
}
void LayViewHeadH::Serialize(Stream& s){
	layHead.Serialize(s);
}
void LayViewHeadH::ToCtrl(const HcmHeader& header){
	layHead.ToCtrl(header);
}
void LayViewHeadH::Clear(){
	layHead.Clear();
}
bool LayViewHeadH::IsCurSel(){
	if(!layHead.GetCurSelID()) return true;
	return false;
}
//!---------------------------------------------------------------------------------------------


// TODO:
class LayHeadV: public WithLayHcmHeadV<ParentCtrl> {
public:
	typedef LayHeadV CLASSNAME;
	void ToCtrl(const HcmHeader& header);
	void FromCtrl(HcmHeader& header);
	void Clear();
	void Serialize(Stream& s);
	bool IsModified()const{return layHead.IsModified();}
	LayHeadV(bool isEditable);
	LayHeadV(bool isEditable, const Vector<FldCVE>& vec);
protected:
	bool isEditable;
	LayGridCNV layHead = isEditable;
};
LayHeadV::LayHeadV(bool isEditable): isEditable(isEditable){
	CtrlLayout(*this);
	Add(layHead.SizePos());
}
LayHeadV::LayHeadV(bool isEditable, const Vector<FldCVE>& vec): isEditable(isEditable){
	CtrlLayout(*this);
	layHead.Set(vec);
	Add(layHead.SizePos());
}
void LayHeadV::Serialize(Stream& s){
	layHead.Serialize(s);
}
void LayHeadV::ToCtrl(const HcmHeader& header){
	layHead.ToCtrl(header);
}
void LayHeadV::FromCtrl(HcmHeader& header){
	if(!isEditable) return;
	layHead.FromCtrl(header);
}
void LayHeadV::Clear(){
	layHead.Clear();
}
//!---------------------------------------------------------------------------------------

/// layer to view the pack entry list (grid)
class LayViewEntrisH : public WithLayHcmEntris<ParentCtrl> {
public:
	typedef LayViewEntrisH CLASSNAME;
	LayGridViewH layEntris = CveEntryList().GetList();
	void ToCtrl(const HcmPack& pack);
	void Clear();
	int GetCurSelID();
	void SetFirstRec();
	void Serialize(Stream& s);
	LayViewEntrisH();
};
LayViewEntrisH::LayViewEntrisH(){
	CtrlLayout(*this);
	Add(layEntris.SizePos());
}
void LayViewEntrisH::Serialize(Stream& s){
	layEntris.Serialize(s);
}
void LayViewEntrisH::ToCtrl(const HcmPack& hcmPack){
	layEntris.ToCtrl(hcmPack);
}
int LayViewEntrisH::GetCurSelID(){
	return layEntris.GetCurSelID();
}
void LayViewEntrisH::SetFirstRec(){
	layEntris.SetFirstRec();
}
void LayViewEntrisH::Clear(){
	layEntris.Clear();
}
//!---------------------------------------------------------------------------------------------

class LayCoEntry: public WithLayEntryGeneral<ParentCtrl> {
public:
	typedef LayCoEntry CLASSNAME;
	void ToCtrl(const HcmIN& hcmIN){layGridCNV.ToCtrl(hcmIN);};
	void FromCtrl(HcmIN& hcmIN){layGridCNV.FromCtrl(hcmIN);};
	void Clear(){layGridCNV.Clear();};
	bool IsModified()const{return layGridCNV.IsModified();}
	void Serialize(Stream& s);
	LayCoEntry(const bool isEditable);
protected:
	bool isEditable;
	LayGridCNV layGridCNV = isEditable;
};
LayCoEntry::LayCoEntry(const bool isEditable):isEditable(isEditable){
	CtrlLayout(*this);
	Add(layGridCNV.SizePos());
	Vector<FldCVE> cvList(
	{
/*
		FldCVE("13Y"),
		FldCVE("2Z"),
		FldCVE("13Z")
*/
		FldCVE("4A", false),
		FldCVE("1A", false),
		FldCVE("1A1", false),
		FldCVE("0A", false),
		FldCVE("4C1", false),
		FldCVE("4C2", false),
		FldCVE("9A", false),
		FldCVE("9B", false),
		FldCVE("9D", false),
		FldCVE("4Z", false),
		FldCVE("9L", false),
		FldCVE("6A", false),
		FldCVE("6B", false),
		FldCVE("6Z", false),
		FldCVE("1Z", false),
		FldCVE("4B", false),
		FldCVE("13X", false),
		FldCVE("2C", false),
		FldCVE("13Y"),
		FldCVE("2W", false),
		FldCVE("2Z"),
		FldCVE("13Z")
		
		
	});
	layGridCNV.Set(cvList);
}
void LayCoEntry::Serialize(Stream& s){
	layGridCNV.Serialize(s);
}
//!---------------------------------------------------------------------------------------


#endif
