/* Anakrino - .NET Reflection Browser
 * Copyright (C) 2001-2002  Jay Freeman (saurik)
*/

/*
 *        Redistribution and use in source and binary
 * forms, with or without modification, are permitted
 * provided that the following conditions are met:
 * 
 * 1. Redistributions of source code must retain the
 *    above copyright notice, this list of conditions
 *    and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the
 *    above copyright notice, this list of conditions
 *    and the following disclaimer in the documentation
 *    and/or other materials provided with the
 *    distribution.
 * 3. The name of the author may not be used to endorse
 *    or promote products derived from this software
 *    without specific prior written permission.
 * 
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS''
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

#ifndef ANAKRINO_MICROSOFTTAB_H
#define ANAKRINO_MICROSOFTTAB_H

#include "external/CoolTabCtrl.h"

class CMicrosoftTabCtrl :
	public CCustomTabCtrl<CMicrosoftTabCtrl>,
	public CCustomDraw<CMicrosoftTabCtrl>
{
  protected:
	CImageList m_Images;
	CBrush m_Backing;

	CFont m_fRegular;
	CFont m_fSelected;

	bool m_SelBold;

  public:
	DECLARE_WND_CLASS(_T("WTL_CoolMicrosoftTabCtrl"))

	BEGIN_MSG_MAP(CMicrosoftTabCtrl)
		MESSAGE_HANDLER(WM_ERASEBKGND, OnEraseBkgnd)
		CHAIN_MSG_MAP(CCustomTabCtrl<CMicrosoftTabCtrl>)
		CHAIN_MSG_MAP_ALT(CCustomDraw<CMicrosoftTabCtrl>, 1)
		REFLECTED_NOTIFY_CODE_HANDLER(TCN_INITIALIZE, OnInitialize)
		DEFAULT_REFLECTION_HANDLER()
	END_MSG_MAP()

	CImageList SetImageList(HIMAGELIST list) {
		CImageList oldList = m_Images;
		m_Images = list;
		return oldList;
	}

	CImageList& GetImageList() {
		return m_Images;
	}

	LRESULT OnEraseBkgnd(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/) {
		CDCHandle dc((HDC) wParam);

		RECT rc;
		GetClientRect(&rc);

		HBRUSH hOldBrush = dc.SelectBrush(m_Backing);
		dc.PatBlt(rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, PATCOPY);
		dc.SelectBrush(hOldBrush);

		dc.SelectStockPen(WHITE_PEN);
		dc.MoveTo(0, rc.bottom - 1);
		dc.LineTo(rc.right + 1, rc.bottom - 1);

		// Connect with the client area.
		DWORD dwStyle = (DWORD)::GetWindowLong(m_hWnd, GWL_STYLE);
		BOOL bHasBottomStyle = dwStyle & TCS_BOTTOM;

		/*if (bHasBottomStyle) {
			rc.bottom = rc.top + 3;
			dc.FillSolidRect(&rc, GetSysColor(COLOR_BTNFACE));
		} else {
			rc.top = rc.bottom - 3;
			dc.FillSolidRect(&rc, GetSysColor(COLOR_BTNFACE));
		}*/

		return 1;
	}

	LRESULT OnInitialize(int /*idCtrl*/, LPNMHDR /*pnmh*/, BOOL& /*bHandled*/) {
		TC_SIZES sizes;
		GetSizeSettings(&sizes);

		sizes.iIndent = 5;
		sizes.iPadding = 0;
		sizes.iMargin = 6;
		sizes.iSelMargin = 1;
		SetSizeSettings(&sizes);

		m_SelBold = true;
		return 0;
	}

	DWORD OnPrePaint(int /*idCtrl*/, LPNMCUSTOMDRAW lpNMCustomDraw) {
		CDCHandle dc = lpNMCustomDraw->hdc ;
		dc.SetTextColor(::GetSysColor(COLOR_BTNTEXT));
		::SetBkMode(lpNMCustomDraw->hdc, TRANSPARENT);

		return CDRF_NOTIFYITEMDRAW;
	}

	DWORD OnItemPrePaint(int /*idCtrl*/, LPNMCUSTOMDRAW lpNMCustomDraw) {
		CDCHandle dc = lpNMCustomDraw->hdc;
		bool bSelected = lpNMCustomDraw->uItemState & CDIS_SELECTED;

		RECT &rc = lpNMCustomDraw->rc;
		RECT rcTab = rc;

		DWORD dwStyle = (DWORD)::GetWindowLong(m_hWnd, GWL_STYLE);
		BOOL bHasBottomStyle = dwStyle & TCS_BOTTOM;

		if (bHasBottomStyle) {
			rcTab.top += 3;
			rcTab.bottom -= 2;
		} else {
			rcTab.top += 2;
			//rcTab.bottom -= 3;
		}

		rcTab.right--;
		if (bSelected) {
			dc.FillRect(&rcTab, (HBRUSH) (COLOR_BTNFACE + 1));

			if (bHasBottomStyle) {
				dc.SelectStockPen(BLACK_PEN);
				dc.MoveTo(rcTab.right, rcTab.top);
				dc.LineTo(rcTab.right, rcTab.bottom);
				dc.LineTo(rcTab.left, rcTab.bottom);
				dc.SelectStockPen(WHITE_PEN);
				dc.LineTo(rcTab.left, rcTab.top);
			} else {
				dc.SelectStockPen(WHITE_PEN);
				dc.MoveTo(rcTab.left, rcTab.bottom);
				dc.LineTo(rcTab.left, rcTab.top);
				dc.LineTo(rcTab.right, rcTab.top);
				dc.SelectStockPen(BLACK_PEN);
				dc.LineTo(rcTab.right, rcTab.bottom);
			}
		} else {
			CPen shadow;
			shadow.CreatePen(PS_SOLID, 1, ::GetSysColor(COLOR_3DSHADOW));

			dc.SelectPen(shadow);
			dc.MoveTo(rcTab.right, 5);
			dc.LineTo(rcTab.right, rcTab.bottom - 2);
		}

		TCITEM item = { 0 };
		TCHAR szText[128];
		item.mask = TCIF_TEXT | TCIF_IMAGE;
		item.pszText = szText;
		item.cchTextMax = sizeof(szText)/sizeof(TCHAR);
		GetItem(lpNMCustomDraw->dwItemSpec, &item);

		TC_SIZES sizes;
		GetSizeSettings(&sizes);

		HFONT oldFont = dc.SelectFont(bSelected ? m_fSelected : m_fRegular);
		COLORREF oldTextColor = dc.SetTextColor(bSelected ? RGB(0, 0, 0) : RGB(115, 115, 118));
		//COLORREF oldTextColor = dc.SetTextColor(::GetSysColor(bSelected ? COLOR_BTNTEXT : COLOR_GRAYTEXT));

		RECT rcText = rc;
		::InflateRect(&rcText, -sizes.iPadding, 0);

		if (item.mask & TCIF_IMAGE && !m_Images.IsNull()) {
			IMAGEINFO ii;
			m_Images.GetImageInfo(item.iImage, &ii);

			DWORD dwDrawStyle = ILD_NORMAL;
			if (ii.hbmMask)
				dwDrawStyle |= ILD_MASK;

			if (ii.rcImage.right - ii.rcImage.left + sizes.iMargin * 2 < rcTab.right - rcTab.left)
				m_Images.Draw(dc, item.iImage, rcTab.left + sizes.iMargin * 2, rcTab.top + 3, ILD_NORMAL);

			rcText.left += ii.rcImage.right - ii.rcImage.left + sizes.iMargin * 2;
		}

		rcText.left += sizes.iMargin;
		rcText.right -= sizes.iMargin;
		rcText.bottom -= bHasBottomStyle ? 4 : 3;

		if (bSelected)
			rcText.left += sizes.iSelMargin;

		if (rcText.left + 12 < rcText.right)
			dc.DrawText(item.pszText, ::lstrlen(item.pszText), &rcText, DT_LEFT | DT_BOTTOM | DT_SINGLELINE | DT_END_ELLIPSIS);

		dc.SetTextColor(oldTextColor);
		dc.SelectFont(oldFont);

		return CDRF_SKIPDEFAULT;
	}

	LRESULT OnSettingChange(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) {

		if (!m_fRegular.IsNull())
			m_fRegular.DeleteObject();
		if (!m_fSelected.IsNull())
			m_fSelected.DeleteObject();
		if (!m_Backing.IsNull())
			m_Backing.DeleteObject();

		LOGFONT font;
		GetObject(AtlGetStockFont(DEFAULT_GUI_FONT), sizeof(LOGFONT), &font);
		_tcscpy(font.lfFaceName, _T("Tahoma"));
		m_fRegular.CreateFontIndirect(&font);

		if (m_SelBold)
			font.lfWeight = FW_BOLD;
		m_fSelected.CreateFontIndirect(&font);

		CWindowDC dc(NULL);
		int nBitsPerPixel = dc.GetDeviceCaps(BITSPIXEL);

		if (nBitsPerPixel > 8) {
			m_Backing.CreateSolidBrush(RGB(251, 250, 255));
		} else {
			m_Backing =  CDCHandle::GetHalftoneBrush();
		}

		Invalidate();
		return 0;
	}

	void UpdateLayout() {
		CClientDC dc(m_hWnd);

		RECT rcClient;
		GetClientRect(&rcClient);

		int cnt = m_Sizes.GetSize();
		int xpos = m_settings.iIndent;

		for (int i(0); i < cnt; i++) {
			LPTCITEM pItem = m_Items[i];

			RECT rc;
			rc.left = rc.right = xpos;
			rc.top = 0;
			rc.bottom = rcClient.bottom - rcClient.top;

			if (pItem->mask & TCIF_TEXT) {
				HFONT hOldFont = dc.SelectFont(i == m_iCurSel ? m_fSelected : m_fRegular);

				RECT rcText = { 0 };
				::DrawText(dc, pItem->pszText, ::lstrlen(pItem->pszText), &rcText, DT_SINGLELINE | DT_CALCRECT);
				rc.right += (rcText.right - rcText.left) + m_settings.iMargin * 2;

				dc.SelectFont(hOldFont);
			}

			if (pItem->mask & TCIF_IMAGE && !m_Images.IsNull()) {
				IMAGEINFO ii;
				m_Images.GetImageInfo(pItem->iImage, &ii);
				rc.right += ii.rcImage.right - ii.rcImage.left + m_settings.iMargin * 2;
			}

			xpos += rc.right - rc.left;

			if (i == m_iCurSel)
				--rc.left;
			m_Sizes.SetAtIndex(i, rc);
		}

		int cxClient = rcClient.right - rcClient.left;
		if (xpos > cxClient && cnt != 0) {
			xpos = m_settings.iIndent;

			int cxItem = (cxClient - xpos) / cnt;
			for (i = 0; i < cnt; i++) {
				LPTCITEM pItem = m_Items[i];
				RECT rc;
				rc.left = rc.right = xpos;
				rc.right += cxItem;
				rc.top = 0;
				rc.bottom = rcClient.bottom-rcClient.top;
				m_Sizes.SetAtIndex(i, rc);
				xpos += (rc.right-rc.left); //+ m_settings.iMargin;
			}
		}
	}
};


#endif//ANAKRINO_MICROSOFTTAB_H