// XTPTabPaintManager.cpp: implementation of the CXTPTabPaintManager class.
//
// This file is a part of the XTREME TOOLKIT PRO MFC class library.
// (c)1998-2012 Codejock Software, All Rights Reserved.
//
// THIS SOURCE FILE IS THE PROPERTY OF CODEJOCK SOFTWARE AND IS NOT TO BE
// RE-DISTRIBUTED BY ANY MEANS WHATSOEVER WITHOUT THE EXPRESSED WRITTEN
// CONSENT OF CODEJOCK SOFTWARE.
//
// THIS SOURCE CODE CAN ONLY BE USED UNDER THE TERMS AND CONDITIONS OUTLINED
// IN THE XTREME TOOLKIT PRO LICENSE AGREEMENT. CODEJOCK SOFTWARE GRANTS TO
// YOU (ONE SOFTWARE DEVELOPER) THE LIMITED RIGHT TO USE THIS SOFTWARE ON A
// SINGLE COMPUTER.
//
// CONTACT INFORMATION:
// support@codejock.com
// http://www.codejock.com
//
/////////////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "Common/XTPVC80Helpers.h"
#include "Common/XTPSystemHelpers.h"
#include "Common/XTPMarkupRender.h"
#include "Common/XTPColorManager.h"
#include "Common/XTPDrawHelpers.h"

#include "XTPTabManager.h"
#include "XTPTabPaintManager.h"

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

DWORD CXTPTabPaintManager::m_nSelectOnDragOverDelay = 300;

//////////////////////////////////////////////////////////////////////
// CXTPTabPaintManager


CXTPTabPaintManager::CXTPTabPaintManager()
{
	m_bUseStandardFont = TRUE;

	m_pColorSet = NULL;
	m_pAppearanceSet = NULL;

	SetAppearance(xtpTabAppearancePropertyPage);

	m_bHotTracking = FALSE;
	m_bBoldNormal = m_bBoldSelected = FALSE;
	m_bShowIcons = TRUE;
	m_bSelectOnButtonDown = TRUE;

	m_bDisableLunaColors = FALSE;
	m_bOneNoteColors = FALSE;

	m_tabPosition = xtpTabPositionTop;
	m_tabLayout = xtpTabLayoutAutoSize;

	m_clientFrame = xtpTabFrameBorder;
	m_bStaticFrame = FALSE;

	m_bInvertGradient = FALSE;
	m_bFillBackground = TRUE;
	m_bDrawFocusRect = TRUE;

	m_rcClientMargin.SetRect(0, 0, 0, 0);
	m_rcControlMargin.SetRect(0, 0, 0, 0);
	m_rcButtonMargin.SetRect(0, 0, 0, 0);

	m_nButtonExtraLength = 0;
	m_szIcon = CSize(16, 16);

	m_nFixedTabWidth = 70;
	m_nMinTabWidth = m_nMaxTabWidth = 0;


	m_bDrawTextEndEllipsis = TRUE;
	m_bDrawTextPathEllipsis = FALSE;
	m_bDrawTextNoPrefix = TRUE;
	m_bDrawTextHidePrefix = FALSE;

	m_bMultiRowFixedSelection = FALSE;
	m_bMultiRowJustified = TRUE;

	m_toolBehaviour = xtpTabToolTipShrinkedOnly;
	m_bSelectOnDragOver = 2;
	m_nItemColor = 0;

	m_bClearTypeTextQuality = FALSE;
	m_bRotateImageOnVerticalDraw = FALSE;

	m_rcButtonTextPadding.SetRect(6, 0, 6, 0);

	m_bClipHeader = TRUE;

	m_nDrawTextFormat = DT_LEFT | DT_VCENTER;

	m_szNavigateButton = CSize(14, 15);

	m_bShowTabs = TRUE;

	m_bVerticalTextTopToBottom = TRUE;


	EnableAutomation();



	RefreshMetrics();
}

CXTPTabPaintManager::~CXTPTabPaintManager()
{
	SAFE_DELETE(m_pColorSet);
	SAFE_DELETE(m_pAppearanceSet);
}

CXTPTabPaintManagerColorSet* CXTPTabPaintManager::SetColor(XTPTabColorStyle tabColor)
{
	CXTPTabPaintManagerColorSet* pColorSet = NULL;

	m_tabColor = tabColor;

	switch (tabColor)
	{
	case xtpTabColorWinNative: pColorSet = new CColorSetWinNative(); break;
	case xtpTabColorVisualStudio2003: pColorSet = new CColorSetVisualStudio2003(); break;
	case xtpTabColorVisualStudio2005: pColorSet = new CColorSetVisualStudio2005(); break;
	case xtpTabColorVisualStudio2008: pColorSet = new CColorSetVisualStudio2008(); break;
	case xtpTabColorVisualStudio2010: pColorSet = new CColorSetVisualStudio2010(); break;
	case xtpTabColorOffice2003: pColorSet = new CColorSetOffice2003(); break;
	case xtpTabColorResource: pColorSet = new CColorSetOffice2007(); break;
	case xtpTabColorOffice2007Access: pColorSet = new CColorSetOffice2007Access(); break;
	default: pColorSet = new CColorSetDefault(); break;
	}

	return SetColorSet(pColorSet);
}
CXTPTabPaintManagerColorSet* CXTPTabPaintManager::SetColorSet(CXTPTabPaintManagerColorSet* pColorSet)
{
	if (pColorSet)
	{
		if (m_pColorSet) delete m_pColorSet;
		m_pColorSet = pColorSet;

		pColorSet->m_pPaintManager = this;
		pColorSet->RefreshMetrics();
	}
	OnPropertyChanged();

	return pColorSet;
}

CXTPTabPaintManagerAppearanceSet* CXTPTabPaintManager::SetAppearance(XTPTabAppearanceStyle tabAppearance)
{
	CXTPTabPaintManagerAppearanceSet* pAppearanceSet = NULL;

	m_tabAppearance = tabAppearance;
	if (tabAppearance == xtpTabAppearanceVisualStudio) pAppearanceSet = new CAppearanceSetVisualStudio();
	else if (tabAppearance == xtpTabAppearanceExcel) pAppearanceSet = new CAppearanceSetExcel();
	else if (tabAppearance == xtpTabAppearancePropertyPageFlat) pAppearanceSet = new CAppearanceSetPropertyPageFlat();
	else if (tabAppearance == xtpTabAppearanceFlat) pAppearanceSet = new CAppearanceSetFlat();
	else if (tabAppearance == xtpTabAppearanceStateButtons) pAppearanceSet = new CAppearanceSetStateButtons();
	else if (tabAppearance == xtpTabAppearancePropertyPageSelected) pAppearanceSet = new CAppearanceSetPropertyPageSelected();
	else if (tabAppearance == xtpTabAppearancePropertyPage2003) pAppearanceSet = new CAppearanceSetPropertyPage2003();
	else if (tabAppearance == xtpTabAppearanceVisio) pAppearanceSet = new CAppearanceSetVisio();
	else if (tabAppearance == xtpTabAppearanceVisualStudio2005) pAppearanceSet = new CAppearanceSetVisualStudio2005();
	else if (tabAppearance == xtpTabAppearancePropertyPage2007) pAppearanceSet = new CAppearanceSetPropertyPage2007();
	else if (tabAppearance == xtpTabAppearancePropertyPageAccess2007) pAppearanceSet = new CAppearanceSetPropertyPageAccess2007();
	else if (tabAppearance == xtpTabAppearanceVisualStudio2010) pAppearanceSet = new CAppearanceSetVisualStudio2010();
	else pAppearanceSet = new CAppearanceSetPropertyPage();

	return SetAppearanceSet(pAppearanceSet);

}
CXTPTabPaintManagerAppearanceSet* CXTPTabPaintManager::SetAppearanceSet(CXTPTabPaintManagerAppearanceSet* pAppearanceSet)
{
	if (pAppearanceSet)
	{
		if (m_pAppearanceSet) delete m_pAppearanceSet;
		m_pAppearanceSet = pAppearanceSet;

		pAppearanceSet->m_pPaintManager = this;
		pAppearanceSet->RefreshMetrics();

		SetColor(pAppearanceSet->GetDefaultColorSet());
	}
	OnPropertyChanged();

	return pAppearanceSet;

}


void CXTPTabPaintManager::SetFontIndirect(LOGFONT* pLogFont, BOOL bUseStandardFont /*= FALSE*/)
{
	m_bUseStandardFont = bUseStandardFont;

	if (!pLogFont)
		return;

	if (m_bClearTypeTextQuality && XTPSystemVersion()->IsClearTypeTextQualitySupported())
	{
		pLogFont->lfQuality = 5;
	}

	m_fntNormal.DeleteObject();
	m_fntBold.DeleteObject();
	m_fntVerticalNormal.DeleteObject();
	m_fntVerticalBold.DeleteObject();

	pLogFont->lfWeight = m_bBoldNormal ? FW_BOLD : FW_NORMAL;
	VERIFY(m_fntNormal.CreateFontIndirect(pLogFont));

	pLogFont->lfWeight = FW_BOLD;
	VERIFY(m_fntBold.CreateFontIndirect(pLogFont));

	STRCPY_S(pLogFont->lfFaceName, LF_FACESIZE, CXTPDrawHelpers::GetVerticalFontName(FALSE));

	if (m_bVerticalTextTopToBottom)
	{
		pLogFont->lfOrientation = 900;
		pLogFont->lfEscapement = 2700;
	}
	else
	{
		pLogFont->lfOrientation = 900;
		pLogFont->lfEscapement = 900;
	}
	pLogFont->lfHeight = pLogFont->lfHeight < 0 ? __min(-11, pLogFont->lfHeight) : pLogFont->lfHeight;
	pLogFont->lfWeight = m_bBoldNormal ? FW_BOLD : FW_NORMAL;
	VERIFY(m_fntVerticalNormal.CreateFontIndirect(pLogFont));

	pLogFont->lfWeight = FW_BOLD;
	VERIFY(m_fntVerticalBold.CreateFontIndirect(pLogFont));
}

void CXTPTabPaintManager::RefreshMetrics()
{
	if (m_bUseStandardFont)
	{
		LOGFONT lfIcon;
		VERIFY(CXTPDrawHelpers::GetIconLogFont(&lfIcon));

		SetFontIndirect(&lfIcon, TRUE);
	}

	m_pColorSet->RefreshMetrics();
	m_pAppearanceSet->RefreshMetrics();
}

void CXTPTabPaintManager::DisableLunaColors(BOOL bDisableLunaColors)
{
	m_bDisableLunaColors = bDisableLunaColors;
	RefreshMetrics();
	OnPropertyChanged();
}
BOOL CXTPTabPaintManager::IsLunaColorsDisabled() const
{
	return m_bDisableLunaColors || XTPColorManager()->IsLunaColorsDisabled();
}

COLORREF CXTPTabPaintManager::GetOneNoteColor(XTPTabOneNoteColor tabColor)
{
	const COLORREF clrTable[] =
	{
		RGB(138, 168, 228), // xtpTabColorBlue    : Blue tab color used when OneNote colors enabled.
		RGB(255, 219, 117), // xtpTabColorYellow  : Yellow tab color used when OneNote colors enabled.
		RGB(189, 205, 159), // xtpTabColorGreen   : Green tab color used when OneNote colors enabled.
		RGB(240, 158, 159), // xtpTabColorRed     : Red tab color used when OneNote colors enabled.
		RGB(186, 166, 225), // xtpTabColorPurple  : Purple tab color used when OneNote colors enabled.
		RGB(154, 191, 180), // xtpTabColorCyan    : Cyan tab color used when OneNote colors enabled.
		RGB(247, 182, 131), // xtpTabColorOrange  : Orange tab color used when OneNote colors enabled.
		RGB(216, 171, 192)  // xtpTabColorMagenta : Magenta tab color used when OneNote colors enabled.
	};

	return clrTable[tabColor-xtpTabColorBlue];
}

void CXTPTabPaintManager::SetOneNoteColors(BOOL bOneNoteColors /* = TRUE */)
{
	m_bOneNoteColors = bOneNoteColors;
	RefreshMetrics();
}

void CXTPTabPaintManager::DrawNavigateButton(CDC* pDC, CXTPTabManagerNavigateButton* pButton, CRect& rc)
{
	FillNavigateButton(pDC, pButton, rc);

	COLORREF clr = pDC->GetTextColor();
	CXTPPenDC pen(*pDC, clr);

	if (pButton->IsEnabled())
	{
		CXTPBrushDC brush(*pDC, clr);
		pButton->DrawEntry(pDC, rc);
	}
	else
	{
		CBrush* pOldBrush = (CBrush*)pDC->SelectStockObject(NULL_BRUSH);
		pButton->DrawEntry(pDC, rc);
		pDC->SelectObject(pOldBrush);
	}

}

void CXTPTabPaintManager::FillNavigateButton(CDC* pDC, CXTPTabManagerNavigateButton* pButton, CRect& rc)
{
	m_pColorSet->FillNavigateButton(pDC, pButton, rc);
}

void CXTPTabPaintManager::DrawTabControl(CXTPTabManager* pTabManager, CDC* pDC, CRect rcClient)
{
	m_pAppearanceSet->DrawTabControl(pTabManager, pDC, rcClient);
}

void CXTPTabPaintManager::DrawRowItems(CXTPTabManager* pTabManager, CDC* pDC, const CRect& rcClipBox, int nItemRow)
{
	CXTPTabManagerItem* pSelected = NULL;

	CXTPTabManager::ROW_ITEMS* pRowItems = pTabManager->m_pRowIndexer->GetRowItems();

	if (!pRowItems)
		return;

	if (nItemRow >= pTabManager->GetRowCount())
		return;

	int nFirstItem = pRowItems[nItemRow].nFirstItem;
	int nLastItem = pRowItems[nItemRow].nLastItem;
	BOOL bDrawRow = TRUE;

	if (m_pAppearanceSet->m_bButtonsReverseZOrder)
	{
		bDrawRow = FALSE;

		for (int i = nFirstItem; i <= nLastItem; i++)
		{
			CXTPTabManagerItem* pItem = pTabManager->GetItem(i);
			if (!pItem)
				return;

			if (pItem->m_nItemRow != nItemRow)
				break;

			if (pItem->IsSelected())
			{
				nFirstItem = i;
				bDrawRow = TRUE;
				break;
			}

			if (pItem->IsVisible() && CRect().IntersectRect(rcClipBox, m_pAppearanceSet->GetButtonDrawRect(pItem)))
			{
				m_pAppearanceSet->DrawSingleButton(pDC, pItem);
			}
		}
	}

	if (bDrawRow)
	{
		for (int i = nLastItem; i >= nFirstItem; i--)
		{
			CXTPTabManagerItem* pItem = pTabManager->GetItem(i);
			if (!pItem)
				return;

			if (pItem->m_nItemRow != nItemRow)
				break;

			if (pItem->IsVisible() && CRect().IntersectRect(rcClipBox, m_pAppearanceSet->GetButtonDrawRect(pItem)))
			{
				if (pItem->IsSelected())
					pSelected = pItem;
				else
					m_pAppearanceSet->DrawSingleButton(pDC, pItem);
			}
		}
	}


	if (pSelected)
	{
		m_pAppearanceSet->DrawSingleButton(pDC, pSelected);
	}


}

void CXTPTabPaintManager::DrawTabControlEx(CXTPTabManager* pTabManager, CDC* pDC, CRect rcClient)
{
	if (pTabManager->IsDrawStaticFrame())
	{
		pDC->Draw3dRect(rcClient, GetColorSet()->m_clrFrameBorder, GetColorSet()->m_clrFrameBorder);
		CXTPTabPaintManagerAppearanceSet::DeflateRectEx(rcClient, CRect(1, 1, 1, 1), pTabManager->GetPosition());
		pDC->Draw3dRect(rcClient, GetColorSet()->m_clrControlFace, GetColorSet()->m_clrControlFace);
		CXTPTabPaintManagerAppearanceSet::DeflateRectEx(rcClient, CRect(1, 0, 1, 1), pTabManager->GetPosition());
	}

	if (m_bFillBackground)
	{
		pDC->FillSolidRect(rcClient, GetColorSet()->m_clrControlFace);
	}

	CXTPTabPaintManagerAppearanceSet::DeflateRectEx(rcClient, m_rcControlMargin, pTabManager->GetPosition());

	pDC->SetBkMode(TRANSPARENT);


	if (m_bFillBackground)
	{
		m_pAppearanceSet->FillTabControl(pTabManager, pDC, rcClient);
	}

	CRect rcClipBox;
	pDC->GetClipBox(rcClipBox);

	if (m_bClipHeader)
		rcClipBox = m_pAppearanceSet->GetHeaderClipBox(pDC, pTabManager);

	if (!rcClipBox.IsRectEmpty())
	{
		CRgn rgn;
		if (m_bClipHeader)
		{
			CRect rcClipBoxViewport(rcClipBox);
			rcClipBoxViewport.OffsetRect(-pDC->GetWindowOrg());

			rgn.CreateRectRgnIndirect(rcClipBoxViewport);
			pDC->SelectClipRgn(&rgn);

			m_pColorSet->SelectClipRgn(pDC, rcClient, pTabManager);
		}

		int nRowCont = pTabManager->GetRowCount();

		for (int j = nRowCont - 1; j >= 0; j--)
		{
			DrawRowItems(pTabManager, pDC, rcClipBox, j);
		}

		if (m_bClipHeader)
		{
			pDC->SelectClipRgn(NULL);
		}
	}

	for (int i = pTabManager->GetNavigateButtonCount() - 1; i >= 0; i--)
		pTabManager->GetNavigateButton(i)->Draw(pDC);

}
int CXTPTabPaintManager::_GetButtonLength(int nValue, int nMin, int nMax)
{
	nValue += m_rcButtonMargin.left +  m_rcButtonMargin.right;
	if (nMin > 0) nValue = max(nMin, nValue);
	if (nMax > 0) nValue = min(nMax, nValue);
	return nValue;
}

void CXTPTabPaintManager::StripMnemonics(CString& strClear)
{
	CXTPDrawHelpers::StripMnemonics(strClear);
}

int CXTPTabPaintManager::GetPrefixTextExtent(CDC* pDC, const CString& str, UINT uFormat)
{
	if (uFormat & DT_NOPREFIX)
		return pDC->GetTextExtent(str).cx;

	CString strClear = str;
	StripMnemonics(strClear);

	return pDC->GetTextExtent(strClear).cx;
}

void CXTPTabPaintManager::DrawTextPathEllipsis(CDC* pDC, CXTPTabManager* pManager, const CString& strItem, CRect rcItem, UINT uFormat)
{
	if (strItem.Find(_T('\\')) != -1)
	{
		m_pAppearanceSet->DrawText(pDC, pManager, strItem, rcItem, uFormat | DT_PATH_ELLIPSIS);
		return;
	}

	LPCTSTR strEllipsis = _T("...");
	int cxEllipsis = pDC->GetTextExtent(strEllipsis, 3).cx;
	int cxItem = GetPrefixTextExtent(pDC, strItem, uFormat);

	if (cxItem <= rcItem.Width())
	{
		m_pAppearanceSet->DrawText(pDC, pManager, strItem, rcItem, uFormat);
		return;
	}
	if (rcItem.Width() <= cxEllipsis)
	{
		m_pAppearanceSet->DrawText(pDC, pManager, CString(strEllipsis), rcItem, uFormat);
		return;
	}
	int nWidth = rcItem.Width() - cxEllipsis;

	int nResultLength = strItem.GetLength() * nWidth / cxItem;
	CString strResultLeft = strItem.Left(nResultLength - nResultLength / 2);
	CString strResultRight = strItem.Right(nResultLength / 2);

	while (GetPrefixTextExtent(pDC, strResultLeft, uFormat) + GetPrefixTextExtent(pDC, strResultRight, uFormat) < nWidth)
	{
		nResultLength++;
		strResultLeft = strItem.Left(nResultLength - nResultLength / 2);
		strResultRight = strItem.Right(nResultLength / 2);
	}

	while (GetPrefixTextExtent(pDC, strResultLeft, uFormat) + GetPrefixTextExtent(pDC, strResultRight, uFormat) > nWidth)
	{
		nResultLength--;
		strResultLeft = strItem.Left(nResultLength - nResultLength / 2);
		strResultRight = strItem.Right(nResultLength / 2);
	}

	m_pAppearanceSet->DrawText(pDC, pManager, strResultLeft + strEllipsis + strResultRight, rcItem, uFormat);
}

void CXTPTabPaintManager::DrawFocusRect(CDC* pDC, CXTPTabManagerItem* /*pItem*/, CRect rcItem)
{
	if (!m_bDrawFocusRect)
		return;

	rcItem.DeflateRect(3, 3, 3, 3);
	pDC->SetTextColor(0);
	pDC->SetBkColor(0xFFFFFF);
	pDC->DrawFocusRect(rcItem);
}

int CXTPTabPaintManager::DrawSingleButtonIconAndText(CDC* pDC, CXTPTabManagerItem* pItem, CRect rcItem, BOOL bDraw)
{
	CXTPTabManager* pManager = pItem->GetTabManager();

	XTPTabLayoutStyle layout = pManager->GetLayout();

	BOOL bVertical = !pManager->IsHorizontalPosition();
	if (layout == xtpTabLayoutRotated) bVertical = !bVertical;

	CString strItem = pItem->GetCaption();

	CFont* pFont = m_bBoldSelected && pItem->IsSelected() && pManager->IsActive() ? GetBoldFont(bVertical) : GetFont(bVertical);
	CXTPFontDC fnt(pDC, pFont);


	CSize szIcon(m_szIcon);
	BOOL bDrawIcon = pManager->DrawIcon(pDC, 0, pItem, FALSE, szIcon);
	BOOL bDrawText = layout != xtpTabLayoutCompressed || pItem->IsSelected();

	int nNavigateButtonsLength = 0;
	if (bDrawText && pItem->GetNavigateButtons()->GetSize() > 0)
	{
		nNavigateButtonsLength = 0;
		for (int i = 0; i < (int)pItem->GetNavigateButtons()->GetSize(); i++)
		{
			CXTPTabManagerNavigateButton* pButton = pItem->GetNavigateButtons()->GetAt(i);
			if (pManager->IsNavigateButtonVisible(pButton))
			{
				CSize sz = pButton->GetSize();
				nNavigateButtonsLength += bVertical ? sz.cy : sz.cx;
			}
		}

		if (nNavigateButtonsLength > 0) nNavigateButtonsLength += 3;
	}


	if (bDraw)
	{
		if (nNavigateButtonsLength > 0)
		{
			m_pColorSet->SetTextColor(pDC, pItem);

			CRect rcEntry(rcItem);
			rcEntry.DeflateRect(m_rcButtonMargin);

			if (bVertical) rcItem.bottom -= 3; else rcItem.right -= 3;

			for (int i = (int)pItem->GetNavigateButtons()->GetSize() - 1; i >= 0; i--)
			{
				CXTPTabManagerNavigateButton* pButton = pItem->GetNavigateButtons()->GetAt(i);


				if (pManager->IsNavigateButtonVisible(pButton))
				{
					CSize szButton = pButton->GetSize();
					if (!bVertical)
					{
						pButton->SetRect(CRect(rcItem.right - szButton.cx,
							rcEntry.CenterPoint().y + szButton.cy / 2 - szButton.cy, rcItem.right,
							rcEntry.CenterPoint().y + szButton.cy / 2));
						rcItem.right -= szButton.cx;
					}
					else
					{
						pButton->SetRect(CRect(rcEntry.CenterPoint().x - szButton.cx / 2,
							rcItem.bottom - szButton.cy, rcEntry.CenterPoint().x - szButton.cx / 2 + szButton.cx, rcItem.bottom));
						rcItem.bottom -= szButton.cy;
					}
					pItem->GetNavigateButtons()->GetAt(i)->Draw(pDC);
				}
			}
		}

		m_pColorSet->SetTextColor(pDC, pItem);

		CRect rcFocus(rcItem);

		if (bVertical)
		{
			int nAvailLength = pItem->GetButtonLength() - pItem->GetContentLength();
			if (nAvailLength > 0)
			{
				rcItem.DeflateRect(0, nAvailLength / 2);
			}

			rcItem.top += m_rcButtonTextPadding.left + m_rcButtonMargin.left;
			if (pManager->GetPosition() == xtpTabPositionRight)
				rcItem.DeflateRect(m_rcButtonMargin.bottom, 0, m_rcButtonMargin.top, 0);
			else
				rcItem.DeflateRect(m_rcButtonMargin.top, 0, m_rcButtonMargin.bottom, 0);

			if (bDrawIcon)
			{
				if (m_bVerticalTextTopToBottom)
				{
					CPoint pt(rcItem.CenterPoint().x - szIcon.cx/2, rcItem.top - 1);
					if (rcItem.Height() > szIcon.cy) pManager->DrawIcon(pDC, pt, pItem, TRUE, szIcon);
					rcItem.top += szIcon.cy + 2;
				}
				else
				{
					CPoint pt(rcItem.CenterPoint().x - szIcon.cx/2, rcItem.bottom - szIcon.cy - (m_rcButtonTextPadding.left + m_rcButtonMargin.left) + 1);
					if (rcItem.Height() > szIcon.cy) pManager->DrawIcon(pDC, pt, pItem, TRUE, szIcon);
					rcItem.bottom -= szIcon.cy + m_rcButtonTextPadding.left + m_rcButtonMargin.left - 1;
				}
			}

			if (bDrawText && rcItem.bottom > rcItem.top + 8)
			{
				CSize szText = pDC->GetTextExtent(strItem);
				rcItem.left = rcItem.right - (rcItem.Width() - szText.cy - (pManager->GetPosition() == xtpTabPositionRight ? 1 : 0)) / 2;
				rcItem.right = rcItem.left + rcItem.Height();
				rcItem.bottom -= m_rcButtonMargin.right + max(0, m_rcButtonTextPadding.right - 4);

				if (!m_bVerticalTextTopToBottom)
				{
					int nHeight = min(rcItem.Height(), szText.cx);
					rcItem.OffsetRect(-szText.cy, nHeight);
				}

				if (!m_bDrawTextNoPrefix)
					StripMnemonics(strItem);

				if (m_bDrawTextPathEllipsis)
				{
					DrawTextPathEllipsis(pDC, pManager, strItem, rcItem, DT_SINGLELINE | DT_NOCLIP | DT_NOPREFIX);
				}
				else
				{
					m_pAppearanceSet->DrawText(pDC, pManager, strItem, &rcItem, DT_SINGLELINE | DT_NOCLIP |
						DT_NOPREFIX | (m_bDrawTextEndEllipsis ? DT_END_ELLIPSIS : 0));
				}
			}

		}
		else
		{
			int nAvailLength = pItem->GetButtonLength() - pItem->GetContentLength();
			if (nAvailLength > 0)
			{
				rcItem.DeflateRect(nAvailLength / 2, 0);
			}

			rcItem.left += m_rcButtonTextPadding.left + m_rcButtonMargin.left;

			if (pManager->GetPosition() == xtpTabPositionBottom)
				rcItem.DeflateRect(0, m_rcButtonMargin.bottom, 0, m_rcButtonMargin.top);
			else
				rcItem.DeflateRect(0, m_rcButtonMargin.top, 0, m_rcButtonMargin.bottom);

			if (bDrawIcon)
			{
				CPoint pt(rcItem.left - 1, rcItem.CenterPoint().y - szIcon.cy/2);
				if (rcItem.Width() > szIcon.cx) pManager->DrawIcon(pDC, pt, pItem, TRUE, szIcon);
				rcItem.left += szIcon.cx + 2;
			}

			if (bDrawText && rcItem.right > rcItem.left)
			{
				rcItem.right -= m_rcButtonTextPadding.right + m_rcButtonMargin.right - (bDrawIcon ? 2 : 0);

				if (pItem->GetMarkupUIElement())
				{
					XTPMarkupSetDefaultFont(pItem->GetTabManager()->GetMarkupContext(), (HFONT)pFont->GetSafeHandle(), pDC->GetTextColor());

					CRect rcText(rcItem);

					if (m_nDrawTextFormat & DT_VCENTER)
					{
						CSize szText = XTPMarkupMeasureElement(pItem->GetMarkupUIElement());
						rcText.top = (rcText.top + rcText.bottom - szText.cy) / 2;
						rcText.bottom = rcText.top + szText.cy;
					}

					XTPMarkupRenderElement(pItem->GetMarkupUIElement(), pDC->GetSafeHdc(), rcText);
				}
				else if (m_bDrawTextPathEllipsis)
				{
					DrawTextPathEllipsis(pDC, pManager, strItem, rcItem, DT_SINGLELINE | m_nDrawTextFormat | (m_bDrawTextNoPrefix ? DT_NOPREFIX : 0));
				}
				else
				{
					if (m_bDrawTextHidePrefix)
						StripMnemonics(strItem);

					m_pAppearanceSet->DrawText(pDC, pManager, strItem, rcItem, DT_SINGLELINE | m_nDrawTextFormat |
						(m_bDrawTextHidePrefix || m_bDrawTextNoPrefix ? DT_NOPREFIX : 0) | (m_bDrawTextEndEllipsis ? DT_END_ELLIPSIS : 0));
				}
			}
		}

		if (pItem->IsFocused())
		{
			DrawFocusRect(pDC, pItem, rcFocus);
		}
		return 0;
	}
	else
	{
		if (layout == xtpTabLayoutFixed)
		{
			return _GetButtonLength(m_nFixedTabWidth, m_nMinTabWidth, m_nMaxTabWidth);
		}

		if (layout == xtpTabLayoutCompressed)
		{
			if (!bDrawText)
				return _GetButtonLength(8 + (bVertical ? szIcon.cy : szIcon.cx), m_nMinTabWidth, m_nMaxTabWidth) ;

			CXTPFontDC fntItems(pDC, m_bBoldSelected && pManager->IsActive() ? GetBoldFont(bVertical) : GetFont(bVertical));

			int nLength = 0;

			for (int i = 0; i < pManager->GetItemCount(); i++)
			{
				CRect rcItemText(0, 0, 0, 0);
				m_pAppearanceSet->DrawText(pDC, pManager, pManager->GetItem(i)->GetCaption(), rcItemText, DT_SINGLELINE | DT_CALCRECT | DT_NOCLIP | (m_bDrawTextNoPrefix ? DT_NOPREFIX : 0));
				nLength = max(nLength, rcItemText.Width());
			}
			return _GetButtonLength(nNavigateButtonsLength + nLength + m_rcButtonTextPadding.left + m_rcButtonTextPadding.right +
				(!bDrawIcon ? 0: bVertical ? szIcon.cy : szIcon.cx), m_nMinTabWidth, m_nMaxTabWidth);
		}

		CSize szText(0);
		if (pItem->GetMarkupUIElement())
		{
			XTPMarkupSetDefaultFont(pManager->GetMarkupContext(), (HFONT)pFont->GetSafeHandle(), pDC->GetTextColor());
			szText = XTPMarkupMeasureElement(pItem->GetMarkupUIElement());
		}
		else
		{
			m_pAppearanceSet->DrawText(pDC, pManager, strItem, rcItem, DT_SINGLELINE | DT_CALCRECT | DT_NOCLIP | (m_bDrawTextNoPrefix ? DT_NOPREFIX : 0));
			szText = rcItem.Size();
		}

		return _GetButtonLength(nNavigateButtonsLength + szText.cx + m_rcButtonTextPadding.left + m_rcButtonTextPadding.right +
			(!bDrawIcon ? 0: bVertical ? szIcon.cy : szIcon.cx), m_nMinTabWidth, m_nMaxTabWidth);
	}
}


void CXTPTabPaintManager::AdjustClientRect(CXTPTabManager* pTabManager, CRect& rcClient)
{
	if (pTabManager->IsDrawStaticFrame())
		CXTPTabPaintManagerAppearanceSet::DeflateRectEx(rcClient, CRect(2, 1, 2, 2), pTabManager->GetPosition());

	if (pTabManager->GetItemCount() > 0)
	{
		m_pAppearanceSet->AdjustClientRect(pTabManager, rcClient);
	}
}

CRect CXTPTabPaintManager::RepositionNavigateButtons(CXTPTabManager* pTabManager, CRect rcClient)
{
	CRect rcHeader = m_pAppearanceSet->GetHeaderRect(rcClient, pTabManager);
	CRect rcNavigateButtons = rcHeader;

	if (pTabManager->IsHorizontalPosition())
		rcNavigateButtons.right -= 1;
	else
		rcNavigateButtons.bottom -= 1;

	CRect rc(rcNavigateButtons);

	for (int i = pTabManager->GetNavigateButtonCount() - 1; i >= 0; i--)
		pTabManager->GetNavigateButton(i)->Reposition(rcNavigateButtons);

	if (rc == rcNavigateButtons) // No Buttons added
		return rcHeader;

	return rcNavigateButtons;
}

void CXTPTabPaintManager::RepositionTabControl(CXTPTabManager* pTabManager, CDC* pDC, CRect rcClient)
{
	pTabManager->m_rcHeaderRect.SetRectEmpty();
	pTabManager->m_rcClient = pTabManager->m_rcControl = rcClient;

	pTabManager->m_pRowIndexer->CreateIndexer(1);

	for (int i = 0; i < pTabManager->GetItemCount(); i++)
	{
		pTabManager->GetItem(i)->m_nItemRow = 0;
	}

	m_pAppearanceSet->RepositionTabControl(pTabManager, pDC, rcClient);
	AdjustClientRect(pTabManager, pTabManager->m_rcClient);
}



BOOL CXTPTabPaintManager::_CreateMultiRowIndexerBestFit(CXTPTabManager* pTabManager, int nWidth, int nRow, int nTotalLength)
{
	const int nRowCount = pTabManager->GetRowCount();
	const int nLengthPerRow = !m_bMultiRowJustified ? nWidth : min(nTotalLength / (nRowCount - nRow), nWidth);

	CXTPTabManager::ROW_ITEMS* pRowItems = pTabManager->m_pRowIndexer->GetRowItems();
	int x = 0;

	for (int i = pRowItems[nRow].nLastItem; i < pTabManager->GetItemCount(); i++)
	{
		CXTPTabManagerItem* pItem = pTabManager->GetItem(i);
		int nLength = pItem->GetButtonLength();

		if (x + nLength > nLengthPerRow && x != 0 && nLength > 0)
		{
			if (nRow == nRowCount - 1)
				return FALSE;

			pRowItems[nRow + 1].nFirstItem = pRowItems[nRow + 1].nLastItem = i;

			if (_CreateMultiRowIndexerBestFit(pTabManager, nWidth, nRow + 1, nTotalLength - x))
				return TRUE;

			if (x + nLength > nWidth)
				return FALSE;
		}
		pRowItems[nRow].nLastItem = i;
		pItem->m_nItemRow = nRow;
		x += nLength;
	}
	return TRUE;
}

void CXTPTabPaintManager::CreateMultiRowIndexer(CXTPTabManager* pTabManager, CDC* pDC, int nWidth)
{
	int x = 0;
	int nRowCount = 1;
	int i;
	int nTotalLength = 0;
	int nItemCount = pTabManager->GetItemCount();
	CXTPTabManagerItem* pSelectedItem = 0;

	for (i = 0; i < nItemCount; i++)
	{
		CXTPTabManagerItem* pItem = pTabManager->GetItem(i);

		if (pItem->IsSelected())
		{
			pSelectedItem = pItem;
		}

		int nLength = pItem->m_nContentLength = pItem->m_nButtonLength =
			pItem->IsVisible() ? m_pAppearanceSet->GetButtonLength(pDC, pItem) : 0;

		if (x + nLength > nWidth && x != 0)
		{
			x = 0;
			nRowCount++;
		}
		x += nLength;
		nTotalLength += nLength;
	}

	CXTPTabManager::ROW_ITEMS* pRowItems = pTabManager->m_pRowIndexer->CreateIndexer(nRowCount);

	if (nRowCount == 1)
		return;

	pRowItems[0].nFirstItem = pRowItems[0].nLastItem = 0;
	VERIFY(_CreateMultiRowIndexerBestFit(pTabManager, nWidth, 0, nTotalLength));

	if (!m_bMultiRowFixedSelection && pSelectedItem)
	{
		int nSelectedRow = pSelectedItem->GetItemRow();

		CXTPTabManager::ROW_ITEMS selectedRow = pRowItems[nSelectedRow];
		pRowItems[nSelectedRow] = pRowItems[0];
		pRowItems[0] = selectedRow;
	}
}

void CXTPTabPaintManager::RepositionTabControlMultiRow(CXTPTabManager* pTabManager, CDC* pDC, CRect rcClient)
{

	pTabManager->m_rcHeaderRect = RepositionNavigateButtons(pTabManager, rcClient);
	pTabManager->m_nHeaderOffset = 0;

	if (pTabManager->GetItemCount() == 0)
		return;

	CRect rcHeaderMargin = m_pAppearanceSet->GetHeaderMargin();
	int nButtonHeight = m_pAppearanceSet->GetButtonHeight(pTabManager);

	if (pTabManager->IsHorizontalPosition())
	{
		int nWidth = pTabManager->m_rcHeaderRect.Width() - (rcHeaderMargin.left + rcHeaderMargin.right);
		CreateMultiRowIndexer(pTabManager, pDC, nWidth);

		int nRowCount = pTabManager->GetRowCount();
		int nTop = 0;

		if (pTabManager->GetPosition() == xtpTabPositionBottom)
		{
			nTop = rcClient.bottom - (nButtonHeight * nRowCount + m_pAppearanceSet->m_nRowMargin * (nRowCount - 1))
				- rcHeaderMargin.top;
		}
		else
		{
			nTop = rcClient.top +  (nButtonHeight * (nRowCount - 1) + m_pAppearanceSet->m_nRowMargin * (nRowCount - 1))
				+ rcHeaderMargin.top;
		}

		int nBottom = nTop + nButtonHeight;

		int nOffset = pTabManager->GetPosition() == xtpTabPositionBottom ?
			nButtonHeight + m_pAppearanceSet->m_nRowMargin: -(nButtonHeight + m_pAppearanceSet->m_nRowMargin);


		CXTPTabManager::ROW_ITEMS* pRowItems = pTabManager->m_pRowIndexer->GetRowItems();
		int i;

		BOOL bSizeToFit = nRowCount > 1 && m_bMultiRowJustified;

		for (int nRow = 0; nRow < nRowCount; nRow++)
		{
			int nTotalLength = 0;

			int nItemInRow = pRowItems[nRow].nLastItem - pRowItems[nRow].nFirstItem + 1;
			int nFirstItem = pRowItems[nRow].nFirstItem;

			if (bSizeToFit)
			{
				for (i = 0; i < nItemInRow; i++)
				{
					nTotalLength += pTabManager->GetItem(nFirstItem + i)->GetButtonLength();
				}
			}

			int nTotalWidth = nWidth;

			int x = pTabManager->m_rcHeaderRect.left + rcHeaderMargin.left;

			for (i = 0; i < nItemInRow; i++)
			{
				CXTPTabManagerItem* pItem = pTabManager->GetItem(nFirstItem + i);
				ASSERT(pItem);
				if (!pItem)
					continue;
				int nButtonLength = pItem->m_nButtonLength;

				if (bSizeToFit)
				{
					int nLength = nButtonLength + (nTotalWidth - nTotalLength) / (nItemInRow - i);
					nTotalWidth -= nLength;
					nTotalLength -= nButtonLength;

					pItem->m_nButtonLength = nButtonLength = nLength;
				}

				pItem->SetRect(CRect(x, nTop, x + nButtonLength, nBottom));
				pItem->m_nItemRow = nRow;


				x += nButtonLength;
			}
			nTop += nOffset;
			nBottom += nOffset;
		}
	}
	else
	{
		int nWidth = pTabManager->m_rcHeaderRect.Height() - (rcHeaderMargin.left + rcHeaderMargin.right);
		CreateMultiRowIndexer(pTabManager, pDC, nWidth);


		int nRowCount = pTabManager->GetRowCount();
		int nLeft = 0;

		if (pTabManager->GetPosition() == xtpTabPositionRight)
		{
			nLeft = rcClient.right - (nButtonHeight * nRowCount + m_pAppearanceSet->m_nRowMargin * (nRowCount - 1))
				- rcHeaderMargin.top;
		}
		else
		{
			nLeft = rcClient.left +  (nButtonHeight * (nRowCount - 1) + m_pAppearanceSet->m_nRowMargin * (nRowCount - 1))
				+ rcHeaderMargin.top;
		}

		int nRight = nLeft + nButtonHeight;

		int nOffset = pTabManager->GetPosition() == xtpTabPositionRight ?
			nButtonHeight + m_pAppearanceSet->m_nRowMargin: -(nButtonHeight + m_pAppearanceSet->m_nRowMargin);


		CXTPTabManager::ROW_ITEMS* pRowItems = pTabManager->m_pRowIndexer->GetRowItems();
		int i;

		BOOL bSizeToFit = nRowCount > 1 && m_bMultiRowJustified;

		for (int nRow = 0; nRow < nRowCount; nRow++)
		{
			int nTotalLength = 0;

			int nItemInRow = pRowItems[nRow].nLastItem - pRowItems[nRow].nFirstItem + 1;
			int nFirstItem = pRowItems[nRow].nFirstItem;

			if (bSizeToFit)
			{
				for (i = 0; i < nItemInRow; i++)
				{
					nTotalLength += pTabManager->GetItem(nFirstItem + i)->GetButtonLength();
				}
			}

			int nTotalWidth = nWidth;

			int y = pTabManager->m_rcHeaderRect.top + rcHeaderMargin.left;

			for (i = 0; i < nItemInRow; i++)
			{
				CXTPTabManagerItem* pItem = pTabManager->GetItem(nFirstItem + i);
				ASSERT(pItem);
				if (!pItem)
					continue;
				int nButtonLength = pItem->m_nButtonLength;

				if (bSizeToFit)
				{
					int nLength = nButtonLength + (nTotalWidth - nTotalLength) / (nItemInRow - i);
					nTotalWidth -= nLength;
					nTotalLength -= nButtonLength;

					pItem->m_nButtonLength = nButtonLength = nLength;
				}

				pItem->SetRect(CRect(nLeft, y, nRight, y + nButtonLength));
				pItem->m_nItemRow = nRow;


				y += nButtonLength;
			}
			nLeft += nOffset;
			nRight += nOffset;
		}
	}
	pTabManager->m_rcHeaderRect = RepositionNavigateButtons(pTabManager, rcClient);
}

void CXTPTabPaintManager::RepositionTabControlEx(CXTPTabManager* pTabManager, CDC* pDC, CRect rcClient)
{
	if (pTabManager->IsDrawStaticFrame())
	{
		CXTPTabPaintManagerAppearanceSet::DeflateRectEx(rcClient, CRect(2, 1, 2, 2), pTabManager->GetPosition());
	}

	CXTPTabPaintManagerAppearanceSet::DeflateRectEx(rcClient, m_rcControlMargin, pTabManager->GetPosition());

	int i;

	if (!m_bShowTabs)
	{
		pTabManager->m_rcHeaderRect.SetRectEmpty();
		for (i = 0; i < pTabManager->GetItemCount(); i++)
		{
			CXTPTabManagerItem* pItem = pTabManager->GetItem(i);
			pItem->SetRect(CRect(0, 0, 0, 0));
		}

		for (i = pTabManager->GetNavigateButtonCount() - 1; i >= 0; i--)
			pTabManager->GetNavigateButton(i)->SetRect(CRect(0, 0, 0, 0));

		return;
	}
	if (pTabManager->GetLayout() == xtpTabLayoutMultiRow)
	{
		RepositionTabControlMultiRow(pTabManager, pDC, rcClient);
		return;
	}

	for (i = 0; i < pTabManager->GetItemCount(); i++)
	{
		CXTPTabManagerItem* pItem = pTabManager->GetItem(i);

		pItem->m_nButtonLength = pItem->m_nContentLength =
			pItem->IsVisible() ? m_pAppearanceSet->GetButtonLength(pDC, pItem) : 0;

		if (pItem->IsVisible())
			pItem->m_nButtonLength += m_nButtonExtraLength;
	}

	pTabManager->m_rcHeaderRect = m_pAppearanceSet->GetHeaderRect(rcClient, pTabManager);

	if (pTabManager->GetItemCount() == 0)
	{
		RepositionNavigateButtons(pTabManager, rcClient);
		return;
	}

	CRect rcHeaderMargin = m_pAppearanceSet->GetHeaderMargin();
	int nButtonHeight = m_pAppearanceSet->GetButtonHeight(pTabManager);


	if (pTabManager->IsHorizontalPosition())
	{
		int nTop = rcClient.top + rcHeaderMargin.top;

		if (pTabManager->GetPosition() == xtpTabPositionBottom)
		{
			nTop = rcClient.bottom - nButtonHeight - rcHeaderMargin.top;
		}

		int nBottom = nTop + nButtonHeight;


		if (pTabManager->GetLayout() == xtpTabLayoutSizeToFit)
		{
			int nWidth = rcClient.Width() - (rcHeaderMargin.right + rcHeaderMargin.left);

			for (i = pTabManager->GetNavigateButtonCount() - 1; i >= 0; i--)
				pTabManager->GetNavigateButton(i)->AdjustWidth(nWidth);

			SizeToFit(pTabManager, nWidth);
		}

		pTabManager->m_rcHeaderRect = RepositionNavigateButtons(pTabManager, rcClient);

		if (pTabManager->m_nHeaderOffset < 0)
		{
			int nLength = pTabManager->GetItemsLength();
			int nNavigateButtonsWidth = pTabManager->m_rcHeaderRect.Width() - rcHeaderMargin.left - rcHeaderMargin.right;

			if (nLength + pTabManager->m_nHeaderOffset < nNavigateButtonsWidth)
			{
				pTabManager->m_nHeaderOffset = min(0, nNavigateButtonsWidth - nLength);
				pTabManager->m_rcHeaderRect = RepositionNavigateButtons(pTabManager, rcClient);
			}
		}

		int x = pTabManager->m_rcHeaderRect.left + rcHeaderMargin.left + pTabManager->GetHeaderOffset();

		if (pTabManager->GetLayout() == xtpTabLayoutRotated)
		{
			if (pTabManager->GetPosition() == xtpTabPositionTop)
			{
				nBottom = pTabManager->m_rcHeaderRect.bottom - rcHeaderMargin.bottom;
			}
			else
			{
				nTop = pTabManager->m_rcHeaderRect.top + rcHeaderMargin.bottom;

			}

			for (i = 0; i < pTabManager->GetItemCount(); i++)
			{
				CXTPTabManagerItem* pItem = pTabManager->GetItem(i);
				if (!pItem->IsVisible()) continue;

				if (pTabManager->GetPosition() == xtpTabPositionTop)
				{
					pItem->SetRect(CRect(x, nBottom - pItem->m_nButtonLength, x + nButtonHeight, nBottom));
				}
				else
				{
					pItem->SetRect(CRect(x, nTop, x + nButtonHeight, nTop + pItem->m_nButtonLength));

				}
				x += nButtonHeight;
			}
		}
		else
		{

			for (i = 0; i < pTabManager->GetItemCount(); i++)
			{
				CXTPTabManagerItem* pItem = pTabManager->GetItem(i);

				pItem->SetRect(CRect(x, nTop, x + pItem->m_nButtonLength, nBottom));
				x += pItem->m_nButtonLength;
			}
		}

	}
	else
	{
		int nLeft = rcClient.left + rcHeaderMargin.top;

		if (pTabManager->GetPosition() == xtpTabPositionRight)
		{
			nLeft = rcClient.right - nButtonHeight - rcHeaderMargin.top;
		}

		int nRight = nLeft + nButtonHeight;

		if (pTabManager->GetLayout() == xtpTabLayoutSizeToFit)
		{
			int nWidth = rcClient.Height() - (rcHeaderMargin.right + rcHeaderMargin.left);

			for (i = pTabManager->GetNavigateButtonCount() - 1; i >= 0; i--)
				pTabManager->GetNavigateButton(i)->AdjustWidth(nWidth);

			SizeToFit(pTabManager, nWidth);
		}

		pTabManager->m_rcHeaderRect = RepositionNavigateButtons(pTabManager, rcClient);

		if (pTabManager->m_nHeaderOffset < 0)
		{
			int nLength = pTabManager->GetItemsLength();
			int nNavigateButtonsWidth = pTabManager->m_rcHeaderRect.Height() - rcHeaderMargin.left - rcHeaderMargin.right;

			if (nLength + pTabManager->m_nHeaderOffset < nNavigateButtonsWidth)
			{
				pTabManager->m_nHeaderOffset = min(0, nNavigateButtonsWidth - nLength);
				pTabManager->m_rcHeaderRect = RepositionNavigateButtons(pTabManager, rcClient);
			}
		}

		int y = pTabManager->m_rcHeaderRect.top + rcHeaderMargin.left + pTabManager->GetHeaderOffset();

		if (pTabManager->GetLayout() == xtpTabLayoutRotated)
		{
			if (pTabManager->GetPosition() == xtpTabPositionLeft)
			{
				nRight = pTabManager->m_rcHeaderRect.right - rcHeaderMargin.bottom;
			}
			else
			{
				nLeft = pTabManager->m_rcHeaderRect.left + rcHeaderMargin.bottom;

			}

			for (i = 0; i < pTabManager->GetItemCount(); i++)
			{
				CXTPTabManagerItem* pItem = pTabManager->GetItem(i);
				if (!pItem->IsVisible()) continue;

				if (pTabManager->GetPosition() == xtpTabPositionLeft)
				{
					pItem->SetRect(CRect(nRight - pItem->m_nButtonLength, y, nRight, y + nButtonHeight));
				}
				else
				{
					pItem->SetRect(CRect(nLeft, y, nLeft + pItem->m_nButtonLength, y + nButtonHeight));

				}
				y += nButtonHeight;
			}
		}
		else
		{
			for (i = 0; i < pTabManager->GetItemCount(); i++)
			{
				CXTPTabManagerItem* pItem = pTabManager->GetItem(i);

				pItem->SetRect(CRect(nLeft, y, nRight, y + pItem->m_nButtonLength));
				y += pItem->m_nButtonLength;
			}
		}
	}
}

void CXTPTabPaintManager::EnsureVisible(CXTPTabManager* pTabManager, CXTPTabManagerItem* pItem)
{
	CRect rcHeader = pTabManager->m_rcHeaderRect;
	CRect rcItem = pItem->GetRect();

	if (rcHeader.IsRectEmpty() || rcItem.IsRectEmpty())
		return;

	if (GetLayout() == xtpTabLayoutSizeToFit)
		return;

	if (pTabManager->IsHorizontalPosition())
	{
		if (rcItem.left < rcHeader.left)
		{
			pTabManager->SetHeaderOffset(pTabManager->GetHeaderOffset() - rcItem.left + rcHeader.left + m_pAppearanceSet->GetHeaderMargin().left);
		}
		else if (rcItem.right > rcHeader.right)
		{
			pTabManager->SetHeaderOffset(pTabManager->GetHeaderOffset() - rcItem.right + rcHeader.right - 2);
		}

	}
	else
	{
		if (rcItem.top < rcHeader.top)
		{
			pTabManager->SetHeaderOffset(pTabManager->GetHeaderOffset() - rcItem.top + rcHeader.top + m_pAppearanceSet->GetHeaderMargin().left);
		}
		else if (rcItem.bottom > rcHeader.bottom)
		{
			pTabManager->SetHeaderOffset(pTabManager->GetHeaderOffset() - rcItem.bottom + rcHeader.bottom - 2);
		}

	}

}

int _cdecl CXTPTabPaintManager::_SizeToFitCompare(const void *arg1, const void *arg2)
{
	int nLength1 = (*((CXTPTabManagerItem**)arg1))->GetButtonLength();
	int nLength2 = (*((CXTPTabManagerItem**)arg2))->GetButtonLength();

	return nLength1 - nLength2;
};

void CXTPTabPaintManager::SizeToFit(CXTPTabManager* pTabManager, int nWidth)
{
	int nLength = pTabManager->GetItemsLength();
	int nCount = pTabManager->GetItemCount();
	if (nCount == 0)
		return;

	if (nWidth < nLength)
	{
		if (nCount == 1)
			pTabManager->GetItem(0)->m_nButtonLength = nWidth;
		else
		{
			CXTPTabManagerItem** pItems = new CXTPTabManagerItem*[nCount];
			if (!pItems)
				return;

			for (int c = 0; c < nCount; c++)
			{
				pItems[c] = pTabManager->GetItem(c);
			}

			qsort(pItems, nCount, sizeof(CXTPTabManagerItem*), _SizeToFitCompare);

			for (int i = 0; i < nCount; i++)
			{
				int nButtonLength = pItems[i]->m_nButtonLength;

				if (nButtonLength * (nCount - i) >= nWidth)
				{
					for (int j = i; j < nCount; j++)
					{
						nButtonLength = nWidth / (nCount - j);
						pItems[j]->m_nButtonLength = nButtonLength;
						nWidth -= nButtonLength;
					}

					break;
				}

				nWidth -= nButtonLength;
			}

			delete[] pItems;
		}
	}
}

XTPTabAppearanceStyle CXTPTabPaintManager::GetAppearance() const
{
	return m_tabAppearance;
}

XTPTabColorStyle CXTPTabPaintManager::GetColor() const
{
	return m_tabColor;
}

void CXTPTabPaintManager::SetPosition(XTPTabPosition tabPosition)
{
	m_tabPosition = tabPosition;
	OnPropertyChanged();

}

void CXTPTabPaintManager::SetLayout(XTPTabLayoutStyle tabLayout)
{
	m_tabLayout = tabLayout;
	OnPropertyChanged();
}

XTPTabPosition CXTPTabPaintManager::GetPosition() const
{
	return m_tabPosition;
}

XTPTabLayoutStyle CXTPTabPaintManager::GetLayout() const
{
	return m_tabLayout;
}


void CXTPTabPaintManager::OnPropertyChanged()
{
	for (int i = 0; i < m_arrObservers.GetSize(); i++)
	{
		m_arrObservers[i]->OnPropertyChanged();
	}
}


void CXTPTabPaintManager::AddObserver(CXTPTabManagerAtom* pObserver)
{
	for (int i = 0; i < m_arrObservers.GetSize(); i++)
	{
		if (m_arrObservers[i] == pObserver)
			return;
	}
	m_arrObservers.Add(pObserver);
}

//////////////////////////////////////////////////////////////////////////