// XTPDatePickerPaintManager.cpp: implementation of the CXTPDatePickerPaintManager class.
//
// This file is a part of the XTREME CALENDAR 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 "Resource.h"
#include "Common/XTPColorManager.h"
#include "Common/XTPDrawHelpers.h"
#include "Common/XTPResourceManager.h"
#include "Common/XTPResourceImage.h"
#include "Common/XTPWinThemeWrapper.h"

#include "XTPCalendarDefines.h"
#include "XTPCalendarUtils.h"

#include "XTPDatePickerPaintManager.h"
#include "XTPDatePickerControl.h"
#include "XTPDatePickerItemMonth.h"
#include "XTPDatePickerItemDay.h"

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

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CXTPDatePickerPaintManager::CXTPDatePickerPaintManager()
{
	m_bEnableTheme = TRUE;

	m_nPaintTheme = xtpCalendarThemeOffice2003;

	m_themeButton = new CXTPWinThemeWrapper();

	m_szDayMargin.cx = 6;
	m_szDayMargin.cy = 2;

	// initialize default fonts
	LOGFONT lfIcon;
	VERIFY(CXTPDrawHelpers::GetIconLogFont(&lfIcon));
	SetFontIndirect(&lfIcon);

	// init metrics
	RefreshMetrics();

	// init cursor
	m_hCursorBack = XTPResourceManager()->LoadCursor(XTP_IDC_DATEPICKER_BACKARROW);
	XTPResourceManager()->AssertValid(m_hCursorBack != 0);

}

void CXTPDatePickerPaintManager::SetFontIndirect(LOGFONT* lFont)
{
		// initialize default day item font
	m_fontDay.DeleteObject();
	VERIFY(m_fontDay.CreateFontIndirect(lFont));

	LOGFONT lfBold = *lFont;
	lfBold.lfWeight = FW_BOLD;
	m_fontDayBold.DeleteObject();
	VERIFY(m_fontDayBold.CreateFontIndirect(&lfBold));

	// initialize default non month day item font
	m_fontNonMonthDay.DeleteObject();
	VERIFY(m_fontNonMonthDay.CreateFontIndirect(lFont));
	// initialize default header font
	m_fontHeader.DeleteObject();
	VERIFY(m_fontHeader.CreateFontIndirect(lFont));
	// initialize default days of week font
	m_fontDaysOfWeek.DeleteObject();
	VERIFY(m_fontDaysOfWeek.CreateFontIndirect(lFont));
	// initialize default popup list control font
	m_fontListControl.DeleteObject();
	VERIFY(m_fontListControl.CreateFontIndirect(lFont));
	// initialize default button font
	m_fontButton.DeleteObject();
	VERIFY(m_fontButton.CreateFontIndirect(lFont));
	// initialize default week numbers font
	m_fontWeekNumbers.DeleteObject();
	lFont->lfHeight -= lFont->lfHeight / 3;
	VERIFY(m_fontWeekNumbers.CreateFontIndirect(lFont));
}


CXTPDatePickerPaintManager::~CXTPDatePickerPaintManager()
{
	//destructor

	SAFE_DELETE(m_themeButton);
}

void CXTPDatePickerPaintManager::RefreshMetrics()
{
	RefreshXtremeColors();

	// get system params
	m_clr3DLight = GetSysColor(COLOR_3DHILIGHT);
	m_clr3DText = GetSysColor(COLOR_BTNTEXT);
	m_clr3DShadow = GetSysColor(COLOR_3DSHADOW);
	m_clr3DFace = GetSysColor(COLOR_BTNFACE);

	m_clrButtonFace.SetStandardValue(m_clr3DFace);
	m_clrButtonText.SetStandardValue(m_clr3DText);


	// initialize default date picker paint manager settings
	m_clrControlBack.SetStandardValue(GetSysColor(COLOR_WINDOW));

	m_clrDayBack.SetStandardValue(m_clrControlBack);
	m_clrDayText.SetStandardValue(GetSysColor(COLOR_WINDOWTEXT));
	m_clrNonMonthDayBack.SetStandardValue(m_clrDayBack);

	m_clrSelectedDayBack.SetStandardValue(GetXtremeColor(XPCOLOR_HIGHLIGHT_CHECKED));
	m_clrSelectedDayText.SetStandardValue(m_clrDayText);

	m_clrStaticBorder = GetXtremeColor(XPCOLOR_STATICFRAME);

	m_clrMonthHeaderBack.SetStandardValue(m_clr3DFace);
	m_clrMonthHeaderText.SetStandardValue(m_clrDayText);
	m_clrDaysOfWeekBack.SetStandardValue(m_clrDayBack);
	m_clrDaysOfWeekText.SetStandardValue(m_clrDayText);
	m_clrWeekNumbersBack.SetStandardValue(m_clrDayBack);
	m_clrWeekNumbersText.SetStandardValue(m_clrDayText);

	m_clrListControlBack.SetStandardValue(GetSysColor(COLOR_WINDOW));
	m_clrListControlText.SetStandardValue(GetSysColor(COLOR_WINDOWTEXT));

	m_clrHighlightToday.SetStandardValue(GetSysColor(COLOR_HIGHLIGHT));


	m_clrNonMonthDayText.SetStandardValue(m_clr3DShadow);
	m_clrMonthBorder.SetStandardValue(m_clr3DShadow);

	m_clrMonthHeaderButton.SetStandardValue(m_clr3DText);

	m_themeButton->CloseTheme();

	BOOL bEnableTheme = m_bEnableTheme &&
						(GetPaintTheme() >= xtpCalendarThemeOffice2003);

	if (bEnableTheme && !XTPColorManager()->IsLunaColorsDisabled())
	{
		switch (XTPColorManager()->GetCurrentSystemTheme())
		{
			case xtpSystemThemeBlue:
			case xtpSystemThemeRoyale:
			case xtpSystemThemeAero:
				m_clrSelectedDayBack.SetStandardValue(RGB(0xFB, 0xE6, 0x94));
				m_clrHighlightToday.SetStandardValue(RGB(0xBB, 0x55, 0x03));
				m_clrMonthHeaderBack.SetStandardValue(RGB(0x9E, 0xBE, 0xF5));
				break;
			case xtpSystemThemeOlive:
				m_clrSelectedDayBack.SetStandardValue(RGB(251, 230, 148));
				m_clrHighlightToday.SetStandardValue(RGB(187, 85, 3));
				m_clrMonthHeaderBack.SetStandardValue(RGB(217, 217, 167));
				break;
			case xtpSystemThemeSilver:
				m_clrSelectedDayBack.SetStandardValue(RGB(251, 230, 148));
				m_clrHighlightToday.SetStandardValue(RGB(187, 85, 3));
				m_clrMonthHeaderBack.SetStandardValue(RGB(215, 215, 229));
				break;
		}
		m_themeButton->OpenTheme(0, L"BUTTON");
	}

	if (GetPaintTheme() < xtpCalendarThemeOffice2003)
	{
		m_clrSelectedDayBack.SetStandardValue(m_clr3DFace);
		m_clrSelectedDayText.SetStandardValue(m_clr3DText);
		m_clrHighlightToday.SetStandardValue(RGB(130, 0, 0));
	}
}

void CXTPDatePickerPaintManager::SetPaintTheme(XTPCalendarTheme ePaintTheme)
{
	m_nPaintTheme = ePaintTheme;
	RefreshMetrics();
}

void CXTPDatePickerPaintManager::DrawBackground(CDC* pDC, CRect rcClient)
{
	pDC->FillSolidRect(rcClient, GetControlBackColor());
}


void CXTPDatePickerPaintManager::DrawBorder(CDC* pDC, const CXTPDatePickerControl* pControl, CRect& rcClient, BOOL bDraw)
{
	XTPDatePickerBorderStyle borderStyle = pControl->GetBorderStyle ();
	BOOL bThemed = m_themeButton->IsAppThemed();

	if (bDraw)
	{
		if (borderStyle == xtpDatePickerBorder3D)
		{
			pDC->Draw3dRect(0, 0, rcClient.Width(), rcClient.Height(), m_clr3DFace, m_clr3DText);
			pDC->Draw3dRect(1, 1, rcClient.Width()-2, rcClient.Height()-2, m_clrControlBack, m_clr3DShadow);
			pDC->Draw3dRect(2, 2, rcClient.Width()-4, rcClient.Height()-4, m_clr3DFace, m_clr3DFace);
			pDC->Draw3dRect(3, 3, rcClient.Width()-6, rcClient.Height()-6, m_clr3DShadow, m_clrControlBack);
		}
		if ((borderStyle == xtpDatePickerBorderStatic) || (borderStyle == xtpDatePickerBorderOffice && bThemed))
		{
			pDC->Draw3dRect(0, 0, rcClient.Width(), rcClient.Height(), m_clrStaticBorder, m_clrStaticBorder);
		}
		if (borderStyle == xtpDatePickerBorderOffice && !bThemed)
		{
			pDC->Draw3dRect(0, 0, rcClient.Width(), rcClient.Height(), m_clr3DFace, m_clr3DText);
			pDC->Draw3dRect(1, 1, rcClient.Width()-2, rcClient.Height()-2, m_clrControlBack, m_clr3DShadow);
			pDC->Draw3dRect(2, 2, rcClient.Width()-4, rcClient.Height()-4, m_clr3DFace, m_clr3DFace);
		}
	}
	else
	{
		if (borderStyle == xtpDatePickerBorder3D)
		{
			rcClient.DeflateRect(4, 4, 4, 4);
		}
		if ((borderStyle == xtpDatePickerBorderStatic) || (borderStyle == xtpDatePickerBorderOffice && bThemed))
		{
			rcClient.DeflateRect(1, 1, 1, 1);
		}
		if (borderStyle == xtpDatePickerBorderOffice && !bThemed)
		{
			rcClient.DeflateRect(3, 3, 3, 3);
		}
	}
}

void CXTPDatePickerPaintManager::SetButtonFontIndirect(LOGFONT* lFont)
{
	m_fontButton.DeleteObject();
	m_fontButton.CreateFontIndirect(lFont);
}

void CXTPDatePickerPaintManager::SetButtonFont(CFont* fontButton)
{
	LOGFONT lFont;
	fontButton->GetLogFont(&lFont);
	SetButtonFontIndirect(&lFont);
}

void CXTPDatePickerPaintManager::Triangle(CDC* pDC, CPoint pt0, CPoint pt1, CPoint pt2, COLORREF clrColor)
{
	CXTPPenDC pen (*pDC, clrColor);
	CXTPBrushDC brush (*pDC, clrColor);

	CPoint pts[3];
	pts[0] = pt0;
	pts[1] = pt1;
	pts[2] = pt2;
	pDC->Polygon(pts, 3);
}

void CXTPDatePickerPaintManager::DrawScrollTriangle(CDC* pDC, CRect rcSpot, BOOL bLeftDirection,
													COLORREF clrColor, BOOL bYears)
{
	CPoint ptCenter(rcSpot.CenterPoint());

	if (bLeftDirection)
	{
		Triangle(pDC,
			ptCenter,
			CPoint(ptCenter.x + 4, ptCenter.y - 4),
			CPoint(ptCenter.x + 4, ptCenter.y + 4),
			clrColor);

		if (bYears)
		{
			Triangle(pDC,
				CPoint(ptCenter.x - 8, ptCenter.y),
				CPoint(ptCenter.x - 4, ptCenter.y - 4),
				CPoint(ptCenter.x - 4, ptCenter.y + 4),
				clrColor);

			Triangle(pDC,
				CPoint(ptCenter.x + 4, ptCenter.y),
				CPoint(ptCenter.x + 8, ptCenter.y - 4),
				CPoint(ptCenter.x + 8, ptCenter.y + 4),
				clrColor);

			//Triangle(pDC,
			//  CPoint(ptCenter.x + 2, ptCenter.y),
			//  CPoint(ptCenter.x + 3, ptCenter.y - 2),
			//  CPoint(ptCenter.x + 3, ptCenter.y + 2),
			//  RGB(255,255,255));
		}
	}
	else
	{
		Triangle(pDC,
			ptCenter,
			CPoint(ptCenter.x - 4, ptCenter.y - 4),
			CPoint(ptCenter.x - 4, ptCenter.y + 4),
			clrColor);

		if (bYears)
		{
			Triangle(pDC,
				CPoint(ptCenter.x + 8, ptCenter.y),
				CPoint(ptCenter.x + 4, ptCenter.y - 4),
				CPoint(ptCenter.x + 4, ptCenter.y + 4),
				clrColor);

			Triangle(pDC,
				CPoint(ptCenter.x - 4, ptCenter.y),
				CPoint(ptCenter.x - 8, ptCenter.y - 4),
				CPoint(ptCenter.x - 8, ptCenter.y + 4),
				clrColor);

			//Triangle(pDC,
			//  CPoint(ptCenter.x - 2, ptCenter.y),
			//  CPoint(ptCenter.x - 3, ptCenter.y - 2),
			//  CPoint(ptCenter.x - 3, ptCenter.y + 2),
			//  RGB(255,255,255));
		}
	}
}

void CXTPDatePickerPaintManager::DrawButton(CDC* pDC, const CRect& rcButton, const CString& strButton, BOOL bIsDown, BOOL bIsHighLight)
{
	pDC->SetBkMode(TRANSPARENT);

	CRect rcButtonX = rcButton;
	rcButtonX.DeflateRect(1, 1, 1, 1);

	BOOL bThemed = m_themeButton->IsAppThemed() &&
		GetPaintTheme() >= xtpCalendarThemeOffice2003;

	if (!bThemed)
	{
		pDC->FillSolidRect(rcButton, m_clrButtonFace);

		if (bIsDown)
		{
			pDC->Draw3dRect(rcButton, m_clr3DText, m_clrButtonFace);
			pDC->Draw3dRect(rcButtonX, m_clr3DShadow, m_clr3DLight);
		}
		else
		{
			pDC->Draw3dRect(rcButton, m_clrButtonFace, m_clr3DText);
			pDC->Draw3dRect(rcButtonX, m_clr3DLight, m_clr3DShadow);
		}
	}
	else
	{
		m_themeButton->DrawThemeBackground(pDC->GetSafeHdc(), BP_PUSHBUTTON,
			bIsDown ? PBS_PRESSED: bIsHighLight ? PBS_HOT : PBS_NORMAL,
			&rcButton, NULL);
	}

	if (!strButton.IsEmpty())
	{
		CXTPFontDC autoFont(pDC, &m_fontButton, m_clrButtonText);
		pDC->DrawText(strButton, rcButtonX, DT_VCENTER | DT_CENTER | DT_SINGLELINE);
	}
}

BOOL CXTPDatePickerPaintManager::DrawDay(CDC* pDC, CXTPDatePickerItemDay* pDay)
{
	if (!pDC || !pDay)
	{
		ASSERT(FALSE);
		return FALSE;
	}

	// check this day item
	BOOL bThisMonthItem = FALSE;
	BOOL bNextMonthItem = FALSE;
	BOOL bPreviousMonthItem = FALSE;

	CXTPDatePickerControl* pControl = pDay->GetDatePickerControl();
	CXTPDatePickerItemMonth* pMonth = pDay->GetMonth();

	COleDateTime dtDay = pDay->GetDate();
	CRect rcDay = pDay->GetRect();

	if (dtDay.GetYear() > pMonth->GetMonth().GetYear())
		bNextMonthItem = TRUE;
	else if (dtDay.GetYear() < pMonth->GetMonth().GetYear())
		bPreviousMonthItem = TRUE;
	else // years the same
	{
		if (dtDay.GetMonth() > pMonth->GetMonth().GetMonth())
			bNextMonthItem = TRUE;
		else if (dtDay.GetMonth() < pMonth->GetMonth().GetMonth())
			bPreviousMonthItem = TRUE;
		else // months the same
			bThisMonthItem = TRUE;
	}

	if (bPreviousMonthItem && !pMonth->GetShowDaysBefore())
		return FALSE;

	if (bNextMonthItem && !pMonth->GetShowDaysAfter())
		return FALSE;

	// set default drawing metrics depending on item month position
	XTP_DAYITEM_METRICS* pMetrics = new XTP_DAYITEM_METRICS;
	pMetrics->clrBackground = bThisMonthItem ?
		GetDayBackColor() : GetNonMonthDayBackColor();
	pMetrics->clrForeground = bThisMonthItem ?
		GetDayTextColor() : GetNonMonthDayTextColor();
	pMetrics->SetFont(bThisMonthItem ?
		GetDayTextFont() : GetNonMonthDayTextFont());

	// call callback function for changing parameters if needed
	pControl->GetDayMetrics(dtDay, pMetrics);

	// change default drawing metrics if day is selected
	if (pControl->IsSelected(dtDay))
	{
		pMetrics->clrBackground = GetSelectedDayBackColor();
		pMetrics->clrForeground = GetSelectedDayTextColor();
	}

	// apply settings to the DC
	pDC->SetBkMode(TRANSPARENT);
	pDC->SetTextColor(pMetrics->clrForeground);

	// fill background
	pDC->FillSolidRect(rcDay, pMetrics->clrBackground);

	// make a text for drawing
	CString strText;
	strText.Format(_T("%i"), dtDay.GetDay());

	// draw item content
	{
		// draw item text
		CXTPFontDC fntdc(pDC, pMetrics->GetFont());
		pDC->DrawText(strText, &rcDay, DT_SINGLELINE | DT_VCENTER | DT_CENTER | DT_NOCLIP);
	}

	CRect rcFocus = rcDay;
	BOOL bToday = FALSE;

	// highlight today item
	if (pControl->GetHighlightToday() && pDay->IsToday(dtDay))
	{
		pDC->Draw3dRect(rcDay, GetHighlightTodayColor(), GetHighlightTodayColor());
		bToday = TRUE;
	}

	if (pControl->IsFocused(dtDay) && pControl->GetSafeHwnd() == ::GetFocus())
	{
		if (!bToday)
		{
			pDC->SetTextColor(0);
			pDC->SetBkColor(RGB(255, 255, 255));
			pDC->DrawFocusRect(&rcFocus);
		}
		else
		{
			COLORREF clrFocus = GetHighlightTodayColor();
			clrFocus = clrFocus ^ RGB(255, 128, 128);

			rcFocus.DeflateRect(0, 0, 1, 1);

			CPen pen1(PS_DOT, 1, clrFocus);
			CXTPPenDC autoPen(pDC, &pen1);

			pDC->MoveTo(rcFocus.TopLeft());
			pDC->LineTo(rcFocus.right, rcFocus.top);
			pDC->LineTo(rcFocus.right, rcFocus.bottom);
			pDC->LineTo(rcFocus.left, rcFocus.bottom);
			pDC->LineTo(rcFocus.left, rcFocus.top);
		}
	}

	pMetrics->InternalRelease();

	return TRUE;
}

void CXTPDatePickerPaintManager::DrawMonthHeader(CDC* pDC, CXTPDatePickerItemMonth* pMonth)
{
	if (pMonth->m_rcHeader.IsRectEmpty())
		return;

	CXTPDatePickerControl* pControl = pMonth->m_pControl;

	COleDateTime dtMonth = pMonth->GetMonth();
	CRect rcHeader = pMonth->m_rcHeader;
	CRect rcLeftScroll = pMonth->m_rcLeftScroll;
	CRect rcRightScroll = pMonth->m_rcRightScroll;

	CXTPClientRect rcClient(pControl);
	DrawBorder(pDC, pControl, rcClient, FALSE);

	CRect rcHeaderBk = pMonth->m_rcMonth;
	rcHeaderBk.bottom = rcHeader.bottom;

	// fill background
	if (GetPaintTheme() != xtpCalendarThemeOffice2000)
	{
		pDC->FillSolidRect(rcHeaderBk, GetMonthHeaderBackColor());
	}
	else
	{
		int nVertDiv = 0;

		if (pMonth->m_nColumn == 0)
			rcHeaderBk.left = rcClient.left + 1;

		if (pMonth->m_nColumn == pControl->GetCols() - 1)
		{
			rcHeaderBk.right = rcClient.right;
			nVertDiv = 2;
		}
		else
		{
			rcHeaderBk.right += 2;
			nVertDiv = 1;
		}

		pDC->FillSolidRect(rcHeaderBk, GetMonthHeaderBackColor());

		pDC->FillSolidRect(rcHeaderBk.left - 1, rcHeaderBk.bottom-1, rcHeaderBk.Width()+1, 1, m_clr3DShadow);

		if (nVertDiv == 1)
		{
			CRect rcDiv = rcHeaderBk;
			rcDiv.DeflateRect(0, 1, 3, 2);
			rcDiv.left = rcDiv.right - 1;
			pDC->FillSolidRect(rcDiv, m_clr3DShadow);

			rcDiv.left++;
			rcDiv.right++;
			pDC->FillSolidRect(rcDiv, m_clrControlBack);
		}

		else if (nVertDiv == 2)
		{
			CRect rcDiv = rcHeaderBk;
			rcDiv.left = rcDiv.right - 1;
			rcDiv.top--;
			pDC->FillSolidRect(rcDiv, m_clr3DShadow);
		}
	}

	// draw header text
	pDC->SetBkColor(GetMonthHeaderBackColor());
	pDC->SetTextColor(GetMonthHeaderTextColor());

	CXTPFontDC fnt(pDC, GetHeaderTextFont());

	CString strText;

	if (!pControl->m_strYearMonthFormat.IsEmpty())
	{
		strText = CXTPCalendarUtils::GetDateFormat(dtMonth, pControl->m_strYearMonthFormat);
	}
	else
	{
		strText.Format(_T("%s %d"), (LPCTSTR)pControl->GetMonthName( dtMonth.GetMonth()), dtMonth.GetYear());
	}

	pDC->DrawText(strText, &rcHeader, DT_SINGLELINE | DT_VCENTER | DT_CENTER);

	// draw left scroll triangle
	if (!rcLeftScroll.IsRectEmpty())
	{
		// draw left triangle itself
		if (pMonth->GetShowLeftScroll())
			DrawScrollTriangle(pDC, rcLeftScroll, TRUE,
			m_clrMonthHeaderButton,
			pControl->m_bYearsTriangle);
	}

	// draw right scroll triangle
	if (!rcRightScroll.IsRectEmpty())
	{
		// draw right triangle itself
		if (pMonth->GetShowRightScroll())
			DrawScrollTriangle(pDC, rcRightScroll, FALSE,
			m_clrMonthHeaderButton,
			pControl->m_bYearsTriangle);
	}
}

void CXTPDatePickerPaintManager::DrawDaysOfWeek(CDC* pDC, CXTPDatePickerItemMonth* pMonth)
{
	if (pMonth->m_rcDaysOfWeek.IsRectEmpty())
		return;

	CXTPDatePickerControl* pControl = pMonth->m_pControl;

	// fill background
	pDC->FillSolidRect(pMonth->m_rcDaysOfWeek, GetDaysOfWeekBackColor());

	// draw days of week text
	pDC->SetBkColor(GetDaysOfWeekBackColor());
	pDC->SetTextColor(GetDaysOfWeekTextColor());
	CXTPFontDC fnt(pDC, GetDaysOfWeekTextFont());
	int nMaxX = 0;

	int nTwoLetterWidth = pDC->GetTextExtent(_T("XX"), 2).cx;
	int nWholeLetterWidth = 0;

	for (int i = 0; i < XTP_WEEK_DAYS; i++)
	{
		CString strText(pControl->GetDayOfWeekName(i));
		nWholeLetterWidth = max(nWholeLetterWidth, pDC->GetTextExtent(strText).cx);
	}

	for (int nDayDelta = 0; nDayDelta < XTP_WEEK_DAYS; nDayDelta++)
	{
		// calc item rect
		CXTPDatePickerItemDay* pDay = pMonth->GetDay(nDayDelta);
		CRect rcItem(pDay->GetRect());
		rcItem.top = pMonth->m_rcDaysOfWeek.top;
		rcItem.bottom = pMonth->m_rcDaysOfWeek.bottom - 2;
		nMaxX = rcItem.right;
		// get item text
		CString strText(pControl->GetDayOfWeekName(pDay->GetDate().GetDayOfWeek()));

		// Check if we can draw whole text
		if (nWholeLetterWidth + 4 <= rcItem.Width())
		{
			pDC->DrawText(strText, &rcItem, DT_SINGLELINE | DT_VCENTER | DT_CENTER);
		}
		else if (nTwoLetterWidth + 4 <= rcItem.Width()) // Draw 2 letters
		{
			int nChrLen = (int)_tcsnbcnt(strText, 2);
			pDC->DrawText(strText, nChrLen, &rcItem, DT_SINGLELINE | DT_VCENTER | DT_CENTER);
		}
		else // Draw only first letter
		{
			int nChrLen = (int)_tcsnbcnt(strText, 1);
			pDC->DrawText(strText, nChrLen, &rcItem, DT_SINGLELINE | DT_VCENTER | DT_CENTER);
		}
	}

	// draw bottom line on days of the week
	CRect rcBottomLine(pMonth->m_rcDaysOfWeek);
	rcBottomLine.bottom--;
	rcBottomLine.top = rcBottomLine.bottom - 1;
	rcBottomLine.left = pMonth->m_rcWeekNumbers.right - 1;
	rcBottomLine.right = nMaxX;
	pDC->FillSolidRect(rcBottomLine, m_clrMonthBorder);
}

void CXTPDatePickerPaintManager::DrawWeekNumbers(CDC* pDC, CXTPDatePickerItemMonth* pMonth)
{
	CXTPDatePickerControl* pControl = pMonth->m_pControl;

	if (!pControl->GetShowWeekNumbers() || pMonth->m_rcWeekNumbers.IsRectEmpty())
		return;

	// fill background
	pDC->FillSolidRect(pMonth->m_rcWeekNumbers, GetWeekNumbersBackColor());

	// draw week numbers
	pDC->SetBkColor(GetWeekNumbersBackColor());
	pDC->SetTextColor(GetWeekNumbersTextColor());
	CXTPFontDC fnt(pDC, GetWeekNumbersTextFont());

	// draw right line on week days
	CRect rcLine(pMonth->m_rcWeekNumbers);

	for (int nWeek = 0; nWeek < XTP_MAX_WEEKS; nWeek++)
	{
		// calculate item rectangle (get week middle day)
		CXTPDatePickerItemDay* pDayFirst = pMonth->GetDay(nWeek * XTP_WEEK_DAYS);
		CXTPDatePickerItemDay* pDayLast = pMonth->GetDay((nWeek + 1) * XTP_WEEK_DAYS - 1);

		if (pDayFirst && (pDayFirst->IsVisible() || nWeek < 4) && pDayLast)
		{
			CRect rcItem(pDayFirst->GetRect());
			rcItem.left = pMonth->m_rcWeekNumbers.left;
			rcItem.right = pMonth->m_rcWeekNumbers.right - 3;
			// get item text
			CString strText;
			int nWeekNumber = ((pDayLast->GetDate() - COleDateTimeSpan(pControl->GetFirstWeekOfYearDays() - 1)).GetDayOfYear() - 1) / 7 + 1;
			strText.Format(_T("%d"), nWeekNumber);
			pDC->DrawText(strText, &rcItem, DT_SINGLELINE | DT_VCENTER | DT_RIGHT);

			rcLine.bottom = rcItem.bottom;
		}
	}

	pDC->FillSolidRect(rcLine.right - 1, rcLine.top - 1, 1, rcLine.Height(), m_clrMonthBorder);
}

CSize CXTPDatePickerPaintManager::CalcDayRect(CDC* pDC)
{
	CFont* fontOld = pDC->SelectObject(&m_fontDay);
	CSize szDay = pDC->GetTextExtent(_T("30"), 2);
	szDay.cx += m_szDayMargin.cx;
	szDay.cy += m_szDayMargin.cy;
	pDC->SelectObject(fontOld);

	return szDay;
}

CSize CXTPDatePickerPaintManager::CalcMonthHeaderRect(CDC* pDC)
{
	CFont* fontOld = pDC->SelectObject(&m_fontHeader);
	CSize szHeader = pDC->GetTextExtent(_T(" "), 1);
	szHeader.cy += 4;
	pDC->SelectObject(fontOld);
	return szHeader;
}

CSize CXTPDatePickerPaintManager::CalcDayOfWeekRect(CDC* pDC)
{
	CFont* fontOld = pDC->SelectObject(&m_fontDaysOfWeek);
	CSize szWeekText = pDC->GetTextExtent(_T(" "), 1);
	szWeekText.cy += 5;
	pDC->SelectObject(fontOld);
	return szWeekText;
}

CSize CXTPDatePickerPaintManager::CalcWeekNumbersRect(CDC* pDC)
{
	CFont* fontOld = pDC->SelectObject(&m_fontWeekNumbers);
	CSize szWeekNumber = pDC->GetTextExtent(_T("88"), 2);
	szWeekNumber.cx += 8;
	pDC->SelectObject(fontOld);
	return szWeekNumber;
}

CSize CXTPDatePickerPaintManager::CalcMonthRect(CDC* pDC)
{
	CSize szDay(CalcDayRect(pDC));
	CSize szHeader(CalcMonthHeaderRect(pDC));
	CSize szWeekText(CalcDayOfWeekRect(pDC));
	CSize szWeekNumber(CalcWeekNumbersRect(pDC));

	CSize szMonth(0, 0);
	szMonth.cx = (szDay.cx * 7 + szWeekNumber.cx * 2);
	szMonth.cy = (szDay.cy * 6 + szWeekText.cy + szHeader.cy);

	return szMonth;
}


CXTPDatePickerThemeOffice2007::CXTPDatePickerThemeOffice2007()
{
	m_nPaintTheme = xtpCalendarThemeResource;

}

CXTPDatePickerThemeOffice2007::~CXTPDatePickerThemeOffice2007()
{
}

void CXTPDatePickerThemeOffice2007::RefreshMetrics()
{
	CXTPDatePickerPaintManager::RefreshMetrics();

	m_clrMonthBorder.SetStandardValue(GetResourceColor(_T("MonthBorder"), RGB(154, 198,255)));
	m_clrMonthHeaderBack.SetStandardValue(GetResourceColor(_T("MonthHeaderBack"), RGB(191, 219, 255)));
	m_clrMonthHeaderText.SetStandardValue(GetResourceColor(_T("MonthHeaderText"), RGB(0, 0, 0)));
	m_clrMonthHeaderButton.SetStandardValue(GetResourceColor(_T("MonthHeaderButton"), RGB(111, 157, 217)));

	m_clrControlBack.SetStandardValue(GetResourceColor(_T("ControlBack"), RGB(255, 255, 255)));

	m_clrHighlightToday.SetStandardValue(GetResourceColor(_T("HighlightToday"), RGB(187, 85, 3)));

	m_clrDayBack.SetStandardValue(m_clrControlBack);
	m_clrDayText.SetStandardValue(GetResourceColor(_T("DayText"), RGB(0, 0, 0)));

	m_clrSelectedDayBack.SetStandardValue(GetResourceColor(_T("SelectedDayBack"), RGB(251, 200, 79)));
	m_clrSelectedDayText.SetStandardValue(GetResourceColor(_T("SelectedDayText"), m_clrDayText));

	m_clrNonMonthDayBack.SetStandardValue(m_clrDayBack);
	m_clrNonMonthDayText.SetStandardValue(GetResourceColor(_T("NonMonthDayText"), m_clr3DShadow));

	m_clrDaysOfWeekBack.SetStandardValue(m_clrDayBack);
	m_clrDaysOfWeekText.SetStandardValue(m_clrDayText);

	m_clrWeekNumbersBack.SetStandardValue(m_clrDayBack);
	m_clrWeekNumbersText.SetStandardValue(m_clrDayText);

	m_clrButtonText.SetStandardValue(RGB(0, 0, 0));
}

void CXTPDatePickerThemeOffice2007::DrawButton(CDC* pDC, const CRect& rcButton, const CString& strButton, BOOL bIsDown, BOOL bIsHighLight)
{
	CXTPResourceImage* pImage = XTPResourceImages()->LoadFile(_T("PUSHBUTTON"));
	if (!pImage)
	{
		CXTPDatePickerPaintManager::DrawButton(pDC, rcButton, strButton, bIsDown, bIsHighLight);
		return;
	}

	pImage->DrawImage(pDC, rcButton, pImage->GetSource(bIsDown ? 2 : bIsHighLight ? 1 : 0, 5), CRect(4, 4, 4, 4), 0xFF00FF);

	pDC->SetBkMode(TRANSPARENT);

	if (!strButton.IsEmpty())
	{
		CXTPFontDC autoFont(pDC, &m_fontButton, m_clrButtonText);

		CRect rcText(rcButton);
		rcText.DeflateRect(1, 1);

		pDC->DrawText(strButton, rcText, DT_VCENTER | DT_CENTER | DT_SINGLELINE);
	}
}



COLORREF CXTPDatePickerThemeOffice2007::GetResourceColor(LPCTSTR pcszColorName, COLORREF clrDefault)
{
	if (this == NULL)
		return clrDefault;

	COLORREF clrColor = COLORREF_NULL;

	CXTPResourceImages* pImages = XTPResourceImages();

	if (pImages->IsValid())
	{
		clrColor = pImages->GetImageColor(_T("DatePicker"), pcszColorName);
	}

	if (clrColor == COLORREF_NULL)
	{
		clrColor = clrDefault;
	}

	return clrColor;
}