/****************************************************************************************/
/*  GROUPTREECTRL.CPP                                                                   */
/*                                                                                      */
/*  Author:                                                                             */
/*  Description:                                                                        */
/*                                                                                      */
/*  The contents of this file are subject to the Jet3D Public License                   */
/*  Version 1.02 (the "License"); you may not use this file except in                   */
/*  compliance with the License. You may obtain a copy of the License at                */
/*  http://www.jet3d.com                                                                */
/*                                                                                      */
/*  Software distributed under the License is distributed on an "AS IS"                 */
/*  basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.  See                */
/*  the License for the specific language governing rights and limitations              */
/*  under the License.                                                                  */
/*                                                                                      */
/*  The Original Code is Jet3D, released December 12, 1999.                             */
/*  Copyright (C) 1996-1999 Eclipse Entertainment, L.L.C. All Rights Reserved           */
/*                                                                                      */
/****************************************************************************************/

#include "stdafx.h"
#include "jwe.h"
#include "grouptreectrl.h"

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

/////////////////////////////////////////////////////////////////////////////
// CGroupTreeCtrl

CGroupTreeCtrl::CGroupTreeCtrl()
{
	m_bDragging = FALSE;
	m_pimagelist = NULL;
}

CGroupTreeCtrl::~CGroupTreeCtrl()
{
}


BEGIN_MESSAGE_MAP(CGroupTreeCtrl, CTreeCtrlEx)
	//{{AFX_MSG_MAP(CGroupTreeCtrl)
	ON_NOTIFY_REFLECT(TVN_BEGINDRAG, OnBegindrag)
	ON_WM_LBUTTONUP()
	ON_WM_MOUSEMOVE()
	ON_WM_LBUTTONDOWN()
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CGroupTreeCtrl message handlers

void CGroupTreeCtrl::OnBegindrag(NMHDR* pNMHDR, LRESULT* pResult) 
{

	HTREEITEM	hitItemDrag;
	HTREEITEM	hitItemParent;
	CPoint      ptAction;
	UINT        nFlags;

	GetCursorPos(&ptAction);
	ScreenToClient(&ptAction);
	
	//((CTreeCtrlPage *)GetParent())->ShowNotification(pnmhdr, pLResult);
	ASSERT(!m_bDragging);
	hitItemDrag = HitTest(ptAction, &nFlags);
	hitItemParent = GetParentItem( hitItemDrag );
	//We can only drag leaf items for now.
	if( hitItemParent == NULL )
		return;
	m_bDragging = TRUE;
	m_hitemDrag = hitItemDrag;
	m_hitemDrop = NULL;

	m_pimagelist = CreateDragImage(m_hitemDrag);  // get the image list for dragging
	if(m_pimagelist == NULL)
		return;
	m_pimagelist->DragShowNolock(TRUE);
	m_pimagelist->SetDragCursorImage(0, CPoint(0, 0));
	m_pimagelist->BeginDrag(0, CPoint(0,0));
	m_pimagelist->DragMove(ptAction);
	m_pimagelist->DragEnter(this, ptAction);
	SetCapture();
	*pResult = 0;
	pNMHDR;
}

BOOL CGroupTreeCtrl::IsChildNodeOf(HTREEITEM hitemChild, HTREEITEM hitemSuspectedParent)
{
	do
	{
		if (hitemChild == hitemSuspectedParent)
			break;
	}
	while ((hitemChild = GetParentItem(hitemChild)) != NULL);

	return (hitemChild != NULL);
}

HTREEITEM CGroupTreeCtrl::TransferItem( HTREEITEM hitemDrag, HTREEITEM hitemDrop )
{
	TV_INSERTSTRUCT     tvstruct;
	TCHAR               sztBuffer[50];
	HTREEITEM hNewItem;
	long Data;

	tvstruct.item.hItem = hitemDrag;
	tvstruct.item.cchTextMax = 49;
	tvstruct.item.pszText = sztBuffer;
	tvstruct.item.mask = TVIF_CHILDREN | TVIF_HANDLE | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_TEXT;
	GetItem(&tvstruct.item);  // get information of the dragged element
	tvstruct.hParent = hitemDrop;
	tvstruct.hInsertAfter = TVI_SORT;
	tvstruct.item.mask = TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_TEXT;
	hNewItem = InsertItem(&tvstruct);
	Data = GetItemData( hitemDrag );
	SetItemData( hNewItem, Data );
	return( hNewItem );
}

void CGroupTreeCtrl::OnLButtonUp(UINT nFlags, CPoint point) 
{
	NM_TREEVIEW tv;

	if (m_bDragging)
	{
		ASSERT(m_pimagelist != NULL);
		m_pimagelist->DragLeave(this);
		m_pimagelist->EndDrag();
		delete m_pimagelist;
		m_pimagelist = NULL;

		if ( m_hitemDrop != NULL && // Cant drop  item to root
			m_hitemDrag != m_hitemDrop && //Cant drop item on self 
			!IsChildNodeOf(m_hitemDrop, m_hitemDrag) && //Cant drop item back in same group
			GetParentItem(m_hitemDrag) != m_hitemDrop &&
			GetParentItem(m_hitemDrop) == NULL			//Drop Item must be group
			)
		{
			HTREEITEM hNewItem;

			hNewItem = TransferItem(m_hitemDrag, m_hitemDrop);
			// Notify that selection has changed, by sending a TVM_INSERTITEM notification
			//DeleteItem(m_hitemDrag); //Moved some lines down !!! JH
			CWnd* pWnd = GetParent();
			if ( pWnd )
			{
				tv.hdr.hwndFrom = GetSafeHwnd();
				tv.hdr.idFrom = GetWindowLong( GetSafeHwnd(), GWL_ID );
				tv.hdr.code = TVN_SELCHANGED;

				tv.itemNew.hItem = hNewItem;
				tv.itemNew.state = GetItemState( m_hitemDrag, 0xffffffff );
				tv.itemNew.lParam = GetItemData( m_hitemDrag );
				tv.itemNew.mask = TVIF_HANDLE|TVIF_STATE|TVIF_PARAM;

				tv.action = TVC_DRAG_END /*TVC_UNKNOWN added by Brian */ ;

				pWnd->SendMessage( WM_NOTIFY, tv.hdr.idFrom, (LPARAM)&tv );
			}
			DeleteItem(m_hitemDrag); // Moved, JH 25.3.2000 
			
		}
		else
			MessageBeep(0);

		ReleaseCapture();
		m_bDragging = FALSE;
		SelectDropTarget(NULL);
	}
	
	CTreeCtrlEx::OnLButtonUp(nFlags, point);
}

void CGroupTreeCtrl::OnMouseMove(UINT nFlags, CPoint point) 
{
	HTREEITEM           hitem;
	UINT                flags;

	if (m_bDragging)
	{
		ASSERT(m_pimagelist != NULL);
		m_pimagelist->DragMove(point);
		if ((hitem = HitTest(point, &flags)) != NULL)
		{
			m_pimagelist->DragLeave(this);
			SelectDropTarget(hitem);
			m_hitemDrop = hitem;
			m_pimagelist->DragEnter(this, point);
		}
	}
	
	CTreeCtrlEx::OnMouseMove(nFlags, point);
}

void CGroupTreeCtrl::OnLButtonDown(UINT nFlags, CPoint point) 
{
	// TODO: Add your message handler code here and/or call default
	ptLButtonDown.x=-1;
	CTreeCtrlEx::OnLButtonDown(nFlags, point);
}
