/*
*******************************************************************************
* Copyright (c) 1996-97 Digi International Inc., All Rights Reserved          *
*                                                                             *
* This  software  contains  proprietary  and  confidential   information   of *
* Digi International  Inc.   By  accepting  transfer  of this copy, Recipient *
* agrees to retain this software in  confidence,  to  prevent  disclosure  to *
* others,  and  to make no  use of this software other than that for which it *
* was delivered.  This is an unpublished copyright work  Digi   International *
* Inc.    Except   as   permitted   by  federal  law,  17 USC 117, copying is *
* strictly prohibited.                                                        *
*                                                                             *
* Digi  International  Inc.  CONFIDENTIAL  -   (Digi    International    Inc. *
* Confidential  when   combined   with   the   aggregated  modules  for  this *
* product) OBJECT CODE ONLY SOURCE MATERIALS                                  *
*                                                                             *
* (C) COPYRIGHT Digi International Inc. 1996-97                               *
*                                                                             *
* All Rights Reserved                                                         *
*                                                                             *
* US   Government   Users   Restricted   Rights   -   Use,   duplication   or *
* disclosure  restricted by GSA ADP Schedule Contract with Digi International *
* Inc.                                                                        *
*                                                                             *
*******************************************************************************

// PacketTreeView.cpp : implementation file
//

Revision History:

   $History: PacketTreeView.cpp $
 * 
 * *****************  Version 19  *****************
 * User: Mikez        Date: 7/11/97    Time: 5:02p
 * Branched in $/Components/Windows/NT/Sync/Build/Diag
 * 
 * *****************  Version 18  *****************
 * User: Rodgerb      Date: 1/27/97    Time: 1:18p
 * Updated in $/Components/Windows/NT/Sync/rev2diag
 * 1) documentation
 * 2) added some new params to Physical layer stats
*/

#include "stdafx.h"
#include "Diagnostic.h"

#include "DiagDoc.h"
#include "PacketTreeView.h"

#define WM_COMMANDHELP      0x0365  // lResult = TRUE/FALSE,

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

/////////////////////////////////////////////////////////////////////////////
// CPacketTreeView

IMPLEMENT_DYNCREATE(CPacketTreeView, CTreeView)

CPacketTreeView::CPacketTreeView()
{
	InTreeChange = FALSE;
	m_bActive = FALSE;
}

CPacketTreeView::~CPacketTreeView()
{
}


BEGIN_MESSAGE_MAP(CPacketTreeView, CTreeView)
	//{{AFX_MSG_MAP(CPacketTreeView)
	ON_NOTIFY_REFLECT(TVN_SELCHANGED, OnSelchanged)
	ON_NOTIFY_REFLECT(NM_RCLICK, OnRclick)
	//}}AFX_MSG_MAP
	ON_MESSAGE(WM_COMMANDHELP, OnCommandHelp)
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CPacketTreeView drawing

void CPacketTreeView::OnDraw(CDC*)
{
	CDocument* pDoc = GetDocument();
	// TODO: add draw code here
}

/////////////////////////////////////////////////////////////////////////////
// CPacketTreeView diagnostics

#ifdef _DEBUG
void CPacketTreeView::AssertValid() const
{
	CTreeView::AssertValid();
}

void CPacketTreeView::Dump(CDumpContext& dc) const
{
	CTreeView::Dump(dc);
}

CDiagDoc* CPacketTreeView::GetDocument() // non-debug version is inline
{
	ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CDiagDoc)));
	return (CDiagDoc*)m_pDocument;
}
#endif //_DEBUG

/////////////////////////////////////////////////////////////////////////////
// CPacketTreeView message handlers

LRESULT CPacketTreeView::OnCommandHelp(WPARAM wParam, LPARAM lParam)
{
	if (lParam == 0)
	{
		lParam = cvtidTreeView;
	}
	
	return GetParentFrame()->SendMessage(WM_COMMANDHELP, wParam, lParam);
}

BOOL FindAndSelect(CTreeCtrl& tree, HTREEITEM item, LPVOID data)
{
	CString ItemText = tree.GetItemText(item);

	if (ItemText == (LPCTSTR)data)
	{
		tree.SelectItem(item);
		tree.EnsureVisible(item);
		return FALSE;
	}

	return TRUE;
}

void CPacketTreeView::OnUpdate(CView *pSender, LPARAM lHint, CObject* pHint) 
{
	// TODO: Add your specialized code here and/or call the base class
	BOOL SameParentFrame =	pSender == NULL ||
													pSender->GetParentFrame() == GetParentFrame();

// OnUpdate message is on lo byes
	lHint = LOBYTE(lHint);

	if (SameParentFrame)
		if (lHint & uavTreeTreeSelChange)
			TraverseTree(FindAndSelect, pHint);
		else if (lHint & uavFrameListRepSelChange)
		{
			BOOL bRedrawWindow = GetTreeCtrl().GetCount() > 0;

			InTreeChange = TRUE;

			GetTreeCtrl().DeleteAllItems();

			InTreeChange = FALSE;

			if (bRedrawWindow)
				RedrawWindow();
		}
		else if (lHint & uavFrameListSelChange)
		{
			DWORD nFrameNum = (DWORD)pHint;

			CTraceData *pTD = GetDocument()->GetTraceData();
			CFrame *pFrame = nFrameNum != -1
												? (CFrame *)pTD->GetTempFrame(nFrameNum)
												: NULL;

			InTreeChange = TRUE;

			SaveTreeState();
			GetTreeCtrl().DeleteAllItems();

			InTreeChange = FALSE;

			if (pFrame != NULL)
			{
				pFrame->DisplayTreeData(GetTreeCtrl(),	
																pTD, 
																nFrameNum == 0
																	? NULL
																	: pTD->GetNewFrame(nFrameNum - 1));
				RestoreTreeState();
			}
		}
}

void CPacketTreeView::OnSelchanged(NMHDR* pNMHDR, LRESULT* pResult) 
{
	NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR;
	// TODO: Add your control notification handler code here
	*pResult = 0;

	if (InTreeChange)
		return;

	InTreeChange = TRUE;

	GetDocument()->UpdateAllViews(this,
																uavFrameTreeSelChange,
																(CObject *)pNMTreeView->itemNew.lParam);

	CString text = GetTreeCtrl().GetItemText(pNMTreeView->itemNew.hItem);

	GetDocument()->UpdateAllViews(this,
																uavTreeTreeSelChange,
																(CObject *)(LPCTSTR)text);
	
	InTreeChange = FALSE;
}

void CPacketTreeView::TraverseTree(PItemFunc pFunc, LPVOID userData)
{
	CTreeCtrl& DataTree = GetTreeCtrl();

	HTREEITEM hItem = DataTree.GetRootItem();

	while (hItem != NULL)
	{
		if (!(*pFunc)(DataTree, hItem, userData))
			break;

		HTREEITEM hSave = hItem;
		hItem = DataTree.GetNextItem(hItem, TVGN_CHILD);

		if (hItem == NULL)
			hItem = DataTree.GetNextItem(hSave, TVGN_NEXT);

		if (hItem == NULL)
		{
			HTREEITEM hParentItem = hSave;

			do
			{
				hParentItem = DataTree.GetNextItem(hParentItem, TVGN_PARENT);
				hItem = DataTree.GetNextItem(hParentItem, TVGN_NEXT);
			}
			while (hParentItem != NULL && hItem == NULL);
		}
	}
}

BOOL CPacketTreeView::SaveStateFunc(CTreeCtrl& DataTree,
																		HTREEITEM hItem,
																		LPVOID userData)
{
	CPacketTreeView *THIS = (CPacketTreeView *)userData;

	CString ItemText = DataTree.GetItemText(hItem);

	int ColonIndex = ItemText.Find(':');

// strip off part past colon, the part past colon is very
// likely to be different every packet
	if (ColonIndex > -1)
		ItemText = ItemText.Left(ColonIndex);

	THIS->m_StateMap.SetAt(	ItemText,
													DataTree.GetItemState(hItem,
																								TVIS_EXPANDED | TVIS_SELECTED));

	return TRUE;
}

BOOL CPacketTreeView::RestoreStateFunc(	CTreeCtrl& DataTree,
																				HTREEITEM hItem,
																				LPVOID userData)
{
	CPacketTreeView *THIS = (CPacketTreeView *)userData;

	CString ItemText = DataTree.GetItemText(hItem);

	int ColonIndex = ItemText.Find(':');

	if (ColonIndex > -1)
		ItemText = ItemText.Left(ColonIndex);
	
	UINT ItemState;

	if (THIS->m_StateMap.Lookup(ItemText, ItemState))
	{
		if (ItemState & TVIS_EXPANDED)
			DataTree.Expand(hItem, TVE_EXPAND);

		if (ItemState & TVIS_SELECTED)
			THIS->m_SelItem = hItem;
	}

	return TRUE;
}

void CPacketTreeView::SaveTreeState()
{
	TraverseTree(&SaveStateFunc, this);
}

void CPacketTreeView::RestoreTreeState()
{
	CTreeCtrl& DataTree = GetTreeCtrl();

	m_SelItem = NULL;
	TraverseTree(&RestoreStateFunc,this);

	if (m_bActive)
		DataTree.SetFocus();
	
	if (m_SelItem == NULL)
		m_SelItem = DataTree.GetRootItem();			

	DataTree.SelectItem(m_SelItem);		
}

BOOL CPacketTreeView::PreCreateWindow(CREATESTRUCT& cs) 
{
	// TODO: Add your specialized code here and/or call the base class
	
	cs.style |= TVS_LINESATROOT | TVS_HASBUTTONS | TVS_HASLINES |
							TVS_DISABLEDRAGDROP | TVS_SHOWSELALWAYS | WS_BORDER;

	return CTreeView::PreCreateWindow(cs);
}

void CPacketTreeView::OnActivateView(	BOOL bActivate,
																			CView *pActivateView,
																			CView *pDeactiveView) 
{
	// TODO: Add your specialized code here and/or call the base class
	CTreeView::OnActivateView(bActivate, pActivateView, pDeactiveView);

	m_bActive = bActivate;

	if (bActivate)
		GetParentFrame()->OnUpdateFrameTitle(TRUE);
}

void CPacketTreeView::OnRclick(NMHDR*, LRESULT* pResult) 
{
	// TODO: Add your control notification handler code here
	POINT pt;

	GetCursorPos(&pt);

	GetParentFrame()->SendMessage(WM_RBUTTONUP,
																MK_RBUTTON,
																(pt.y << 16) + pt.x);

	*pResult = 1;
}
