// TreeListHeaderCtrl.cpp : implementation file
//

#include "stdafx.h"
#include "apl_gui.h"

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

/////////////////////////////////////////////////////////////////////////////
// CaplTreeListHeaderCtrl

CaplTreeListHeaderCtrl::CaplTreeListHeaderCtrl()
{
	//initialise variables
	m_pImageList = NULL;
	m_RTL = FALSE;

	m_ToolTip =&m_MyToolTip;

}

CaplTreeListHeaderCtrl::~CaplTreeListHeaderCtrl()
{
	m_pFont.DeleteObject();
}


BEGIN_MESSAGE_MAP(CaplTreeListHeaderCtrl, CHeaderCtrl)
	//{{AFX_MSG_MAP(CaplTreeListHeaderCtrl)
	ON_WM_CREATE()
	ON_WM_MOUSEMOVE()
	ON_WM_PAINT()		
	ON_WM_LBUTTONDOWN()
	ON_WM_RBUTTONDOWN()
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CaplTreeListHeaderCtrl message handlers
//**********************************************************************
void CaplTreeListHeaderCtrl::DrawItem( LPDRAWITEMSTRUCT lpDrawItemStruct )
{
	CDC dc;
	dc.Attach( lpDrawItemStruct->hDC );	

	// Save DC
//	int nSavedDC = dc.SaveDC();

	// Get the column rect	
	CRect rcLabel( lpDrawItemStruct->rcItem );
	rcLabel.DeflateRect(4,1);

	// Get the column text and format
	TCHAR buf[256];
	HD_ITEM hditem;
	
	hditem.mask = HDI_TEXT | HDI_FORMAT;
	hditem.pszText = buf;
	hditem.cchTextMax = 255;

	GetItem( lpDrawItemStruct->itemID, &hditem );

	//CFont *pOldFont=dc.SelectObject(CFont::FromHandle((HFONT)GetStockObject(ANSI_VAR_FONT)));
	CFont *pOldFont=dc.SelectObject(&m_pFont);

	// Determine format for drawing column label
	UINT uFormat = DT_SINGLELINE | DT_NOPREFIX | DT_NOCLIP 	| DT_VCENTER | DT_END_ELLIPSIS ;

	if( hditem.fmt & HDF_CENTER)	 uFormat |= DT_CENTER;
	else if( hditem.fmt & HDF_RIGHT) uFormat |= DT_RIGHT;
	else	uFormat |= DT_LEFT;

	if( lpDrawItemStruct->itemState == ODS_SELECTED )
	{
		rcLabel.left++;
		rcLabel.top += 2;
		rcLabel.right++;
	}
	
	int imageIndex;
	int img_cx=0, img_cy=0;

	if (m_pImageList &&  m_mapImageIndex.Lookup( lpDrawItemStruct->itemID, imageIndex ) )
	{
		if( imageIndex != -1 )
		{
			IMAGEINFO imageinfo;
			if( m_pImageList->GetImageInfo( imageIndex, &imageinfo ) )
			{
				img_cx=	imageinfo.rcImage.right - imageinfo.rcImage.left;
				img_cy=	imageinfo.rcImage.bottom - imageinfo.rcImage.top;
				
				CPoint point;
				point.y=rcLabel.top +((rcLabel.bottom-rcLabel.top)-img_cy)/2;

				if(uFormat & DT_RIGHT) // draw to the left of the label
				{
					point.x=rcLabel.left;
				}
				else // draw to the right
					point.x=rcLabel.right - img_cx-3;

				m_pImageList->Draw(&dc, imageIndex, point, ILD_TRANSPARENT );
			}
		}
	}

	if(uFormat & DT_RIGHT) rcLabel.left += img_cx + 2;
	else rcLabel.right -= img_cx;

	if( rcLabel.left < rcLabel.right )
			dc.DrawText(buf,-1,rcLabel, uFormat);

	dc.SelectObject(pOldFont);
	// Restore dc
//	dc.RestoreDC( nSavedDC );

	// Detach the dc before returning
	dc.Detach();
}

//**********************************************************************
CImageList* CaplTreeListHeaderCtrl::SetImageList( CImageList* pImageList )
{
	CImageList *pPrevList = m_pImageList;
	m_pImageList = NULL;
	if(pImageList && pImageList->m_hImageList)
		m_pImageList = pImageList;
	return pPrevList;
}

//**********************************************************************
int CaplTreeListHeaderCtrl::GetItemImage( int nItem )
{
	int imageIndex;
	if( m_mapImageIndex.Lookup( nItem, imageIndex ) )
		return imageIndex;
	return -1;
}

//**********************************************************************
void CaplTreeListHeaderCtrl::SetItemImage( int nItem, int nImage )
{
	// Save the image index
	m_mapImageIndex[nItem] = nImage;

	// Change the item to ownder drawn
	HD_ITEM hditem;

	hditem.mask = HDI_FORMAT;
	GetItem( nItem, &hditem );
	hditem.fmt |= HDF_OWNERDRAW;
	SetItem( nItem, &hditem );

	// Invalidate header control so that it gets redrawn
	Invalidate();
}

//**********************************************************************
void CaplTreeListHeaderCtrl::Autofit(int nOverrideItemData /*= -1*/, int nOverrideWidth /*= 0*/)
{
	int nItemCount = GetItemCount();
	int nTotalWidthOfColumns = 0;
	int nItem;
	HD_ITEM hi;
	CRect rClient;

	if (!m_bAutofit)
		return;

	SetRedraw(FALSE);

	GetParent()->GetClientRect(&rClient);
	if (-1 != nOverrideItemData)
		rClient.right -= nOverrideWidth;

	// Get total width of all columns
	for (nItem = 0; nItem < nItemCount; nItem++)
	{
		if (nItem == nOverrideItemData)	// Don't mess with the item being resized by the user
			continue;

		hi.mask = HDI_WIDTH;
		GetItem(nItem, &hi);

		nTotalWidthOfColumns += hi.cxy;
	}

	if (nTotalWidthOfColumns != rClient.Width())
	{
		if ( nTotalWidthOfColumns == 0 ) nTotalWidthOfColumns = 1;

		/// при плавном изменьшении размеров может получиться так что одна колонка(несколько) становится во много раз больше других
		/// корректируем размеры колонок которые меньше minColWidth, остальные растягиваем пропорционально

		// M:18427 // желаемый минимальный размер колонки
		const int minColWidth = 40; 

		int realItemCount = nOverrideItemData == -1 ? nItemCount : nItemCount - 1;

		int nMinCol = 0;
		int propTotalWidth = 0; /// размер столбцов которые будут растягиваться пропорционально

		// минимальный размер всех столбцов можно сделать minColWidth
		if ( false )//minColWidth * realItemCount < rClient.Width() )
		{
			// считаем сколько колонок будет меньше minColWidth
			for (nItem = 0; nItem < nItemCount; nItem++)
			{
				if (nItem == nOverrideItemData)	// Skip the overrride column if there is one!
					continue;

				hi.mask = HDI_WIDTH;
				GetItem(nItem, &hi);
				
				if ( hi.cxy == 0 ) hi.cxy = 1;
				int newWidth = (hi.cxy * rClient.Width()) / nTotalWidthOfColumns;

				if ( newWidth < minColWidth )
				{
					nMinCol++;
				}
				else
				{
					propTotalWidth += hi.cxy;
				}
			}

			int propWidth = rClient.Width() - nMinCol * minColWidth;

			if ( propTotalWidth == 0 ) propTotalWidth = 1;

			// растягиваем в соотв с новым размером или уст мин размер
			for (nItem = 0; nItem < nItemCount; nItem++)
			{
				if (nItem == nOverrideItemData)	// Skip the override column if there is one!
					continue;

				hi.mask = HDI_WIDTH;
				GetItem(nItem, &hi);

				hi.mask = HDI_WIDTH;

				int newWidth = (hi.cxy * rClient.Width() ) / nTotalWidthOfColumns;
				
				if ( newWidth < minColWidth ) 
				{
					hi.cxy = minColWidth;
				}
				else
				{
					hi.cxy = (hi.cxy * propWidth ) / propTotalWidth;
				}

				SetItem(nItem, &hi);
			}


		}
		else
		{
			// тут с минимальным размером как получится( было раньше )

			// Shrink/expand all columns proportionally based on their current size
			for (nItem = 0; nItem < nItemCount; nItem++)
			{
				if (nItem == nOverrideItemData)	// Skip the overrride column if there is one!
					continue;

				hi.mask = HDI_WIDTH;
				GetItem(nItem, &hi);

				hi.mask = HDI_WIDTH;
				if(nTotalWidthOfColumns==0) nTotalWidthOfColumns=1;
				if(hi.cxy == 0) hi.cxy = minColWidth;		// M:18427
				hi.cxy = (hi.cxy * rClient.Width()) / nTotalWidthOfColumns;
				if(hi.cxy == 0) hi.cxy = minColWidth;		// M:18427

				SetItem(nItem, &hi);
			}
		}
	}

	SetRedraw(TRUE);
	Invalidate();
}

//**********************************************************************
int CaplTreeListHeaderCtrl::OnCreate(LPCREATESTRUCT lpCreateStruct) 
{
	if (CHeaderCtrl::OnCreate(lpCreateStruct) == -1)
		return -1;
	
	// TODO: Add your specialized creation code here
	return 0;
}

//**********************************************************************
void CaplTreeListHeaderCtrl::OnMouseMove(UINT nFlags, CPoint point) 
{
	// TODO: Add your message handler code here and/or call default
	m_ToolTip->Hide();

	CHeaderCtrl::OnMouseMove(nFlags, point);

	int i, idx=-1, x=point.x, y=point.y;
	RECT r;

	if(y>2)
	{
		for(i=0;i<GetItemCount();i++)
		{
			
			GetItemRect(i,&r);
			if(x>(r.left+4) && x<(r.right-4))
			{
				if(y<(r.bottom-3)) idx=i;
				break;
			}
		}
	}
	if(idx>=0)
	{
		HDITEM hditem;
		hditem.mask=HDI_TEXT;
		TCHAR buf[256];
		hditem.pszText = buf;
		hditem.cchTextMax = 255;

		GetItem(idx,&hditem);
		
		POINT p;
		p.x=point.x+10;
		p.y=point.y+10;
		ClientToScreen(&p);
		m_ToolTip->Show(p.x,p.y, buf);  
	}
	TRACKMOUSEEVENT		csTME;
	csTME.cbSize = sizeof(csTME);
	csTME.dwFlags = TME_LEAVE;
	csTME.hwndTrack = m_hWnd;
	::_TrackMouseEvent(&csTME);
}



void CaplTreeListHeaderCtrl::CalcWindowRect(LPRECT lpClientRect, UINT nAdjustType) 
{
	m_pFont.DeleteObject();
	
	CHeaderCtrl::CalcWindowRect(lpClientRect, nAdjustType);
}

void CaplTreeListHeaderCtrl::OnLButtonDown(UINT nFlags, CPoint point) 
{
	// TODO: Add your message handler code here and/or call default
	m_ToolTip->Hide();
	CHeaderCtrl::OnLButtonDown(nFlags, point);
}

void CaplTreeListHeaderCtrl::OnRButtonDown(UINT nFlags, CPoint point) 
{
	// TODO: Add your message handler code here and/or call default
	m_ToolTip->Hide();
	CHeaderCtrl::OnRButtonDown(nFlags, point);
}

BOOL CaplTreeListHeaderCtrl::PreTranslateMessage(MSG* pMsg) 
{
	if(pMsg!=0&&m_ToolTip!=0)
	{
		if(m_ToolTip->IsNeedHideOnMessage(pMsg->message))
			m_ToolTip->Hide();
	}
	return CHeaderCtrl::PreTranslateMessage(pMsg);
}
