// ComboTreeCtrl.cpp : implementation file
//

#include "stdafx.h"
#include "ComboTreeCtrl3.h"
#include "TreeComboBox3.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CComboTreeCtrl3

CComboTreeCtrl3::CComboTreeCtrl3()
	:m_pCombo(NULL)
{
}

CComboTreeCtrl3::~CComboTreeCtrl3()
{
}


BEGIN_MESSAGE_MAP(CComboTreeCtrl3, CTreeCtrl)
	//{{AFX_MSG_MAP(CComboTreeCtrl3)
	ON_NOTIFY_REFLECT(NM_KILLFOCUS, OnKillfocus)
	ON_NOTIFY_REFLECT(NM_CLICK, OnClick)
	ON_NOTIFY_REFLECT(TVN_KEYDOWN, OnKeydown)
	//}}AFX_MSG_MAP
	ON_MESSAGE(TREECTRL_CHECK_STATE_CHANGE, OnTreeCtrlCheckStateChange)
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CComboTreeCtrl3 message handlers SetItemState

void CComboTreeCtrl3::Display(CRect rc, CString str)
{	
	SetWindowPos(&wndNoTopMost, rc.left, rc.top, rc.right, rc.bottom, SWP_SHOWWINDOW);

	CWnd* pTopParent = GetParent()->GetParentOwner();
	if(pTopParent != NULL)
	{
		pTopParent->SendMessage(WM_NCACTIVATE,TRUE);
		pTopParent->SetRedraw(TRUE);
	}
	///////////////////////
	if(str=="")return;
	HTREEITEM hItem;
	HTREEITEM hRoot=GetRootItem();
	if(GetNextSiblingItem(hRoot))
	{
		FindItem2("xxxyyyzzz", hRoot);
		hItem=FindItem(str, hRoot);
		if(hItem)
		{
			//	AfxMessageBox("111");
			SetItemState(hItem, TVIS_SELECTED, TVIS_SELECTED);
			EnsureVisible(hItem);
		}

		HTREEITEM hNext=GetNextSiblingItem(hRoot);
		while(hNext)
		{
			FindItem2("xxxyyyzzz", hNext);
			hItem=FindItem(str, hNext);
			if(hItem)
			{
				//  AfxMessageBox("222");
				SetItemState(hItem, TVIS_SELECTED, TVIS_SELECTED);
				EnsureVisible(hItem);
			}

			hNext=GetNextSiblingItem(hNext);
		}
	}
	else
	{
		FindItem2("xxxyyyzzz", hRoot);
		hItem=FindItem(str, hRoot);
		if(hItem)
		{
			//	AfxMessageBox("dddd");
			SetItemState(hItem, TVIS_SELECTED, TVIS_SELECTED);
			EnsureVisible(hItem);
		}
	}
}

BOOL CComboTreeCtrl3::PreTranslateMessage(MSG* pMsg) 
{
	// TODO: Add your specialized code here and/or call the base class

	if(pMsg->hwnd == m_hWnd && pMsg->message == WM_KEYDOWN &&
		(pMsg->wParam == VK_RETURN || pMsg->wParam == VK_ESCAPE))
	{
		::PostMessage(m_pCombo->m_hWnd,WMU_CLOSE_CONTROL,(WPARAM)0,(LPARAM)0);
		return TRUE;
	}

	return CTreeCtrl::PreTranslateMessage(pMsg);
}

void CComboTreeCtrl3::OnKillfocus(NMHDR* pNMHDR, LRESULT* pResult) 
{
	// TODO: Add your control notification handler code here

	::PostMessage(m_pCombo->m_hWnd,WMU_CLOSE_CONTROL,(WPARAM)0,(LPARAM)0);
}

LRESULT CComboTreeCtrl3::OnTreeCtrlCheckStateChange(WPARAM wParam, LPARAM lParam)
{
	HTREEITEM hItemChanged = (HTREEITEM)lParam;
	BOOL bCheckState = GetCheck(hItemChanged);
	SelectItem(hItemChanged);

	if(! bCheckState)UncheckChilds(hItemChanged,TRUE);
	else
	{
		while(hItemChanged = GetParentItem(hItemChanged))
			SetCheck(hItemChanged);
	}

	return 1;
}

void CComboTreeCtrl3::OnClick(NMHDR* pNMHDR, LRESULT* pResult) 
{
	// TODO: Add your control notification handler code here

	UINT nFlags;
	HTREEITEM hItem;
	// verify that we have a mouse click in the check box area 
	DWORD dwPos = GetMessagePos();
	CPoint point(LOWORD(dwPos),HIWORD(dwPos));
	ScreenToClient(&point);
	hItem = HitTest(point,&nFlags);
	if(hItem)
	{
		if(GetParentItem(hItem))
			::PostMessage(m_pCombo->m_hWnd,WMU_CLOSE_CONTROL,(WPARAM)0,(LPARAM)hItem);
		//	AfxMessageBox(GetItemText(hItem));
	}

//	if(hItem && (nFlags  & TVHT_ONITEMSTATEICON))
	//	PostMessage(TREECTRL_CHECK_STATE_CHANGE,0,(LPARAM)hItem);

	*pResult = 0;
}

void CComboTreeCtrl3::OnKeydown(NMHDR* pNMHDR, LRESULT* pResult) 
{
	TV_KEYDOWN* pTVKeyDown = (TV_KEYDOWN*)pNMHDR;
	// TODO: Add your control notification handler code here

	if(pTVKeyDown->wVKey == VK_SPACE)
	{
		HTREEITEM hItem = GetSelectedItem();
		if(hItem != NULL)
		{
			// handle state change here or post message to another handler
			// Post message state has changed
			PostMessage(TREECTRL_CHECK_STATE_CHANGE,0,(LPARAM)hItem);
		}
	}

	*pResult = 0;
}

int CComboTreeCtrl3::UncheckChilds(HTREEITEM hItem/* = NULL*/, BOOL bRecurse/* = TRUE*/)
{
	int nCount = 0;
	if(hItem == NULL)GetSelectedItem();
	if(ItemHasChildren(hItem))
	{
		hItem = GetNextItem(hItem,TVGN_CHILD);
		while(hItem)
		{
			nCount++;
			SetCheck(hItem,FALSE);
			if(bRecurse)nCount += UncheckChilds(hItem,bRecurse);
			hItem = GetNextItem(hItem,TVGN_NEXT);
		}
	}

	return nCount;
}

void CComboTreeCtrl3::GetTreeHierarchy(HTREEITEM hItem, CString &sTreeHierarchy, const BOOL bTopToBottom)
{
	HTREEITEM hRoot = GetParentItem(hItem);
	if(hRoot != NULL)
	{
		sTreeHierarchy += GetItemText(hItem) + "\\";
		return;
	}

	if(! bTopToBottom)sTreeHierarchy += GetItemText(hItem) + "\\";
	GetTreeHierarchy(hRoot,sTreeHierarchy,bTopToBottom);
	if(bTopToBottom)sTreeHierarchy += GetItemText(hItem) + "\\";
}

HTREEITEM CComboTreeCtrl3::FindItem(const CString& sName, HTREEITEM hRoot)
{
	// check whether the current item is the searched one
	CString sText = GetItemText(hRoot);
	if(sText.Compare(sName) == 0)return hRoot;

	// get a handle to the first child item
	HTREEITEM hSub = GetChildItem(hRoot);
	// iterate as long a new item is found
	while(hSub)
	{
		// check the children of the current item
		HTREEITEM hFound = FindItem(sName, hSub);
		if(hFound)return hFound;
		// get the next sibling of the current item
		hSub = GetNextSiblingItem(hSub);
	}

	return NULL;
}

HTREEITEM CComboTreeCtrl3::FindItem2(const CString& sName, HTREEITEM hRoot)
{
	// check whether the current item is the searched one
	CString sText = GetItemText(hRoot);
	if(sText.Compare(sName) == 0)return hRoot;
	SetItemState(hRoot, 0, TVIS_SELECTED);
//	SetItemState(hRoot, 0, TVIS_EXPANDED);
	// get a handle to the first child item
	HTREEITEM hSub = GetChildItem(hRoot);
	// iterate as long a new item is found
	while(hSub)
	{
		SetItemState(hSub, 0, TVIS_SELECTED);
	   // SetItemState(hSub, 0, TVIS_EXPANDED);
		// check the children of the current item
		HTREEITEM hFound = FindItem(sName, hSub);
		if(hFound)return hFound;
		// get the next sibling of the current item
		hSub = GetNextSiblingItem(hSub);
	}
	return NULL;
}