// ComboTree.cpp

#include "stdafx.h"
#include "AplGuiEx.h"

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


//non top level child control ids
#define IDC_COMBOTREE_BUTTON   4317         
#define IDC_COMBOTREE_EDIT     4318 
#define IDC_COMBOTREE_DROPDOWN 4319         


/////////////////////////////////////////////////////////////////////////////
// ComboTree

CComboTree::CComboTree()
{
	m_Tree.SetCombo(this);
	m_ComboWidth = 200;
	m_ComboHeight = 200;
	m_bDroppedState = FALSE;
	m_bCreateWithCheckboxes = FALSE;
	m_bSelectOnlyChilds=false;
}

CComboTree::~CComboTree()
{
}

BEGIN_MESSAGE_MAP(CComboTree, CWnd)
	//{{AFX_MSG_MAP(ComboTree)
	ON_WM_CREATE()
	ON_WM_SETFOCUS()
	ON_WM_KILLFOCUS()
	ON_WM_GETDLGCODE()
	ON_WM_MOUSEACTIVATE()
	ON_WM_MOUSEWHEEL()
	ON_WM_MOUSEMOVE()
	//}}AFX_MSG_MAP
	ON_BN_CLICKED(IDC_COMBOTREE_BUTTON, OnDropdownButton)
	ON_NOTIFY(NM_CLICK, IDC_COMBOTREE_EDIT, OnDropdownEdit)
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// ComboTree message handlers

int CComboTree::OnMouseActivate(CWnd* pDesktopWnd, UINT nHitTest, UINT message) 
{
	UNREFERENCED_PARAMETER(pDesktopWnd);
	UNREFERENCED_PARAMETER(nHitTest);
	UNREFERENCED_PARAMETER(message);

	return MA_ACTIVATE;   
}

void CComboTree::OnMouseMove(UINT nFlags, CPoint point)
{
	UNREFERENCED_PARAMETER(nFlags);
	UNREFERENCED_PARAMETER(point);
}

BOOL CComboTree::OnMouseWheel(UINT nFlags, short zDelta, CPoint pt)
{
	UNREFERENCED_PARAMETER(nFlags);
	UNREFERENCED_PARAMETER(zDelta);
	UNREFERENCED_PARAMETER(pt);

	return 0;
}

LRESULT CComboTree::SendParentComboMessage(UINT Action)
{
	CWnd* pParent = GetParent();
	if (pParent && pParent->GetSafeHwnd())
	{
		return pParent->SendMessage(WM_COMMAND, MAKEWPARAM( GetDlgCtrlID(), Action),(LPARAM)GetSafeHwnd());
	}

	return 0L;
}

void CComboTree::SetWindowText(LPCTSTR Text)
{
	m_Edit.SetWindowText(Text);
	Invalidate();
}

CString CComboTree::GetWindowText()
{
	CString Text;
	m_Edit.GetWindowText(Text);
	return Text;
}

int CComboTree::GetLBText(HTREEITEM hItem, CString& rText)
{
  int retval = CB_ERR;
  rText = m_Tree.GetItemText(hItem);
  if (rText.GetLength() > 0)
  {
	retval = 0;
  }
  return retval;
}

BOOL CComboTree::SetCheck(HTREEITEM hItem, BOOL bChecked)
{
	if (m_Tree.IsItemChecked(hItem))
	{
		if (bChecked)
		{
			//already checked
			return m_Tree.SetCheck(hItem, CComboTreeDropList::REFRESH);
		}
		else
		{
			//uncheck
			return m_Tree.SetCheck(hItem, CComboTreeDropList::UNCHECK);
		}
	}
	else
	{
		if (bChecked)
		{
			return m_Tree.SetCheck(hItem, CComboTreeDropList::CHECK);
		}
		else
		{
			//already unchecked
			return m_Tree.SetCheck(hItem, CComboTreeDropList::REFRESH);
		}
	}
}

void CComboTree::HideTree()
{
	SetDroppedState(FALSE);
	m_Tree.ShowWindow(SW_HIDE);

	//Tree is no longer displayed, stop message interception
	m_ComboTreeHook.UnhookParent();

	m_Edit.Invalidate();
	m_DropDownButton.Invalidate();
	Invalidate();
}

void CComboTree::ShowTree()
{
	//Must set focus to edit here or dropdown will still have it and act on
	//arrow key messages
		
	m_Edit.SetFocus();
	DisplayTree();
	m_BeginPath = m_Tree.GetCurrentTreePath();
	SendParentComboMessage(CBN_DROPDOWN);

	//Must call this to intercept parent window messsages
	m_ComboTreeHook.HookParent();

	m_Edit.Invalidate();
	m_DropDownButton.Invalidate();
	Invalidate();

	ReleaseCapture();
}

void CComboTree::OnDropdownButton()
{
    if (GetDroppedState())
	{
		OnSelection();
	}
	else
	{
		ShowTree();
	}
}

void CComboTree::OnDropdownEdit(NMHDR* pNMHDR, LRESULT* pResult)
{
	*pResult = 0;
}

void CComboTree::CalculateDroppedRect(LPRECT lpDroppedRect)
{
	_ASSERTE(lpDroppedRect);

	if (!lpDroppedRect)
	{
		return;
	}

	CRect rectCombo;
	GetWindowRect(&rectCombo);

	//adjust to either the top or bottom
	int DropTop = rectCombo.bottom;
	int ScreenHeight = GetSystemMetrics(SM_CYSCREEN);
	if ((DropTop + m_ComboHeight) > ScreenHeight)
	{
		DropTop = rectCombo.top - m_ComboHeight;
	}

	//adjust to either the right or left
	int DropLeft = rectCombo.left;
	int ScreenWidth = GetSystemMetrics(SM_CXSCREEN);
	if ((DropLeft + m_ComboWidth) > ScreenWidth)
	{
		DropLeft = rectCombo.right - m_ComboWidth;
	}

	lpDroppedRect->left  = DropLeft;
	lpDroppedRect->top   = DropTop;
	lpDroppedRect->bottom = DropTop + m_ComboHeight;
	lpDroppedRect->right  = DropLeft + m_ComboWidth;
}

void CComboTree::DisplayTree()
{
	CRect rect(0,0,200,200);

	CalculateDroppedRect(&rect);

	m_Tree.SetWindowPos(&wndTopMost, rect.left, rect.top,
		                 rect.Width(), rect.Height(), SWP_SHOWWINDOW );

	SetDroppedState(TRUE);

	m_Tree.PostMessage(WM_SETFOCUS);
	m_Tree.SetActiveWindow();
	m_Tree.SetForegroundWindow();
}


BOOL CComboTree::SetHasCheckboxes(BOOL bHasCheckboxes)
{
	//can't call this tree has no checkboxes
	if (m_bCreateWithCheckboxes == bHasCheckboxes)
	{
		//already set to this value
		return TRUE;
	}
	
	if (m_Tree.GetSafeHwnd())
	{
		_ASSERTE(("Checkbox style must be set before tree is created!", FALSE));
		return FALSE;
	}

	m_bCreateWithCheckboxes = bHasCheckboxes;

	return TRUE;
}

BOOL CComboTree::GetHasCheckboxes()
{
	return m_bCreateWithCheckboxes;
}

BOOL CComboTree::CreateTree()
{	
	CWnd* pParent = GetParent();
	if (pParent==NULL || pParent->GetSafeHwnd()==NULL)
	{
		return FALSE;
	}

	CRect treeRect(0,0, m_ComboWidth, m_ComboHeight);

	//can't have a control Id with WS_POPUP style
	CWnd* pDesktop = GetDesktopWindow();
	if(m_Tree.m_hWnd == 0)
	{
		if (! m_Tree.CreateEx(  WS_EX_LEFT | WS_EX_LTRREADING | WS_EX_RIGHTSCROLLBAR | WS_EX_TOOLWINDOW , 
			WS_CHILD | WS_BORDER | TVS_SINGLEEXPAND | TVS_HASLINES | TVS_LINESATROOT | TVS_HASBUTTONS | TVS_NOTOOLTIPS ,
			treeRect, pDesktop, IDC_COMBOTREE_DROPDOWN))
		{
			return FALSE;
		}
	}

	m_ComboTreeHook.Init(::GetParent(m_hWnd), this);	 // initialize

	return TRUE;
}

BOOL CComboTree::CreateButton()
{	
	CRect btnRect;
	GetClientRect(&btnRect);

	int width = GetSystemMetrics(SM_CXVSCROLL);
	btnRect.left = 	btnRect.right - width;
	
     m_DropDownButton.CreateEx( 0, _T("BUTTON"), NULL,
								WS_TABSTOP | BS_PUSHBUTTON | BS_NOTIFY | WS_VISIBLE | WS_CHILD | BS_OWNERDRAW,
								btnRect, this, IDC_COMBOTREE_BUTTON);

	m_DropDownButton.MoveWindow(&btnRect);

	return TRUE;
}

//Requires that dropdown button be created first, to size it properly
BOOL CComboTree::CreateEdit()
{	
	if (!m_DropDownButton.GetSafeHwnd())
	{
		return FALSE;
	}

	CRect clientRect;
	GetClientRect(&clientRect);

	CRect btnRect;
	m_DropDownButton.GetWindowRect(&btnRect);
	ScreenToClient(&btnRect);

	CRect editRect;
	editRect.left = clientRect.left;
	editRect.top = clientRect.top;
	editRect.bottom = clientRect.bottom;
	editRect.right = btnRect.left;

	BOOL bCreate = m_Edit.Create(WS_CHILD |  WS_TABSTOP | WS_VISIBLE ,  editRect, this, IDC_COMBOTREE_EDIT);


	if (bCreate)
	{
		CWnd* pParent = GetParent();
		CFont* pFont = pParent->GetFont();
		m_Edit.SetFont(pFont);
	}

	return bCreate;
}

//Creates ComboTree window, used by SubclassDlgItem
BOOL CComboTree::Create( const RECT& rect, int DroppedWidth, int DroppedHeight, CWnd* pParentWnd, UINT nID )
{
	ASSERT(pParentWnd != NULL);
	if (!pParentWnd)
	{
		return FALSE;
	}

	m_ComboWidth = DroppedWidth;
	m_ComboHeight = DroppedHeight;

   CString className = AfxRegisterWndClass( CS_VREDRAW | CS_HREDRAW | CS_DBLCLKS,
											::LoadCursor(NULL, IDC_ARROW),
											(HBRUSH)::GetStockObject(WHITE_BRUSH));

   BOOL bCreate =  __super::CreateEx(WS_EX_CLIENTEDGE, className, NULL, WS_CHILD | WS_BORDER, rect, pParentWnd, nID);

	_ASSERTE(bCreate);

	if (!bCreate)
	{
		return FALSE;
	}

	UpdateWindow();

	return TRUE;
}

int CComboTree::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
	if (CWnd::OnCreate(lpCreateStruct) == -1)
		return -1;

	if (!CreateTree())
	{
		return -1;
	}

	if (!CreateButton())
	{
		return -1;
	}

	if (!CreateEdit())
	{
		return -1;
	}

	return 0;
}

CString CComboTree::GetTreePath(HTREEITEM hItem)
{
	return m_Tree.GetTreePath(hItem);
}

CString CComboTree::GetCurrentTreePath()
{
	return m_Tree.GetCurrentTreePath();
}

void CComboTree::SetDelimiter(CString delimiter)
{
	m_Tree.SetPathDelimiter(delimiter);
}

CString CComboTree::GetDelimiter()
{
	return m_Tree.GetPathDelimiter();
}

HTREEITEM CComboTree::AddString(LPCTSTR lpszString)
{
	return m_Tree.AddString(lpszString);
}

HTREEITEM CComboTree::FindString(LPCTSTR lpszString, HTREEITEM hParent /*=NULL*/)
{
	return m_Tree.FindString(lpszString, hParent);
}

int CComboTree::DeleteString(HTREEITEM hItem)
{
	HTREEITEM hSelected = m_Tree.GetSelectedItem();
	if (m_Tree.DeleteItem(hItem))
	{
		if (hItem == hSelected)
		{
			//get the new item
			hItem = m_Tree.GetSelectedItem();
			if (hItem)
			{
				CString NodeText = m_Tree.GetItemText(hItem);
				SetWindowText(NodeText);
				SendParentComboMessage(CBN_SELCHANGE);
			}
			else
			{
				SetWindowText(_T(""));
			}
		}
		return 0;
	}
	else
	{
		return CB_ERR;
	}
}

HTREEITEM CComboTree::SelectString(LPCTSTR lpszString, HTREEITEM hParent /*=NULL*/)
{
	HTREEITEM hMatch = m_Tree.SelectString(lpszString, hParent);
	CString NodeText = m_Tree.GetItemText(hMatch);
	SetWindowText(NodeText);

	SendParentComboMessage(CBN_SELCHANGE);

	return hMatch;
}

HTREEITEM CComboTree::GetCurSel()
{
	return m_Tree.GetSelectedItem();
}

int CComboTree::SetItemData(HTREEITEM hItem, DWORD dwItemData)
{
	if (!m_Tree.SetItemData(hItem, dwItemData))
	{
		return CB_ERR;
	}
	else 
	{
		return 0;
	}
}

DWORD CComboTree::GetItemData(HTREEITEM hItem)
{
	return m_Tree.GetItemData(hItem);
}

void CComboTree::ShowDropDown(BOOL bShowIt)
{
	if (bShowIt)
	{
		if (!GetDroppedState())
		{
			ShowTree();
		}
	}
	else 
	{
		if (!GetDroppedState())
		{
			return; //there is no active dropdown, can't hide
		}
	
		HideTree();
	}
}

void CComboTree::ResetContent()
{
	m_Tree.DeleteAllItems( );
}

int CComboTree::SetDroppedWidth(UINT nWidth)
{
	int retval = 0;
	if (nWidth >= 0) //-V547
	{
		m_ComboWidth = nWidth;
		if (GetDroppedState())
		{
			DisplayTree();
		}
	}
	else
	{
		retval = CB_ERR;
	}
	return retval;
}

int CComboTree::GetDroppedWidth( )
{
	return m_ComboWidth;
}

int CComboTree::SetDroppedHeight(UINT nHeight)
{
	int retval = 0;
	if (nHeight >= 0) //-V547
	{
		m_ComboHeight = nHeight;
		if (GetDroppedState())
		{
			DisplayTree();
		}
	}
	else
	{
		retval = CB_ERR;
	}
	return retval;
}

int CComboTree::GetDroppedHeight()
{
	return m_ComboHeight;
}

BOOL CComboTree::GetDroppedState( )
{
	return m_bDroppedState;
}

void CComboTree::GetDroppedControlRect(LPRECT pRect)
{
	_ASSERTE(pRect);
	if (pRect)
	{
		CalculateDroppedRect(pRect);
	}
}

void CComboTree::OnSetFocus(CWnd* pOldWnd)
{
	CWnd::OnSetFocus(pOldWnd);
	if (::GetFocus() != m_DropDownButton.GetSafeHwnd())
	{
		m_Edit.Invalidate();
	}
}

BOOL CComboTree::IsMouseOnTree()
{
	BOOL bMouseOn = FALSE;
	CPoint point;
	if (GetCursorPos(&point))
	{
		CRect rect;
		m_Tree.GetWindowRect(&rect);
		if (rect.PtInRect(point))
		{
			bMouseOn = TRUE;
		}
	}
	return bMouseOn;
}

BOOL CComboTree::IsMouseOnButton()
{
	BOOL bMouseOn = FALSE;
	CPoint point;
	if (GetCursorPos(&point))
	{
		CRect rect;
		m_DropDownButton.GetWindowRect(&rect);
		if (rect.PtInRect(point))
		{
			bMouseOn = TRUE;
		}
	}
	return bMouseOn;
}

BOOL CComboTree::IsMouseOnEdit()
{
	BOOL bMouseOn = FALSE;
	CPoint point;
	if (GetCursorPos(&point))
	{
		CRect rect;
		m_Edit.GetWindowRect(&rect);
		if (rect.PtInRect(point))
		{
			bMouseOn = TRUE;
		}
	}
	return bMouseOn;
}

BOOL CComboTree::IsEditHighlightOn()
{
	BOOL bHighlightOn = FALSE;
	HWND hFocus = ::GetFocus();

	if (hFocus == GetSafeHwnd() || 
		hFocus == m_Edit.GetSafeHwnd() ||
		hFocus == m_DropDownButton.GetSafeHwnd())
	{
		bHighlightOn = TRUE;
	}

	return bHighlightOn;
}

void CComboTree::OnKillFocus(CWnd* pNewWnd)
{
	CWnd::OnKillFocus(pNewWnd);
	
	m_Edit.Invalidate();	
}

BOOL CComboTree::OnCommand(WPARAM wParam, LPARAM lParam)
{
	if (HIWORD(wParam) == BN_KILLFOCUS	)
	{
		m_Edit.Invalidate();
	}

	return CWnd::OnCommand(wParam, lParam);
}

BOOL CComboTree::OnKeyDropdownInactive(UINT message, UINT nChar)
{
	if(GetDroppedState())
	{
		return FALSE;
	}

	if ((message == WM_SYSKEYDOWN))
	{
		if ((nChar == VK_DOWN))
		{
			ShowTree();
			return FALSE;
		}
	}
	else if ((message == WM_KEYDOWN) && (nChar == VK_F4))
	{
		ShowTree();
		return FALSE;
	}
	else if ((message == WM_KEYDOWN) && (nChar == VK_TAB))
	{
		
		BOOL bShift = (GetKeyState(VK_SHIFT) < 0);
		
		CWnd* pComboParent = GetParent();
		if (pComboParent && pComboParent->GetSafeHwnd())
		{
			CWnd* pNext = pComboParent->GetNextDlgTabItem(this, bShift);
			if (pNext && pNext->GetSafeHwnd())
			{
//				TRACE("ComboTree::OnKeyDropdownInactive() -Moving focus\n");
				pNext->SetFocus();
			}
		}
		return FALSE;
	}

	return TRUE;
}

BOOL CComboTree::OnKeyDropdownActive(UINT message, UINT nChar)
{
	if(!GetDroppedState())
	{
		return FALSE;
	}

	if (message == WM_SYSKEYDOWN)
	{
		if ((nChar == VK_UP))
		{
			OnSelection();
			return FALSE;
		}
	}
	else if ((message == WM_KEYDOWN) && (nChar == VK_F4))
	{
		OnSelection();
		return FALSE;
	}
	else if (nChar == VK_RETURN)
	{
		OnSelection(true);
		return FALSE;
	}
	else if (nChar == VK_ESCAPE)
	{
		OnCancel();
		return FALSE;
	}
	else if ((message == WM_KEYDOWN) && (nChar == VK_TAB))
	{
		OnSelection();
		
		BOOL bShift = (GetKeyState(VK_SHIFT) < 0);
		
		CWnd* pComboParent = GetParent();
		if (pComboParent && pComboParent->GetSafeHwnd())
		{
			CWnd* pNext = pComboParent->GetNextDlgTabItem(this, bShift);
			if (pNext && pNext->GetSafeHwnd())
			{
//				TRACE("ComboTree::OnKeyDropdownActive(() Moving Focus\n");
				pNext->SetFocus();
			}
		}
		return FALSE;
	}

	return TRUE;
}

BOOL CComboTree::PreTranslateMessage(MSG* pMsg)
{
	if(GetDroppedState())
	{
		BOOL bContinue = TRUE;
		if ((pMsg->message >= WM_KEYFIRST) && (pMsg->message <= WM_KEYLAST))
		{
			bContinue = OnKeyDropdownActive(pMsg->message, pMsg->wParam);
			if (bContinue)
			{
				bContinue = m_Tree.SendMessage( pMsg->message, pMsg->wParam, pMsg->lParam);
			}
			if (!bContinue)
			{
				return FALSE;
			}
		}
	}
	else //not dropped down
	{
		BOOL bContinue = TRUE;
		if ((pMsg->message >= WM_KEYFIRST) && (pMsg->message <= WM_KEYLAST))
		{
			bContinue = OnKeyDropdownInactive(pMsg->message, pMsg->wParam);
			if (!bContinue)
			{
				return FALSE;
			}
		}
	}

	return CWnd::PreTranslateMessage(pMsg);
}

UINT CComboTree::OnGetDlgCode()
{
	UINT result = CWnd::OnGetDlgCode();
	result |= DLGC_WANTALLKEYS | DLGC_WANTARROWS | DLGC_WANTCHARS ;
	
	return result;
}

void CComboTree::OnSelection(bool bEnd /*= false*/)
{
	bool bIsChild=IsChildItem();
	if ( m_Tree.GetSafeHwnd() )
	{
		HTREEITEM hItem = m_Tree.GetSelectedItem();
		if (hItem)
		{
			if(m_bSelectOnlyChilds==false || (m_bSelectOnlyChilds && bIsChild))
			{
				CString Text;
				Text = m_Tree.GetItemText(hItem);
				SetWindowText(Text);
				SendParentComboMessage(CBN_SELENDOK);
//				TRACE("ComboTree::OnSelection()\n");
			}
		}
	}

	if(m_bSelectOnlyChilds==false || (m_bSelectOnlyChilds && bIsChild))
	{
		HideTree();
	}
}

void CComboTree::OnCancel()
{
	//restore inital path
	m_Tree.SelectString(m_BeginPath);
	SendParentComboMessage(CBN_SELENDCANCEL);
	HideTree();
}

bool CComboTree::IsChildItem()
{
	bool bResult=true;
	HTREEITEM hItem = m_Tree.GetSelectedItem();
	if (hItem)
	{
		if( m_Tree.ItemHasChildren( hItem ) )
		{
			bResult=false;
		}
	}
	return bResult;
}


/////////////////////////////////////////////////////////////////////////////
// CaplLB_ComboTree
IMPLEMENT_DYNAMIC(CaplLB_ComboTree, CComboTree)

CaplLB_ComboTree::CaplLB_ComboTree()
{
	m_x = m_y = m_cx = m_cy = 0;
	m_bFullWindowText = false;
}

CaplLB_ComboTree::~CaplLB_ComboTree()
{
}


BEGIN_MESSAGE_MAP(CaplLB_ComboTree, CComboTree)
	//{{AFX_MSG_MAP(CaplLB_ComboTree)
	ON_CONTROL_REFLECT(CBN_KILLFOCUS, OnKillfocus)
	ON_WM_KILLFOCUS()
	ON_WM_LBUTTONDOWN()
	ON_WM_MOVE()
	ON_WM_SIZE()
	ON_WM_MOUSEACTIVATE()
	ON_WM_MOUSEWHEEL()
	ON_WM_MOUSEMOVE()
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CaplLB_ComboTree message handlers

void CaplLB_ComboTree::OnMove(int x, int y)
{
	if( x == m_x && y == m_y )
	{
		m_Edit.Invalidate();
		return;
	}

	__super::OnMove(x, y);

	m_x = x;
	m_y = y;

	m_Edit.MoveWindow(0, 0, m_cx-GetSystemMetrics(SM_CXVSCROLL)-1, m_cy);
	m_DropDownButton.MoveWindow(m_cx-GetSystemMetrics(SM_CXVSCROLL), 0, GetSystemMetrics(SM_CXVSCROLL), m_cy);
}

void CaplLB_ComboTree::OnSize(UINT nType, int x, int y)
{
	if( x == m_cx && y == m_cy )
	{
		m_Edit.Invalidate();
		return;
	}

	__super::OnSize(nType, x, y);

	m_cx = x;
	m_cy = GetSystemMetrics(SM_CYVSCROLL);

	MoveWindow( m_x-GetSystemMetrics(SM_CXFIXEDFRAME),
				m_y-GetSystemMetrics(SM_CYFIXEDFRAME),
				m_cx+GetSystemMetrics(SM_CXFIXEDFRAME)*2,
				m_cy+GetSystemMetrics(SM_CYFIXEDFRAME)*2);
	m_Edit.MoveWindow(0, 0, m_cx-GetSystemMetrics(SM_CXVSCROLL)-1, m_cy);
	m_DropDownButton.MoveWindow(m_cx-GetSystemMetrics(SM_CXVSCROLL), 0, GetSystemMetrics(SM_CXVSCROLL), m_cy);
}

void CaplLB_ComboTree::OnKillfocus()
{
	if( IsMouseOnTree() )
		return;

	if(GetDroppedState())
	{
		CWnd* parent = GetParent();
		if (parent)
			parent->SetFocus();	
	}
	else
	{
		ReleaseCapture();
	}
}

void CaplLB_ComboTree::OnKillFocus(CWnd* pNewWnd)
{
	__super::OnKillFocus(pNewWnd);

	OnKillfocus();
}

int CaplLB_ComboTree::OnMouseActivate(CWnd* pDesktopWnd, UINT nHitTest, UINT message)
{
	return __super::OnMouseActivate(pDesktopWnd, nHitTest, message);
}

void CaplLB_ComboTree::OnMouseMove(UINT nFlags, CPoint point)
{
	__super::OnMouseMove(nFlags, point);
}

BOOL CaplLB_ComboTree::OnMouseWheel(UINT nFlags, short zDelta, CPoint pt)
{
	if(IsMouseOnTree() && GetDroppedState())
		return m_Tree.OnMouseWheel(nFlags, zDelta, pt);
	else
		return __super::OnMouseWheel(nFlags, zDelta, pt);
}

void CaplLB_ComboTree::OnLButtonDown(UINT nFlags, CPoint point)
{
	CPoint pt(point);
	CRect rect;
	GetWindowRect(rect);
	ClientToScreen(&pt);
	if(!rect.PtInRect(pt))
	{
//		if(IsMouseOnTree() && GetDroppedState())
//		{
//			ReleaseCapture();
//
//			CPoint ptt(point);
//			m_Tree.ClientToScreen(&ptt);
//			CPoint p;
//			p.x = point.x + pt.x - ptt.x;
//			p.y = point.y + pt.y - ptt.y;
//			return m_Tree.OnLButtonDown(nFlags, p);
//		}

		CaplListCtrl *pList = (CaplListCtrl*)GetParent();
		if(pList)
		{
			if(::IsWindow(pList->m_hWnd))
			{
				if(pList->EndEdit() && !pList->m_sErrorText.IsEmpty())
				{
					SetCapture();
					return;
				}
				ReleaseCapture();
			}
		}
	}
	else
	{
		if(IsMouseOnEdit() || IsMouseOnButton())
		{
			if(GetDroppedState())
			{
				OnSelection();
			}
			else
			{
				ShowTree();
			}
		}
		else
			CComboTree::OnLButtonDown(nFlags, point);
	}
}
void CaplLB_ComboTree::CalculateDroppedRect(LPRECT lpDroppedRect)
{
	_ASSERTE(lpDroppedRect);

	if (!lpDroppedRect)
	{
		return;
	}

	CRect rectCombo;
	GetWindowRect(&rectCombo);

	int DropTop = rectCombo.bottom;

	///////////////////////////////////////////////////////////////////////////
	CString    str;
	CSize      sz;
	int        dx = 0;
	TEXTMETRIC tm;
	CDC*       pDC = m_Tree.GetDC();
	CFont*     pFont = m_Tree.GetFont();

	// Select the listbox font, save the old font
	CFont* pOldFont = pDC->SelectObject(pFont);
	// Get the text metrics for avg char width
	pDC->GetTextMetrics(&tm);

	int nCount = 0;
	for( HTREEITEM hItem = m_Tree.GetRootItem(); hItem != NULL; )
	{
		GetLBText(hItem, str);
		sz = pDC->GetTextExtent(str);

		// Add the avg width to prevent clipping
		sz.cx += tm.tmAveCharWidth;

		bool isExpand = true;
		int nParent = 0;
		HTREEITEM hParentItem = hItem;
		while( hParentItem )
		{
			hParentItem = m_Tree.GetParentItem(hParentItem);
			if( isExpand )
			{
				if( hParentItem )
					isExpand = (m_Tree.GetItemState(hParentItem, TVIS_EXPANDED) & TVIS_EXPANDED) ? true : false;
				else if( !nParent )
					isExpand = true;
			}
			nParent++;
		}
		sz.cx += nParent*m_Tree.GetIndent();

		hItem = m_Tree.GetNextItem(hItem);

		if( isExpand )
		{
			if (sz.cx > dx)
				dx = sz.cx;

			nCount++;
		}
	}
	// Select the old font back into the DC
	pDC->SelectObject(pOldFont);
	ReleaseDC(pDC);

	// Adjust the width for the vertical scroll bar
	SCROLLBARINFO sbi;
	sbi.cbSize = sizeof(SCROLLBARINFO);
	m_Tree.GetScrollBarInfo(OBJID_VSCROLL, &sbi);
	if( !(sbi.rgstate[0]&STATE_SYSTEM_INVISIBLE) )
		dx += ::GetSystemMetrics(SM_CXVSCROLL);

	int sdx = ::GetSystemMetrics(SM_CXSCREEN) - rectCombo.left;
	if( dx < sdx ) sdx = dx;
	dx = rectCombo.right - rectCombo.left;
	if( dx > sdx ) sdx = dx;

	int sdy = (nCount+1)*(tm.tmHeight+tm.tmInternalLeading+tm.tmExternalLeading);
	if( sdy > m_ComboHeight ) sdy = m_ComboHeight;
	///////////////////////////////////////////////////////////////////////////

	int ScreenHeight = GetSystemMetrics(SM_CYSCREEN);
	if ((DropTop + sdy) > ScreenHeight)
	{
		DropTop = rectCombo.top - sdy;
	}
	int DropLeft = rectCombo.left;

	lpDroppedRect->left  = DropLeft;
	lpDroppedRect->top   = DropTop;
	lpDroppedRect->bottom = DropTop + sdy;
	lpDroppedRect->right  = DropLeft + sdx;
}

void CaplLB_ComboTree::OnCancel()
{
	__super::OnCancel();

	CaplListCtrl *pList = (CaplListCtrl*)GetParent();
	if(pList)
	{
		if(::IsWindow(pList->m_hWnd))
		{
			if(pList->EndEdit() && !pList->m_sErrorText.IsEmpty())
			{
				SetCapture();
				return;
			}
			ReleaseCapture();
		}
	}
}

void CaplLB_ComboTree::OnSelection(bool bEnd /*= false*/)
{
	bool bIsChild = IsChildItem();
	if( m_Tree.GetSafeHwnd() )
	{
		HTREEITEM hItem = m_Tree.GetSelectedItem();
		if (hItem)
		{
			if(m_bSelectOnlyChilds==false || (m_bSelectOnlyChilds && bIsChild))
			{
				if( m_bFullWindowText == false )
					SetWindowText(m_Tree.GetItemText(hItem));
				else
					SetWindowText(m_Tree.GetTreePath(hItem));
				SendParentComboMessage(CBN_SELENDOK);
			}
		}
	}

	if(m_bSelectOnlyChilds==false || (m_bSelectOnlyChilds && bIsChild))
	{
		HideTree();

		if (bEnd)
		{
			CaplListCtrl *pList = (CaplListCtrl*)GetParent();
			if(pList)
			{
				if(::IsWindow(pList->m_hWnd))
				{
					ReleaseCapture();

					NMHDR nmHDR;
					memset(&nmHDR, 0, sizeof(NMHDR));
					nmHDR.idFrom = GetDlgCtrlID();
					nmHDR.hwndFrom = m_hWnd;
					nmHDR.code = APL_LC_CBN_SELCHANGE;
					pList->SendMessage(WM_NOTIFY, pList->GetDlgCtrlID(), (LPARAM)&nmHDR);
				}
			}
		}
	}
}

int CaplLB_ComboTree::DeleteString( HTREEITEM hItem )
{
	HTREEITEM hSelected = m_Tree.GetSelectedItem();
	if (m_Tree.DeleteItem(hItem))
	{
		if (hItem == hSelected)
		{
			//get the new item
			hItem = m_Tree.GetSelectedItem();
			if (hItem)
			{
				if( m_bFullWindowText == false )
					SetWindowText(m_Tree.GetItemText(hItem));
				else
					SetWindowText(m_Tree.GetTreePath(hItem));
				SendParentComboMessage(CBN_SELCHANGE);
			}
			else
			{
				SetWindowText(_T(""));
			}
		}
		return 0;
	}
	else
	{
		return CB_ERR;
	}
}

HTREEITEM CaplLB_ComboTree::SelectString( LPCTSTR lpszString, HTREEITEM hParent /*=NULL*/)
{
	HTREEITEM hMatch = m_Tree.SelectString(lpszString, hParent);
	if( m_bFullWindowText == false )
		SetWindowText(m_Tree.GetItemText(hMatch));
	else
		SetWindowText(m_Tree.GetTreePath(hMatch));

	SendParentComboMessage(CBN_SELCHANGE);

	return hMatch;
}
