// SortableHeaderCtrl.cpp : implementation file
//

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

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

/////////////////////////////////////////////////////////////////////////////
// CSortableHeaderCtrl

CSortableHeaderCtrl::CSortableHeaderCtrl()
{
	m_bSortAsc = FALSE;
	m_nSortCol = -1;
	m_iLastColumn = -1;
	m_bUseMultiLine=false;

	CaplSetResourceHandle setres(module_inst);
	
//	m_bmpArrowUp.LoadBitmap( IDB_ARROWUP );
//	m_bmpArrowDown.LoadBitmap( IDB_ARROWDOWN );

	COLORMAP  cm;
	cm.from=RGB(192,192,192);
	cm.to=GetSysColor(COLOR_BTNFACE);
	
	m_bmpArrowUp.LoadMappedBitmap(IDB_ARROWUP,0,&cm,1);
	m_bmpArrowDown.LoadMappedBitmap(IDB_ARROWDOWN,0,&cm,1);

	m_ToolTip =&m_MyToolTip;
}

CSortableHeaderCtrl::~CSortableHeaderCtrl()
{
	m_bmpArrowUp.DeleteObject();
	m_bmpArrowDown.DeleteObject();
}


BEGIN_MESSAGE_MAP(CSortableHeaderCtrl, CHeaderCtrl)
	//{{AFX_MSG_MAP(CSortableHeaderCtrl)
	ON_WM_MOUSEMOVE()
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CSortableHeaderCtrl message handlers
/////////////////////////////////////////////////////////////////////////////

int CSortableHeaderCtrl::SetSortImage( int nCol, BOOL bAsc )
{
    CBitmap *pTempBmp = NULL;
	if( bAsc )
		pTempBmp = &m_bmpArrowUp;
	else
		pTempBmp = &m_bmpArrowDown;
	
	HD_ITEM Item;	
	Item.mask = HDI_FORMAT;
	GetItem( nCol, &Item );
	Item.mask = HDI_BITMAP | HDI_FORMAT;	
	Item.fmt |= HDF_BITMAP;
	Item.hbm = (HBITMAP)pTempBmp->GetSafeHandle();
	SetItem( nCol, &Item );
	m_iLastColumn = nCol;
    return 1;
}

void CSortableHeaderCtrl::OnEndtrack(NMHDR* pNMHDR, LRESULT* pResult) 
{
	CMultiColumnSortListView *pView = (CMultiColumnSortListView *)GetParent();
	pView->SaveColumnWidths();
	*pResult = 0;
}

const int CSortableHeaderCtrl::GetLastColumn() const
{
	return m_iLastColumn;
}

void CSortableHeaderCtrl::RemoveSortImage( int iItem )
{
	if( iItem != -1 )
	{
		HD_ITEM hditem;	
		hditem.mask = HDI_FORMAT;
		GetItem( iItem, &hditem );
		hditem.mask = HDI_FORMAT;	
		hditem.fmt &= ~HDF_BITMAP;
		SetItem( iItem, &hditem );
	}
}

void CSortableHeaderCtrl::RemoveAllSortImages()
{
	int iCount = GetItemCount();
	for( int i = 0; i < iCount; i++ )
		RemoveSortImage( i );
}

void CSortableHeaderCtrl::OnMouseMove(UINT nFlags, CPoint point) 
{
	// TODO: Add your message handler code here and/or call default
	bool bNeedTestToolTip=true;
	if(m_ToolTip->IsShowed())
	{
		if(!m_TitledRect.PtInRect(point)) m_ToolTip->Hide();
		else 
			bNeedTestToolTip=false;
	}


	CHeaderCtrl::OnMouseMove(nFlags, point);

	if(!bNeedTestToolTip || (nFlags|MK_LBUTTON&MK_RBUTTON&MK_RBUTTON)) return;

	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);

		CString text=hditem.pszText;
		CDC *pDC = GetDC();
		CSize size = pDC->GetTextExtent(text);
		// если по этому столбцу была сортировка - учитываем ширину стрелочки
		int arrow_width = 0;
		if( m_iLastColumn == idx) arrow_width = 20; 

		if(size.cx > (r.right - r.left - m_ToolTip->m_text_x_paragr - arrow_width))
		{
			POINT p;
// 			p.x=point.x+10;
// 			p.y=point.y+10;
			p.x=r.left+1+arrow_width;
			p.y=r.top+1;

			ClientToScreen(&p);
			m_ToolTip->Show(p.x,p.y, buf);  
			// запоминаем предыдущий отултипленый
			m_TitledRect = r;
		}
		ReleaseDC(pDC);
	}


	TRACKMOUSEEVENT		csTME;
	csTME.cbSize = sizeof(csTME);
	csTME.dwFlags = TME_LEAVE;
	csTME.hwndTrack = m_hWnd;
	::_TrackMouseEvent(&csTME);
}

BOOL CSortableHeaderCtrl::PreTranslateMessage(MSG* pMsg) 
{
	// TODO: Add your specialized code here and/or call the base class
	if(pMsg!=0 && m_ToolTip!=0)
	{
		if(m_ToolTip->IsNeedHideOnMessage(pMsg->message))
			m_ToolTip->Hide();
	}				
	return CHeaderCtrl::PreTranslateMessage(pMsg);
}



void CSortableHeaderCtrl::SetAutoHigh(bool bUseMultiLine)
{
	int i;
	HDITEM hdItem;
	TCHAR  lpBuffer[256];

	hdItem.mask = HDI_TEXT|HDI_FORMAT;
	hdItem.pszText = lpBuffer;
	hdItem.cchTextMax = 256;


	if(m_HighFont.m_hObject!=0)
		m_HighFont.DeleteObject( );

	if(bUseMultiLine)
	{
		int max_lines=1;

		hdItem.mask = HDI_TEXT|HDI_FORMAT;

		for(i=0; i<GetItemCount(); i++)
		{
			GetItem(i,&hdItem);
			hdItem.fmt|= HDF_OWNERDRAW;
			SetItem(i,&hdItem);
			
			int i=0,lines=1;
			while((hdItem.pszText)[i]!=_T('\0'))
			{
				if((hdItem.pszText)[i]==_T('\n')) lines++;
				i++;
			}
			if(lines>max_lines) max_lines=lines;
		}

		if(m_TextFont.m_hObject==0)
		{
			LOGFONT lf1;
			CFont *cur_font=GetFont();
			cur_font->GetLogFont(&lf1);
			m_TextFont.CreateFontIndirect(&lf1);
		}

		LOGFONT lf;
		m_TextFont.GetLogFont(&lf);
		//HFONT hf=(HFONT)GetStockObject(DEFAULT_GUI_FONT);
		//::GetObject(hf, sizeof(LOGFONT), &lf); 

		lf.lfHeight=(long)((lf.lfHeight*(max_lines+0.4)));
		m_HighFont.CreateFontIndirect(&lf);
		SetFont(&m_HighFont);
		m_bUseMultiLine=true;
	}
	else // включаем оргинальную отрисовку
	{
		hdItem.mask = HDI_FORMAT;

		int k=HDF_OWNERDRAW;

		for(i=0; i<GetItemCount(); i++)
		{
			GetItem(i,&hdItem);
			hdItem.fmt&= ~HDF_OWNERDRAW;
			SetItem(i,&hdItem);
		}
		m_bUseMultiLine=false;
		SetFont(&m_TextFont);
	}
	// Так криво перересовываем. Другого способа не нашел (АЯ)
	CWnd *par=GetParent();
	if(par!=0)
	{
		if(par->m_hWnd!=0)
		{
			if(par->IsWindowVisible())
			{
				par->ShowWindow(SW_HIDE);
				par->ShowWindow(SW_SHOW);
			}
		}
	}
}


void CSortableHeaderCtrl::MyDraw(LPDRAWITEMSTRUCT lpDrawItemStruct)
{
	// TODO: Add your message handler code here and/or call default
	ASSERT(lpDrawItemStruct->CtlType == ODT_HEADER);

   HDITEM hdi;
   TCHAR  lpBuffer[256];

   hdi.mask = HDI_TEXT|HDI_BITMAP|HDI_FORMAT;
   hdi.pszText = lpBuffer;
   hdi.cchTextMax = 256;

   GetItem(lpDrawItemStruct->itemID, &hdi);

   	
	CDC* pDC;
	pDC = CDC::FromHandle(lpDrawItemStruct->hDC);

	//THIS FONT IS ONLY FOR DRAWING AS LONG AS WE DON'T DO A SetFont(...)
	//pDC->SelectObject(GetStockObject(DEFAULT_GUI_FONT));
	pDC->SelectObject(m_TextFont);
   // Draw the button frame.
   ::DrawFrameControl(lpDrawItemStruct->hDC, 
      &lpDrawItemStruct->rcItem, DFC_BUTTON, DFCS_BUTTONPUSH);

	RECT txt_rect=lpDrawItemStruct->rcItem;

	// Картинка сортировки 
	if((hdi.fmt&HDF_BITMAP)!=0)
	{
		CSize bmp_size; bmp_size.cx=9; bmp_size.cy=9;
		CPoint bmp_pnt;
		int bmp_dy=(txt_rect.bottom-txt_rect.top-bmp_size.cy)/2;
		bmp_pnt.x=txt_rect.left+3;
		bmp_pnt.y=txt_rect.top+bmp_dy;

		txt_rect.left=bmp_pnt.x+bmp_size.cx+2;

		pDC->DrawState(bmp_pnt,bmp_size,hdi.hbm,DST_BITMAP);
	}

	// текст
	UINT uFormat = DT_CENTER;

	//calculate text rectangle first
	CRect tmpRect = lpDrawItemStruct->rcItem;
	::DrawText(lpDrawItemStruct->hDC, lpBuffer, _strlen(lpBuffer), 
	&tmpRect, DT_CALCRECT);


	int dy=(txt_rect.bottom-tmpRect.bottom)/2;
	if(dy<0) dy=0;
	txt_rect.top+=dy;

	if((txt_rect.right-txt_rect.left)<(tmpRect.right-tmpRect.left))
	{
		uFormat=DT_LEFT;
		txt_rect.left+=3;
		txt_rect.right-=3;
	}

   ::DrawText(lpDrawItemStruct->hDC, lpBuffer, _strlen(lpBuffer), 
      &txt_rect, uFormat);

   pDC->SelectStockObject(SYSTEM_FONT);
   

//	CHeaderCtrl::OnDrawItem(nIDCtl, lpDrawItemStruct);
}


BOOL CSortableHeaderCtrl::OnChildNotify(UINT message, WPARAM wParam, LPARAM lParam, LRESULT* pLResult) 
{
	// TODO: Add your specialized code here and/or call the base class

	if ((message != WM_DRAWITEM) || (!m_bUseMultiLine))
		//return CHeaderCtrl::OnChildNotify(message, wParam, lParam, pLResult);
		return CWnd::OnChildNotify(message, wParam, lParam, pLResult);

	pLResult=0;
	//ASSERT(pLResult == NULL);       // no return value expected
	//UNUSED(pResult); // unused in release builds
	MyDraw((LPDRAWITEMSTRUCT)lParam);

	return TRUE;

//	return CHeaderCtrl::OnChildNotify(message, wParam, lParam, pLResult);
}
