/*=========================================================================
* 
* CPAdList.cpp :  Lists - Implementation file
* 
*
* Version			1.0
* Creation date		
* Revision date
*
* Shaitan
*=======================================================================*/
#include "stdafx.h"
#ifdef ACTIVE_EDITOR
#include "acp_base.h"
#include "itf/CPAdTree.hpp"
#include "itf/CPAdList.hpp"
#include "ITF/CPABaseO.hpp"
#include "ITF/CPAEditB.hpp"
#include "itf/CPAProj.hpp"
#include "IncTUT.h"

#define C_uiCustomEntriesStart 10

//#################################################################################
// CPA_TreeItem
//#################################################################################

/*----------------------------------------
	Constructor 
----------------------------------------*/
CPA_TreeItem::CPA_TreeItem (CPA_BaseObject *pObject)
{
	// init parameters
	m_pObject = pObject;
	m_pInfo = NULL;
	m_iIcon = 0;
	m_iState = 0;
}

/*----------------------------------------
	Destructor 
----------------------------------------*/
CPA_TreeItem::~CPA_TreeItem (void)
{

}


//#################################################################################
// Hierarchy Tree Control
//#################################################################################
BEGIN_MESSAGE_MAP(CPA_HierarchyTree, CTreeCtrl)
	ON_WM_RBUTTONDOWN()
	ON_WM_LBUTTONDBLCLK()
	ON_WM_LBUTTONUP()
	ON_WM_MOUSEMOVE()
	ON_WM_KEYDOWN()
	ON_WM_KEYUP()
END_MESSAGE_MAP()

/*----------------------------------------
	Constructor
----------------------------------------*/
CPA_HierarchyTree::CPA_HierarchyTree (void)
{
	m_pParentDialog = NULL;
	m_hDraggedItem = NULL;
	m_hTarget = NULL;
	m_pRoot = NULL;
	// init default icons
	m_stDefaultImageList.Create(16, 16, FALSE, 0, 1);
	m_stDefaultImageList.Add(M_GetMainApp()->LoadIcon(CPA_IDI_EDIT_DEFAULT));
}

CPA_HierarchyTree::~CPA_HierarchyTree (void)
{

}


/*----------------------------------------
	Set functions
----------------------------------------*/
void CPA_HierarchyTree::SetTreeRoot (CPA_BaseObject *pRoot)
{
	m_pRoot = pRoot;
	fn_vFillHierarchyTree(pRoot, TVI_ROOT);
}

/*----------------------------------------
	Set icons
----------------------------------------*/
void CPA_HierarchyTree::SetIconList (CImageList *pIconList, BOOL bUpdate)
{
	// user icon list
	if (pIconList)
	{
		SetImageList(pIconList, TVSIL_NORMAL);
		m_pIconList = pIconList;
	}
	// else default one
	else
	{
		SetImageList(&m_stDefaultImageList, TVSIL_NORMAL);
		m_pIconList = &m_stDefaultImageList;
	}
	
	if (bUpdate)
		fn_vFillHierarchyTree(m_pRoot, TVI_ROOT);
}

/*----------------------------------------
	Set icons
----------------------------------------*/
void CPA_HierarchyTree::SetStateList (CImageList *pStateList, BOOL bUpdate)
{
	// user icon list
	if (pStateList)
		SetImageList(pStateList, TVSIL_STATE);
	m_pStateList = pStateList;
	
	if (bUpdate)
		fn_vFillHierarchyTree(m_pRoot, TVI_ROOT);
}

/*----------------------------------------
	Init Hierarchy
----------------------------------------*/
void CPA_HierarchyTree::fn_vDeleteHierarchyTree (HTREEITEM hTreeParent)
{
	CPA_TreeItem *pTreeItem;
	HTREEITEM	 hChild;

	if (!m_pRoot)
		return;
	
	if (hTreeParent)
	{
		// delete item data
		pTreeItem = (CPA_TreeItem *) GetItemData(hTreeParent);
		if (pTreeItem)
			delete pTreeItem;
	}
	
	// test all childs
	hChild = (hTreeParent) ? GetChildItem(hTreeParent) : GetRootItem();
	while (hChild)
	{
		fn_vDeleteHierarchyTree(hChild);
		hChild = GetNextSiblingItem(hChild);
	}

	// end => delete items
	if (hTreeParent == NULL)
		DeleteAllItems();
}

/*----------------------------------------
	Init Hierarchy
----------------------------------------*/
void CPA_HierarchyTree::fn_vFillHierarchyTree (CPA_BaseObject *pEdParent, HTREEITEM hTreeParent)
{
	CPA_BaseObject	*pEdChild;
	CPA_TreeItem	*pTreeItem;
	HTREEITEM		hTreeChild;
	void			*pInfo;
	int				iNumIcon, iNumState;

	if (!pEdParent)
		return;
	
	// first child
	pEdChild = GetCorrespondingChild(pEdParent, NULL);
	
	while (pEdChild)
	{
		// create tree item
		pTreeItem = new CPA_TreeItem(pEdChild);
		// get icon
		iNumIcon = GetCorrespondingIcon(pEdChild);
		pTreeItem->SetIcon(iNumIcon);
		// set info
		pInfo = GetCorrespondingInfo(pEdChild, pEdParent);
		pTreeItem->SetInfo(pInfo);
		// get state
		if (m_pStateList)
		{
			// get icon
			iNumState = GetCorrespondingState(pEdChild);
			pTreeItem->SetState(iNumState);
		}

		// create item
		hTreeChild = InsertItem(pEdChild->GetNameToDraw(), iNumIcon, iNumIcon, hTreeParent, TVI_LAST);
		// set data
		SetItemData(hTreeChild, (DWORD) pTreeItem);
		// if necessary, set state icon
		if (m_pStateList)
			SetItem(hTreeChild, TVIF_STATE, pEdChild->GetNameToDraw(), iNumState, iNumState, 
					TVIS_STATEIMAGEMASK,  INDEXTOSTATEIMAGEMASK(iNumState), (DWORD)pTreeItem);			

		// next level
		fn_vFillHierarchyTree(pEdChild, hTreeChild);

		// next child
		pEdChild = GetCorrespondingChild(pEdParent, pEdChild);
	}
}


/*----------------------------------------
	Drag&Drop End
----------------------------------------*/
void CPA_HierarchyTree::OnLButtonUp (UINT nFlags, CPoint point)
{
	if ((!m_hDraggedItem)||(!m_hTarget))
	{
		CTreeCtrl::OnLButtonUp (nFlags, point);
		return;
	}

	// if target is valid, complete drag&drop
	m_pParentDialog->fn_vOnDragDropEndHierarchy();
	SetItemState(m_hTarget, 0, TVIS_DROPHILITED);
	m_hDraggedItem = NULL;
	m_hTarget = NULL;
}

/*----------------------------------------
	Drag&Drop
----------------------------------------*/
void CPA_HierarchyTree::OnMouseMove (UINT nFlags, CPoint point)
{
	HTREEITEM		hTarget;
	UINT			pFlag;

	if (!m_hDraggedItem)
	{
		CTreeCtrl::OnMouseMove (nFlags, point);
		return;
	}
	hTarget = HitTest(point, &pFlag);
	if (hTarget != m_hTarget)
	{
		if (m_hTarget)
			SetItemState(m_hTarget, 0, TVIS_DROPHILITED);
		if (m_pParentDialog->fn_bAcceptAsDragDropTarget(hTarget))
			m_hTarget = hTarget;
		else
			m_hTarget = NULL;
		if (m_hTarget)
			SetItemState(m_hTarget, TVIS_DROPHILITED, TVIS_DROPHILITED);
	}
}


/*----------------------------------------
	DblClk
----------------------------------------*/
void CPA_HierarchyTree::OnLButtonDblClk(UINT nFlags, CPoint point) 
{
	if (m_pParentDialog)
		m_pParentDialog->fn_vOnDblClkHierarchyTree();

	else
		CTreeCtrl::OnLButtonDblClk(nFlags, point);
}

/*----------------------------------------
	Key Down
----------------------------------------*/
void CPA_HierarchyTree::OnKeyDown (UINT nChar, UINT nRepCnt, UINT nFlags)
{
	if (!m_pParentDialog || !m_pParentDialog->fn_bOnKeyDownInControl(nChar, nRepCnt, nFlags))
		CTreeCtrl::OnKeyDown(nChar, nRepCnt, nFlags);
}

/*----------------------------------------
	Key Up
----------------------------------------*/
void CPA_HierarchyTree::OnKeyUp (UINT nChar, UINT nRepCnt, UINT nFlags)
{
	if (!m_pParentDialog ||	!m_pParentDialog->fn_bOnKeyUpInControl(nChar, nRepCnt, nFlags))
		CTreeCtrl::OnKeyUp(nChar, nRepCnt, nFlags);
}

/*----------------------------------------
	Popup Menu
----------------------------------------*/
void CPA_HierarchyTree::OnRButtonDown(UINT nFlags, CPoint point) 
{
	BOOL bEntry = FALSE;
	
	ClientToScreen( &point );
	// create popup menu	
	CMenu oMenu;
	oMenu.CreatePopupMenu();

	// Custom Entries
	if (m_pParentDialog)
		bEntry = m_pOwnerEditor->fn_bAddEntriesToTreePopup(m_pParentDialog, m_pParentDialog->GetCurrentType(), &oMenu, C_uiCustomEntriesStart);
	else
		bEntry = m_pOwnerEditor->fn_bAddEntriesToTreePopup(this, m_pRoot, &oMenu, C_uiCustomEntriesStart);
	
	// display & track popup menu
	if (bEntry)
    {
        TUT_M_vGetTutDll    ();
        TUT_M_vRegisterMenu (this -> m_hWnd , oMenu . m_hMenu , point . x , point . y);
		oMenu.TrackPopupMenu( TPM_LEFTALIGN | TPM_RIGHTBUTTON, point.x, point.y, this);
    }
	// destroy menus
	oMenu.DestroyMenu();
}

/*----------------------------------------
	Answer to Popup
----------------------------------------*/
BOOL CPA_HierarchyTree::OnCommand( WPARAM wParam, LPARAM lParam )
{
	// command from a menu ?
	if (HIWORD(wParam) == 0) 
	{
		// custom entries
		if (LOWORD(wParam) >= C_uiCustomEntriesStart) 
		{
			if (m_pParentDialog)
				m_pOwnerEditor->fn_vOnCommandInTreePopup(m_pParentDialog, m_pParentDialog->GetCurrentType(), LOWORD(wParam) - C_uiCustomEntriesStart);
			else
				m_pOwnerEditor->fn_vOnCommandInTreePopup(this, m_pRoot, LOWORD(wParam) - C_uiCustomEntriesStart);
		}
	}
	return CTreeCtrl::OnCommand(wParam, lParam);
}


/*----------------------------------------
	Get Item
----------------------------------------*/
HTREEITEM CPA_HierarchyTree::GetCorrespondingItem (CPA_BaseObject *pObject, CPA_BaseObject *pParent, HTREEITEM hElem)
{
	HTREEITEM		hChild, hParent, hResult;
	CPA_TreeItem	*pData;

	// test hElem name
	if (hElem)
	{
		// get item data
		pData = (CPA_TreeItem *) GetItemData(hElem);
		// check item data
		if ((pData)&&(pData->GetObject() == pObject))
		{
			// no parent specified => OK
			if (!pParent)
				return hElem;
			// must test parent
			else
			{
				// get parent item
				hParent = GetParentItem(hElem);
				if (hParent)
				{
					// test parent data
					pData = (CPA_TreeItem *) GetItemData(hParent);
					if ((pData)&&(pData->GetObject() == pParent))
						return hElem;
				}
			}
		}
	}
	
	// test all childs
	hChild = (hElem) ? GetChildItem(hElem) : GetRootItem();
	while (hChild)
	{
		hResult = GetCorrespondingItem(pObject, pParent, hChild);
		if (hResult)
			return hResult;
		hChild = GetNextSiblingItem(hChild);
	}
	
	return NULL;
}

/*----------------------------------------
	Get Icon
----------------------------------------*/
int CPA_HierarchyTree::GetCorrespondingIcon	(CPA_BaseObject *pObject)
{
	// get icon
	if (m_pParentDialog)
		return m_pOwnerEditor->GetIconForTreeItem (m_pParentDialog, m_pParentDialog->GetCurrentType(), pObject);
	else
		return m_pOwnerEditor->GetIconForTreeItem (this, m_pRoot, pObject);

}

/*----------------------------------------
	Get State
----------------------------------------*/
int CPA_HierarchyTree::GetCorrespondingState (CPA_BaseObject *pObject)
{
	// get state
	if (m_pParentDialog)
		return m_pOwnerEditor->GetStateForTreeItem (m_pParentDialog, m_pParentDialog->GetCurrentType(), pObject);
	else
		return m_pOwnerEditor->GetStateForTreeItem (this, m_pRoot, pObject);
}

/*----------------------------------------
	Get State
----------------------------------------*/
CPA_BaseObject * CPA_HierarchyTree::GetCorrespondingChild (CPA_BaseObject *pParent, CPA_BaseObject *pBrother)
{
	if (m_pParentDialog)
		return m_pOwnerEditor->GetTreeNodeNextChild (m_pParentDialog, m_pParentDialog->GetCurrentType(), pParent, pBrother);
	else
		return m_pOwnerEditor->GetTreeNodeNextChild (this, m_pRoot, pParent, pBrother);
}


/*----------------------------------------
	Get Info
----------------------------------------*/
void * CPA_HierarchyTree::GetCorrespondingInfo (CPA_BaseObject *pObject, CPA_BaseObject *pParent)
{
	if (m_pParentDialog)
		return m_pOwnerEditor->GetInfoForTreeItem (m_pParentDialog, m_pParentDialog->GetCurrentType(), pObject, pParent);
	else
		return m_pOwnerEditor->GetInfoForTreeItem (this, m_pRoot, pObject, pParent);
}

/*----------------------------------------
	Get Item Info
----------------------------------------*/
void * CPA_HierarchyTree::GetItemInfo (CPA_BaseObject *pObject, CPA_BaseObject *pParent)
{
	CPA_TreeItem	*pItemData;
	HTREEITEM		hItem;

	// get item
	hItem = GetCorrespondingItem (pObject, pParent, NULL);
	if (!hItem)
		return NULL;
	//get item data
	pItemData = (CPA_TreeItem *) GetItemData(hItem);
	if (!pItemData)
		return NULL;
	// get item info
	return pItemData->GetInfo();
}

/*----------------------------------------
	Set Item Info
----------------------------------------*/
void CPA_HierarchyTree::SetItemInfo (CPA_BaseObject *pObject, CPA_BaseObject *pParent, void *pInfo)
{
	CPA_TreeItem	*pItemData;
	HTREEITEM		hItem;

	// get item
	hItem = GetCorrespondingItem (pObject, pParent, NULL);
	if (!hItem)
		return;
	//get item data
	pItemData = (CPA_TreeItem *) GetItemData(hItem);
	if (!pItemData)
		return;
	// set item info
	pItemData->SetInfo(pInfo);
}

/*----------------------------------------
	Get Item Icon
----------------------------------------*/
int CPA_HierarchyTree::GetItemIcon (CPA_BaseObject *pObject, CPA_BaseObject *pParent)
{
	CPA_TreeItem	*pItemData;
	HTREEITEM		hItem;

	// get item
	hItem = GetCorrespondingItem (pObject, pParent, NULL);
	if (!hItem)
		return -1;
	//get item data
	pItemData = (CPA_TreeItem *) GetItemData(hItem);
	if (!pItemData)
		return -1;
	// get item icon
	return pItemData->GetIcon();
}

/*----------------------------------------
	Set Item Icon
----------------------------------------*/
void CPA_HierarchyTree::SetItemIcon (CPA_BaseObject *pObject, CPA_BaseObject *pParent, int iIcon)
{
	CPA_TreeItem	*pItemData;
	HTREEITEM		hItem;

	// get item
	hItem = GetCorrespondingItem (pObject, pParent, NULL);
	if (!hItem)
		return;
	//get item data
	pItemData = (CPA_TreeItem *) GetItemData(hItem);
	if (!pItemData)
		return;
	// set item icon
	pItemData->SetIcon(iIcon);
	SetItemImage(hItem, iIcon, iIcon);
}

/*----------------------------------------
	Get Item State
----------------------------------------*/
int CPA_HierarchyTree::GetItemStateI (CPA_BaseObject *pObject, CPA_BaseObject *pParent)
{
	CPA_TreeItem	*pItemData;
	HTREEITEM		hItem;

	// no image list => no icon index
	if (!m_pStateList)
		return -1;
	
	// get item
	hItem = GetCorrespondingItem (pObject, pParent, NULL);
	if (!hItem)
		return -1;
	//get item data
	pItemData = (CPA_TreeItem *) GetItemData(hItem);
	if (!pItemData)
		return -1;
	// get item state
	return pItemData->GetState();
}

/*----------------------------------------
	Set Item State
----------------------------------------*/
void CPA_HierarchyTree::SetItemStateI (CPA_BaseObject *pObject, CPA_BaseObject *pParent, int iState)
{
	CPA_TreeItem	*pItemData;
	HTREEITEM		hItem;

	// no image list => no icon index
	if (!m_pStateList)
		return;

	// get item
	hItem = GetCorrespondingItem (pObject, pParent, NULL);
	if (!hItem)
		return;
	//get item data
	pItemData = (CPA_TreeItem *) GetItemData(hItem);
	if (!pItemData)
		return;
	// set item state
	pItemData->SetState(iState);
	SetItem(hItem, TVIF_STATE, pItemData->GetObject()->GetNameToDraw(), iState, iState, 
			TVIS_STATEIMAGEMASK,  INDEXTOSTATEIMAGEMASK(iState), (DWORD)pItemData);			
}


#endif //ACTIVE_EDITOR




