// ClassInfoDlg_Gui_CatList.cpp : implementation file
//

#include "stdafx.h"
#include "ClassInfoDlg_Gui_CatList.h"
#include "XmlGuiCategoryInfo.h"
#include "XmlGuiCategoryField.h"
#include "XmlGuiCategoryInfoList.h"
#include "XmlClassInfo.h"
#include "XmlMemberInfo.h"
#include "CategoryFieldEditorDlg.h"
#include "CategoryInfoEditorDlg.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif


#define COL_CLASS_MEMBER	1
#define COL_DESCRIPTION		2

/////////////////////////////////////////////////////////////////////////////
// CClassInfoDlg_Gui_CatList dialog


CClassInfoDlg_Gui_CatList::CClassInfoDlg_Gui_CatList(CWnd* pParent /*=NULL*/)
	: CPropertyEditorDlg(CClassInfoDlg_Gui_CatList::IDD, pParent),
	classInfo_(NULL),
	initialized_(false),
	categoryList_(NULL)
{
	//{{AFX_DATA_INIT(CClassInfoDlg_Gui_CatList)
		// NOTE: the ClassWizard will add member initialization here
	//}}AFX_DATA_INIT
}


void CClassInfoDlg_Gui_CatList::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CClassInfoDlg_Gui_CatList)
	DDX_Control(pDX, IDC_CHK_SORT, chkSort_);
	DDX_Control(pDX, IDC_CMD_EDIT_CATEGORY, cmdEditCategory_);
	DDX_Control(pDX, IDC_CMD_EDIT_FIELD, cmdEditField_);
	DDX_Control(pDX, IDC_LVW_STRUCT, lvwStruct_);
	DDX_Control(pDX, IDC_CMD_MOVE_UP, cmdMoveUp_);
	DDX_Control(pDX, IDC_CMD_MOVE_DOWN, cmdMoveDown_);
	DDX_Control(pDX, IDC_CMD_DELETE_FIELD, cmdDeleteField_);
	DDX_Control(pDX, IDC_CMD_DELETE_CAT, cmdDeleteCategory_);
	DDX_Control(pDX, IDC_CMD_ADD_FIELD, cmdAddField_);
	DDX_Control(pDX, IDC_CMD_ADD_CAT, cmdAddCategory_);
	//}}AFX_DATA_MAP
}


BEGIN_MESSAGE_MAP(CClassInfoDlg_Gui_CatList, CPropertyEditorDlg)
	//{{AFX_MSG_MAP(CClassInfoDlg_Gui_CatList)
	ON_BN_CLICKED(IDC_CMD_ADD_CAT, OnCmdAddCat)
	ON_BN_CLICKED(IDC_CMD_DELETE_CAT, OnCmdDeleteCat)
	ON_BN_CLICKED(IDC_CMD_MOVE_DOWN, OnCmdMoveDown)
	ON_BN_CLICKED(IDC_CMD_MOVE_UP, OnCmdMoveUp)
	ON_BN_CLICKED(IDC_CMD_ADD_FIELD, OnCmdAddField)
	ON_NOTIFY(NM_DBLCLK, IDC_LVW_STRUCT, OnDblclkLvwStruct)
	ON_WM_SIZE()
	ON_BN_CLICKED(IDC_CMD_EDIT_FIELD, OnCmdEditField)
	ON_BN_CLICKED(IDC_CMD_DELETE_FIELD, OnCmdDeleteField)
	ON_BN_CLICKED(IDC_CMD_EDIT_CATEGORY, OnCmdEditCategory)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CClassInfoDlg_Gui_CatList message handlers

BOOL CClassInfoDlg_Gui_CatList::OnInitDialog() 
{
	CDialog::OnInitDialog();
	
	UpdateWindowSize();
	
	imageList_.Create(16, 16, ILC_COLOR32 | ILC_MASK, 4, 4);
	imageList_.Add(AfxGetApp()->LoadIcon(IDI_CLASS));
	imageList_.Add(AfxGetApp()->LoadIcon(IDI_CLASS_MEMBER));
	
	lvwStruct_.InsertColumn(0, _T("Category/Field"), LVCFMT_LEFT, 150);
	lvwStruct_.InsertColumn(1, _T("Class Member"), LVCFMT_LEFT, 150);
	lvwStruct_.InsertColumn(2, _T("Description"), LVCFMT_LEFT, 150);
	lvwStruct_.SetImageList(&imageList_, LVSIL_SMALL);

	lvwStruct_.SetExtendedStyle(lvwStruct_.GetExtendedStyle() | LVS_EX_FULLROWSELECT);
	initialized_ = true;

	return TRUE;  // return TRUE unless you set the focus to a control
	              // EXCEPTION: OCX Property Pages should return FALSE
}

void CClassInfoDlg_Gui_CatList::OnCmdAddCat() 
{
	CXmlGuiCategoryInfo* newCategory;
	CCategoryInfoEditorDlg dlg;
	int selCategoryIndex;
	int ret;

	selCategoryIndex = GetSelectedCategoryIndex();
	if (selCategoryIndex == -1)
		selCategoryIndex = 0;

	newCategory = categoryList_->InsertCategory(selCategoryIndex);
	
	dlg.Init(newCategory, categoryList_);
	ret = dlg.DoModal();
	if (ret != IDOK) {
		categoryList_->RemoveCategory(newCategory);
		return;
	}
	
	BuildList();
}

void CClassInfoDlg_Gui_CatList::BuildList()
{
	CXmlGuiCategoryInfo* categoryInfo;
	CXmlGuiCategoryField* field;
	int selIndex;
	cmString selItemText;
	int insertionPoint;
	LVITEM item;
	CXmlMemberInfo* member;

	lvwStruct_.SetFocus();
	selIndex = lvwStruct_.GetNextItem(-1, LVNI_SELECTED);
	selItemText = lvwStruct_.GetItemText(selIndex, 0);

	lvwStruct_.DeleteAllItems();

	for (int catIndex = 0; catIndex < categoryList_->GetSize(); catIndex++) {
		categoryInfo = categoryList_->GetCategory(catIndex);
		
		insertionPoint = lvwStruct_.InsertItem(lvwStruct_.GetItemCount(), categoryInfo->GetCaption(), 0);
		lvwStruct_.SetItemText(insertionPoint, COL_DESCRIPTION, categoryInfo->GetDescription());
		if (categoryInfo->GetName() == selItemText)
			selIndex = insertionPoint;
		
		if (!categoryInfo->GetContracted()) {
			for (int fieldIndex = 0; fieldIndex < categoryInfo->GetFieldCount(); fieldIndex++) {
				field = categoryInfo->GetField(fieldIndex);
				
				item.mask = LVIF_TEXT | LVIF_INDENT | LVIF_IMAGE;
				item.iItem = lvwStruct_.GetItemCount();
				item.iSubItem = 0;
				item.pszText = (TCHAR*)(const TCHAR*)field->GetCaption();
				item.iIndent = 2;
				item.iImage = 1;

				// member name could be changed so get it from classInfo
				//
				member = dynamic_cast<CXmlMemberInfo*>(classInfo_->GetMemberById(field->GetMemberId()));
				if (member) {
					insertionPoint = lvwStruct_.InsertItem(&item);
					lvwStruct_.SetItemText(insertionPoint, COL_CLASS_MEMBER, field->GetMemberName());
					lvwStruct_.SetItemText(insertionPoint, COL_DESCRIPTION, field->GetDescription());

					if (member->GetCaption() == selItemText)
						selIndex = insertionPoint;
				}
			}
		}
	}

	lvwStruct_.SetItemState(selIndex, LVIS_SELECTED, LVIS_SELECTED);
}

void CClassInfoDlg_Gui_CatList::OnCmdDeleteCat() 
{
	int selCatIndex;
	
	selCatIndex = GetSelectedCategoryIndex();
	if (selCatIndex != -1) {
		categoryList_->RemoveCategory(selCatIndex);
		BuildList();
	}
}

void CClassInfoDlg_Gui_CatList::OnCmdDeleteField()
{
	CXmlGuiCategoryField* field;
	CXmlGuiCategoryInfo* cat;

	cat = GetSelectedCategory();
	field = GetSelectedField();
	if (cat && field) {
		cat->RemoveField(field);
		BuildList();
	}
}

void CClassInfoDlg_Gui_CatList::OnCmdMoveDown() 
{
	int itemIndent;
	int selIndex;

	selIndex = lvwStruct_.GetNextItem(-1, LVNI_SELECTED);
	if (selIndex < 0 || selIndex >= lvwStruct_.GetItemCount())
		return;

	itemIndent = GetItemIndent(selIndex);
	if (itemIndent == 0) {
		categoryList_->MoveDownCategory(GetSelectedCategoryIndex());
	} else {
		int selCatIndex;
		int selFieldIndex;
		CXmlGuiCategoryInfo* categoryInfo;

		selCatIndex = GetSelectedCategoryIndex();
		if (selCatIndex == -1)
			return;

		categoryInfo = categoryList_->GetCategory(selCatIndex);
		selFieldIndex = GetSelectedFieldIndex();

		categoryInfo->MoveDownField(selFieldIndex);

	}
	BuildList();
}

void CClassInfoDlg_Gui_CatList::OnCmdMoveUp() 
{
	int itemIndent;
	int selIndex;

	selIndex = lvwStruct_.GetNextItem(-1, LVNI_SELECTED);
	if (selIndex <= 0)
		return;

	itemIndent = GetItemIndent(selIndex);
	if (itemIndent == 0) {
		categoryList_->MoveUpCategory(GetSelectedCategoryIndex());
	} else {
		int selCatIndex;
		int selFieldIndex;
		CXmlGuiCategoryInfo* categoryInfo;

		selCatIndex = GetSelectedCategoryIndex();
		if (selCatIndex == -1)
			return;

		categoryInfo = categoryList_->GetCategory(selCatIndex);
		selFieldIndex = GetSelectedFieldIndex();

		categoryInfo->MoveUpField(selFieldIndex);
	}

	BuildList();
}

int CClassInfoDlg_Gui_CatList::GetItemIndent(int index)
{
	LV_ITEM lvi;

	lvi.iItem = index;
	lvi.iSubItem = 0;
	lvi.mask = LVIF_INDENT;

	VERIFY(lvwStruct_.GetItem(&lvi));

	return lvi.iIndent;
} 

void CClassInfoDlg_Gui_CatList::OnCmdAddField() 
{
	// fields can be added if selected class has members
	//
	if (classInfo_->GetMemberCount() == classInfo_->GetMemberCount(enDataType_Class)) {
		MessageBox(_T("Selected class has no members !"));
		return;
	}

	CXmlGuiCategoryInfo* categoryInfo;
	CXmlGuiCategoryField* newField;
	int selCatIndex;
	int selFieldIndex;
	int ret;

	selCatIndex = GetSelectedCategoryIndex();
	if (selCatIndex == -1)
		return;

	categoryInfo = categoryList_->GetCategory(selCatIndex);

	selFieldIndex = GetSelectedFieldIndex();
	if (selFieldIndex == -1)
		selFieldIndex = 0;

	// display dialog 
	//
	CCategoryFieldEditorDlg dlg;
	
	newField = categoryInfo->InsertField(selFieldIndex);

	newField->SetClassInfo(classInfo_);
	dlg.Init(classInfo_, newField, categoryList_, categoryInfo->GetName());
	ret = dlg.DoModal();
	if (ret != IDOK) {
		categoryInfo->RemoveField(newField);
		return;
	}

	BuildList();
}

int CClassInfoDlg_Gui_CatList::GetSelectedCategoryIndex()
{
	int selIndex;
	int catIndex;
	int itemIndent;

	selIndex = lvwStruct_.GetNextItem(-1, LVNI_SELECTED);
	if (selIndex == -1)
		return selIndex;

	catIndex = -1;
	for (int i = 0; i < lvwStruct_.GetItemCount(); i++) {
		itemIndent = GetItemIndent(i);
		if (itemIndent == 0)
			catIndex++;

		if (i == selIndex)
			break;
	}

	return catIndex;
}

int CClassInfoDlg_Gui_CatList::GetSelectedFieldIndex()
{
	int selIndex;
	int i;
	int itemIndent;
	int fieldIndex;

	selIndex = lvwStruct_.GetNextItem(-1, LVNI_SELECTED);
	if (selIndex == -1)
		return selIndex;

	itemIndent = GetItemIndent(selIndex);
	if(itemIndent == 0)
		return -1;

	i = selIndex;
	fieldIndex = -1;
	for (i = selIndex; i >= 0; i--) {
		itemIndent = GetItemIndent(i);
		if (itemIndent == 0)
			break;

		fieldIndex++;
	}
	
	return fieldIndex;
}


void CClassInfoDlg_Gui_CatList::OnDblclkLvwStruct(NMHDR* pNMHDR, LRESULT* pResult) 
{
	int selCatIndex;
	int selIndex;

	selIndex = lvwStruct_.GetNextItem(-1, LVNI_SELECTED);
	if (selIndex == -1)
		return;

	selCatIndex = GetSelectedCategoryIndex();
	if (selCatIndex != -1 && GetItemIndent(selIndex) == 0) {
		CXmlGuiCategoryInfo* categoryInfo;

		categoryInfo = categoryList_->GetCategory(selCatIndex);
		categoryInfo->SetContracted(!categoryInfo->GetContracted());

		BuildList();
	} else {
		OnCmdEditField();
	}

	*pResult = 0;
}

void CClassInfoDlg_Gui_CatList::StoreData()
{
	categoryList_->SetSorted(chkSort_.GetCheck() == TRUE);
}

void CClassInfoDlg_Gui_CatList::SetData(CXmlBaseElement* element)
{
	classInfo_ = dynamic_cast<CXmlClassInfo*>(element);
	assert(classInfo_);
	if (classInfo_ == NULL)
		return;

	categoryList_ = classInfo_->GetCategoryInfoList();
	chkSort_.SetCheck(categoryList_->GetSorted());
	
	BuildList();
}

void CClassInfoDlg_Gui_CatList::UpdateWindowSize()
{
	CRect rc;
	CRect listRect;
	CRect btnRect;
	int btnTop;
	int btnLeft = 0;
	CSize btnSize;
	
	GetWindowRect(rc);
	ScreenToClient(rc);
	
	// get size of template button
	//
	cmdAddCategory_.GetWindowRect(btnRect);
	btnSize = btnRect.Size();

	// lower buttons layer
	//
	btnTop = rc.bottom - btnSize.cy;	
	btnLeft = 0;
	
	cmdAddField_.SetWindowPos(&CWnd::wndTop, btnLeft, btnTop, btnSize.cx, btnSize.cy, 0);
	btnLeft += btnSize.cx;
	
	cmdDeleteField_.SetWindowPos(&CWnd::wndTop, btnLeft, btnTop, btnSize.cx, btnSize.cy, 0);
	btnLeft += btnSize.cx;

	cmdEditField_.SetWindowPos(&CWnd::wndTop, btnLeft, btnTop, btnSize.cx, btnSize.cy, 0);
	btnLeft += btnSize.cx;

	chkSort_.SetWindowPos(&CWnd::wndTop, btnLeft + 5, btnTop, 0, 0, SWP_NOSIZE);
	
	btnLeft = rc.Width() - btnSize.cx;
	cmdMoveDown_.SetWindowPos(&CWnd::wndTop, btnLeft, btnTop, btnSize.cx, btnSize.cy, 0);
		
	// upper buttons layer
	//
	btnTop -= btnSize.cy;
	btnLeft = 0;
	
	cmdAddCategory_.SetWindowPos(&CWnd::wndTop, btnLeft, btnTop, btnSize.cx, btnSize.cy, 0);
	btnLeft += btnRect.Width();
	
	cmdDeleteCategory_.SetWindowPos(&CWnd::wndTop, btnLeft, btnTop, btnSize.cx, btnSize.cy, 0);
	btnLeft += btnRect.Width();

	cmdEditCategory_.SetWindowPos(&CWnd::wndTop, btnLeft, btnTop, btnSize.cx, btnSize.cy, 0);
	btnLeft = rc.Width() - btnSize.cx;
	
	cmdMoveUp_.SetWindowPos(&CWnd::wndTop, btnLeft, btnTop, btnSize.cx, btnSize.cy, 0);
	btnLeft += btnRect.Width();

	lvwStruct_.SetWindowPos(&CWnd::wndTop, 0, 0, rc.Width(), btnTop - 1, SWP_SHOWWINDOW);


}

void CClassInfoDlg_Gui_CatList::OnSize(UINT nType, int cx, int cy) 
{
	CDialog::OnSize(nType, cx, cy);
	
	if (initialized_)
		UpdateWindowSize();
}

void CClassInfoDlg_Gui_CatList::OnCmdEditField() 
{
	CXmlGuiCategoryField* field;
	CXmlGuiCategoryInfo* categoryInfo;
	CCategoryFieldEditorDlg dlg;
	int ret;

	field = GetSelectedField();
	categoryInfo = GetSelectedCategory();
	if (field) {
		dlg.Init(classInfo_, field, categoryList_, categoryInfo->GetCaption());
		ret = dlg.DoModal();
		if (ret == IDOK) 
			BuildList();
	}
}

CXmlGuiCategoryInfo* CClassInfoDlg_Gui_CatList::GetSelectedCategory()
{
	int selCategoryIndex;

	selCategoryIndex = GetSelectedCategoryIndex();	
	if (selCategoryIndex == -1)
		return NULL;
	
	return categoryList_->GetCategory(selCategoryIndex);
}

CXmlGuiCategoryField* CClassInfoDlg_Gui_CatList::GetSelectedField()
{
	CXmlGuiCategoryInfo* selCategory;
	int selFieldIndex;

	selCategory = GetSelectedCategory();
	if (selCategory == NULL)
		return NULL;

	selFieldIndex = GetSelectedFieldIndex();
	if (selFieldIndex == -1)
		return NULL;
	
	return selCategory->GetField(selFieldIndex);
}

void CClassInfoDlg_Gui_CatList::OnCmdEditCategory() 
{
	CXmlGuiCategoryInfo* category;
	CCategoryInfoEditorDlg dlg;
	int ret;

	category = GetSelectedCategory();
	if (category) {
		dlg.Init(category, categoryList_);
		ret = dlg.DoModal();
		if (ret == IDOK) 
			BuildList();
	}
}

void CClassInfoDlg_Gui_CatList::OnDataUpdate()
{
	BuildList();
}








