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