You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1439 lines
40 KiB
C++

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