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.

3287 lines
88 KiB
C++

// XTPCalendarDayView.cpp: implementation of the CXTPCalendarDayView 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 "Common/XTPDrawHelpers.h"
#include "Common/XTPSmartPtrInternalT.h"
#include "Common/XTPNotifyConnection.h"
#include "Common/XTPColorManager.h"
#include "Resource.h"
#include "XTPCalendarDefines.h"
#include "XTPCalendarOptions.h"
#include "XTPCalendarUtils.h"
#include "XTPCalendarNotifications.h"
#include "XTPCalendarPtrCollectionT.h"
#include "XTPCalendarTimeZoneHelper.h"
#include "XTPCalendarEvent.h"
#include "XTPCalendarResource.h"
#include "XTPCalendarData.h"
#include "XTPCalendarView.h"
#include "XTPCalendarViewDay.h"
#include "XTPCalendarViewEvent.h"
#include "XTPCalendarViewPart.h"
#include "XTPCalendarDayViewEvent.h"
#include "XTPCalendarDayViewDay.h"
#include "XTPCalendarDayView.h"
#include "XTPCalendarDayViewTimeScale.h"
#include "XTPCalendarPaintManager.h"
#include "XTPCalendarTheme.h"
#include "XTPCalendarThemeOffice2007.h"
#include "XTPCalendarControl.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#define new DEBUG_NEW
#endif
#define XTP_SCROLL_TIMER_RESOLUTION_MS 30
#define XTP_REDRAW_TIMER_RESOLUTION_MS 2000
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
IMPLEMENT_DYNAMIC(CXTPCalendarDayView, CXTPCalendarView)
CXTPCalendarDayView::CXTPCalendarDayView(CXTPCalendarControl* pCalendarControl) :
TBase(pCalendarControl, xtpCalendarDayView),
m_ptLastMousePos(0, 0)
{
m_pTimeScaleHeader = new CXTPCalendarDayViewTimeScale(this);
m_pTimeScaleHeader2 = new CXTPCalendarDayViewTimeScale(this, FALSE, FALSE);
m_LayoutX.m_nRowCount = 0;
m_LayoutX.m_nVisibleRowCount = 0;
m_LayoutX.m_nTopRow = 0;
m_LayoutX.m_nTopAllDayRow = 0;
m_LayoutX.m_nVisibleAllDayCount = 0;
m_LayoutX.m_rcAllDayEvents.SetRectEmpty();
m_LayoutX.m_rcDayHeader.SetRectEmpty();
m_LayoutX.m_nAllDayEventsCountMax = 0;
m_LayoutX.m_nAllDayEventHeight = 0;
m_nAllDayEventsCountMin_WhenDrag = 0;
m_spDraggingStartOffset_Time = 0.;
m_bShowAllDayEventsOnly = FALSE;
m_bHideAllDayEventsArea = FALSE;
m_nScrollOffsetX = 0;
m_nMinColumnWidth = -1;
// 0 - means disabled; -1 use auto for multiresources; -X use for multiresources only; +X used always (in single and multi resources mode).
// add today to the day view by default
COleDateTime dtNow(CXTPCalendarUtils::GetCurrentTime());
m_arDays.Add(new CXTPCalendarDayViewDay(this, dtNow));
// go to the beginning of the work day
int nHour = 0, nMin = 0, nSec = 0;
XTP_SAFE_CALL1(m_pControl, GetWorkDayStartTime(nHour, nMin, nSec));
int nPos = GetCellNumber(nHour, nMin, nSec, FALSE);
_ScrollV(nPos, nPos);
m_dwScrollingEventTimerID = 0;
m_dwScrollingEventTimerHorID = 0;
m_bMouseOutOfDragArea = FALSE;
m_dtDraggingStartPoint = COleDateTime(0, 0, 0, 0, 0, 0);
m_dtTimeScaleMin.SetTime(0, 0, 0);
m_dtTimeScaleMax.SetTime(23, 59, 59);
//m_bEcoMode = FALSE;
m_bEcoAllDayMode = FALSE;
m_bPreventDragAllDayEventInDayView = FALSE;
m_bDraftMode = FALSE;
m_bPrintRepeatHeaderFooterMode = FALSE;
//m_bPrintRepeatHeaderFooterMode = TRUE;
m_bDF_mode = FALSE;
m_bPrintFullScale = TRUE;
m_nDayHeaderPeriod = 1;
m_nDayViewPrintInterval = 60;
m_nCurPage = 0;
m_bUseNewHitTestCode = TRUE;
m_bShowLinks = FALSE;
m_bHideLinkContainer = FALSE;
m_dwRedrawNowLineTimerID = 0;
m_dtLastRedrawTime = CXTPCalendarUtils::GetCurrentTime();
}
CXTPCalendarDayView::~CXTPCalendarDayView()
{
CMDTARGET_RELEASE(m_pTimeScaleHeader);
CMDTARGET_RELEASE(m_pTimeScaleHeader2);
ClearDays();
}
void CXTPCalendarDayView::SetIsHideAllDayEventsArea(BOOL bHide)
{
CXTPCalendarControl::CUpdateContext updateContext2(GetCalendarControl(), xtpCalendarUpdateRedraw | xtpCalendarUpdateLayout);
m_bHideAllDayEventsArea = bHide;
}
XTPCalendarViewType CXTPCalendarDayView::GetViewType() const
{
// int nWWMask = m_pControl ? m_pControl->GetWorkWeekMask() : xtpCalendarDayMo_Fr;
int nWWMask = xtpCalendarDayMo_Fr; //Default 62 as 2 + 4 + 8 + 16 + 32
if (m_pControl)
nWWMask = m_pControl->GetWorkWeekMask();
int nDaysCount = GetViewDayCount();
int nWWCount = CXTPCalendarUtils::GetDayOfWeekCount(nWWMask);
if (nDaysCount != nWWCount && nDaysCount != 7)
return xtpCalendarDayView;
int nFirstDayOfWeek = xtpCalendarDayMonday; //Default 2
if (m_pControl)
nFirstDayOfWeek = m_pControl->GetFirstDayOfWeek();
int nNextWWeekIdx = nFirstDayOfWeek;
//Dennis Volodomanov Issue #: 18604
//the first call returns a 7 (for example, for a Saturday)
//and then this 7 is passed into the function that expects a bitmask.
BOOL bWDOrderFull = TRUE;
int nViewType = xtpCalendarWorkWeekView;
for (int i = 0; i < nDaysCount; i++)
{
COleDateTime dtDay = GetViewDayDate(i);
int nDayOfWeek = dtDay.GetDayOfWeek();
int nDayMask = CXTPCalendarUtils::GetDayOfWeekMask(nDayOfWeek);
if ((nWWMask & nDayMask) == 0)
nViewType = xtpCalendarDayView;
if (nNextWWeekIdx != nDayOfWeek)
bWDOrderFull = FALSE;
nNextWWeekIdx = (nNextWWeekIdx % 7) + 1;
}
if (nDaysCount == 7 && bWDOrderFull)
nViewType = xtpCalendarFullWeekView;
return (XTPCalendarViewType)nViewType;
}
void CXTPCalendarDayView::ClearDays()
{
m_arDays.RemoveAll();
}
COleDateTime CXTPCalendarDayView::GetCellTime(int nCell) const
{
double dblTime = (long)nCell * (double)GetCellDuration();
COleDateTime dtCellTime(m_dtTimeScaleMin);
dtCellTime += (DATE)dblTime;
return dtCellTime;
}
COleDateTimeSpan CXTPCalendarDayView::GetCellDuration() const
{
return m_pTimeScaleHeader ? m_pTimeScaleHeader->GetScaleInterval() : (double) 0;
}
int CXTPCalendarDayView::GetCellNumber(COleDateTime dtTime, BOOL bForEndTime) const
{
double dblTime = (double) GetDateTimeTime(dtTime) - m_dtTimeScaleMin;
//dblTime += (double) COleDateTimeSpan(0,0,0,1);
double dblEpsilon = XTP_HALF_SECOND * (bForEndTime ? -1 : 1);
//double dblEpsilon = .5 * (bForEndTime ? -1 : 1);
double dblCellDur = (double) GetCellDuration();
if (dblCellDur <= XTP_HALF_SECOND)
dblCellDur = XTP_HALF_SECOND * 2 * 60 * 30; //30min if too small
double dCell = dblTime / dblCellDur + dblEpsilon;
int nCell = int (dCell);
return nCell;
}
int CXTPCalendarDayView::GetCellNumber(int nHour, int nMin, int nSec, BOOL bForEndTime) const
{
COleDateTime dtTime;
dtTime.SetTime(nHour, nMin, nSec);
return GetCellNumber(dtTime, bForEndTime);
}
void CXTPCalendarDayView::ScrollV(int nIndex, int nPos_raw)
{
if (m_bScrollV_Disabled)
return;
_ScrollV(nIndex, nPos_raw);
}
void CXTPCalendarDayView::_ScrollV(int nIndex, int /*nPos_raw*/)
{
if (m_bShowAllDayEventsOnly)
{
if (nIndex + m_LayoutX.m_nVisibleAllDayCount >= m_LayoutX.m_nAllDayEventsCountMax)
nIndex = m_LayoutX.m_nAllDayEventsCountMax - m_LayoutX.m_nVisibleAllDayCount;
if (nIndex < 0)
nIndex = 0;
m_LayoutX.m_nTopAllDayRow = nIndex;
}
else
{
if (nIndex + m_LayoutX.m_nVisibleRowCount >= m_LayoutX.m_nRowCount)
nIndex = m_LayoutX.m_nRowCount - m_LayoutX.m_nVisibleRowCount;
if (nIndex == m_LayoutX.m_nTopRow)
return;
m_LayoutX.m_nTopRow = nIndex;
}
}
void CXTPCalendarDayView::ScrollH(int nPos, int nPos_raw)
{
SCROLLINFO si;
if (!GetScrollBarInfoH(&si))
m_nScrollOffsetX = 0;
int nXmax = si.nMax - si.nPage + 1;
m_nScrollOffsetX = min(max(nPos, si.nMin), nXmax);
if (!m_bScrollH_Disabled)
{
if (RecalcMinColumnWidth() > 0)
{
RedrawControl();
}
else
{
if (nPos_raw < 0)
ScrollDaysToPrev();
else if (nPos_raw > nXmax)
ScrollDaysToNext();
}
}
}
BOOL CXTPCalendarDayView::GetScrollBarInfoV(SCROLLINFO* pSI) const
{
ASSERT(pSI);
if (!pSI || m_bScrollV_Disabled)
return FALSE;
if (m_bShowAllDayEventsOnly)
{
pSI->nPos = m_LayoutX.m_nTopAllDayRow;
pSI->nMax = m_LayoutX.m_nAllDayEventsCountMax - 1;
pSI->nPage = m_LayoutX.m_nVisibleAllDayCount;
return m_LayoutX.m_nVisibleAllDayCount < m_LayoutX.m_nAllDayEventsCountMax;
}
else
{
pSI->nPos = m_LayoutX.m_nTopRow;
pSI->nMax = m_LayoutX.m_nRowCount - 1;
pSI->nPage = m_LayoutX.m_nVisibleRowCount;
return m_LayoutX.m_nVisibleRowCount != m_LayoutX.m_nRowCount;
}
}
BOOL CXTPCalendarDayView::GetScrollBarInfoH(SCROLLINFO* pSI, int* pnScrollStep) const
{
UNREFERENCED_PARAMETER(pnScrollStep);
ASSERT(pSI);
if (!pSI)
return FALSE;
int nMinColumnWidth = RecalcMinColumnWidth();
if (nMinColumnWidth <= 0)
return FALSE;
CRect rcClient = _GetScrollRectClient();
int nColumnsCount = GetTotalGroupsCount();
int nFullWidth = nColumnsCount * nMinColumnWidth;
if (nFullWidth <= rcClient.Width())
return FALSE;
pSI->nPos = min(m_nScrollOffsetX, nFullWidth);
pSI->nMin = 0;
pSI->nMax = nFullWidth;
pSI->nPage = rcClient.Width();
return TRUE;
}
int CXTPCalendarDayView::GetTotalGroupsCount() const
{
int nGroupsCount = 0;
int nDays = GetViewDayCount();
for (int i = 0; i < nDays; i++)
{
CXTPCalendarDayViewDay* pDay = GetViewDay(i);
ASSERT(pDay);
if (pDay)
nGroupsCount += pDay->GetViewGroupsCount();
}
return nGroupsCount;
}
int CXTPCalendarDayView::RecalcMinColumnWidth() const
{
int nMinColumnWidth = m_nMinColumnWidth;
if (nMinColumnWidth < 0)
{
// automatically use horizontal scrolling for multi-resources mode
if (GetResources() && GetResources()->GetCount() <= 1)
return -1;
if (nMinColumnWidth == -1)
nMinColumnWidth = ::GetSystemMetrics(SM_CXFULLSCREEN) / 8;
// nMinColumnWidth = ::GetSystemMetrics(SM_CXFULLSCREEN) / 6;
//in average screen case this setting allows to see 6 columns
//(2 days with 3 schedules in day) without scrolling
else
nMinColumnWidth = abs(nMinColumnWidth);
}
return nMinColumnWidth;
}
int CXTPCalendarDayView::GetAllDayEventsMaxCount() const
{
int nAllDayMax = 0;
int nCount = GetViewDayCount();
for (int i = 0; i < nCount; i++)
{
CXTPCalendarDayViewDay* pViewDay = GetViewDay(i);
ASSERT(pViewDay);
if (!pViewDay)
continue;
int nGroupsCount = pViewDay->GetViewGroupsCount();
for (int g = 0; g < nGroupsCount; g++)
{
int nAllDay = 0;
CXTPCalendarDayViewGroup* pViewGroup = pViewDay->GetViewGroup(g);
ASSERT(pViewGroup);
if (!pViewGroup)
{
continue;
}
int nECount = pViewGroup->GetViewEventsCount();
for (int j = 0; j < nECount; j++)
{
CXTPCalendarDayViewEvent* pViewEvent = pViewGroup->GetViewEvent(j);
ASSERT(pViewEvent);
if (pViewEvent && pViewEvent->IsMultidayEvent())
{
nAllDay++;
}
}
nAllDayMax = max(nAllDayMax, nAllDay);
}
}
return nAllDayMax;
}
void CXTPCalendarDayView::AdjustAllDayEvents()
{
if (GetResources() && GetResources()->GetCount() > 1)
return;
int nDaysCount = GetViewDayCount();
for (int nDayIdx = 0; nDayIdx < nDaysCount; nDayIdx++)
{
CXTPCalendarDayViewDay* pViewDay = GetViewDay(nDayIdx);
if (!pViewDay)
{
ASSERT(FALSE);
continue;
}
// go through all days to look for multiday events
int nGroupsCount = pViewDay->GetViewGroupsCount();
for (int g = 0; g < nGroupsCount; g++)
{
CXTPCalendarDayViewGroup* pViewGroup = pViewDay->GetViewGroup(g);
ASSERT(pViewGroup);
if (!pViewGroup)
{
continue;
}
int nEventsCount = pViewGroup->GetViewEventsCount();
for (int nEvent = 0; nEvent < nEventsCount; nEvent++)
{
CXTPCalendarViewEvent* pViewEvent = pViewGroup->GetViewEvent(nEvent);
if (!pViewEvent)
{
ASSERT(FALSE);
continue;
}
int nMDEFlags = pViewEvent->GetMultiDayEventFlags();
if ((nMDEFlags & xtpCalendarMultiDayMSmask) || !(nMDEFlags & xtpCalendarMultiDayFMLmask))
continue; // already marked or not multi day
pViewEvent->SetMultiDayEvent_MasterSlave(TRUE, NULL);
int nMasterPlace = pViewEvent->GetEventPlaceNumber();
if ((nMDEFlags & xtpCalendarMultiDayLast) == 0)
{
// find other visible instances and mark them as Slave
for (int i = nDayIdx + 1; i < nDaysCount; i++)
{
CXTPCalendarViewDay* pViewDay2 = GetViewDay(i);
if (XTP_SAFE_GET1(pViewDay2, GetViewGroupsCount(), 0) != 1)
{
ASSERT(FALSE);
break;
}
CXTPCalendarViewEvent* pViewEvent2 = XTP_SAFE_GET2(pViewDay2,
GetViewGroup_(0), GetViewEventByEvent_(pViewEvent->GetEvent()), NULL);
if (!pViewEvent2)
break;
pViewEvent->AddMultiDayEvent_Slave(pViewEvent2, nMasterPlace);
}
}
}
}
}
}
int CXTPCalendarDayView::CalculateHeaderFormatAndHeight(CDC* pDC, int nCellWidth)
{
ASSERT(pDC);
const int cnMinHeight = 19;
CXTPCalendarViewPart* pPart = XTP_SAFE_GET1(GetPaintManager(), GetDayViewHeaderPart(), NULL);
ASSERT(pPart);
if (!pPart || !pDC)
{
return cnMinHeight;
}
CalculateHeaderFormat(pDC, nCellWidth, &pPart->GetTextFont());
CString strHearderTest = _T("QW(");
int nCount = GetViewDayCount();
for (int i = 0; i < nCount; i++)
{
CXTPCalendarDayViewDay* pDay = GetViewDay(i);
ASSERT(pDay);
if (pDay)
{
strHearderTest += pDay->GetCaption();
}
}
CXTPFontDC fnt(pDC, &pPart->GetTextFont());
CSize sizeH = pDC->GetTextExtent(strHearderTest);
int nHeight = max(cnMinHeight, sizeH.cy + 6);
return nHeight;
}
CXTPCalendarData* CXTPCalendarDayView::_GetDataProviderByConnStr(LPCTSTR pcszConnStr, BOOL bCompareNoCase)
{
UNREFERENCED_PARAMETER(pcszConnStr);
UNREFERENCED_PARAMETER(bCompareNoCase);
return NULL;
}
BOOL CXTPCalendarDayView::IsGroupHeaderVisible() const
{
BOOL bHideHeader = XTP_SAFE_GET1(GetResources(), GetCount(), 0) == 1 &&
XTP_SAFE_GET2(GetResources(), GetAt(0), IsSchedulesSetEmpty(), FALSE);
return !bHideHeader;
}
void CXTPCalendarDayView::AdjustLayout(CDC* pDC, const CRect& rcView, BOOL bCallPostAdjustLayout)
{
ASSERT(pDC);
if (!pDC)
{
return;
}
XTP_SAFE_CALL1(m_pTimeScaleHeader, SetCaption(GetScaleText()) );
XTP_SAFE_CALL1(m_pTimeScaleHeader, SetVisible(!m_bShowAllDayEventsOnly) );
XTP_SAFE_CALL1(m_pTimeScaleHeader2, SetCaption(GetScale2Text()) );
XTP_SAFE_CALL1(m_pTimeScaleHeader2, SetVisible(IsScale2Visible()) );
TBase::AdjustLayout(pDC, rcView, FALSE);
// COleDateTimeSpan spDaySpan(1, 0, 0, 0);
COleDateTimeSpan spDaySpan(m_dtTimeScaleMax - m_dtTimeScaleMin);
double dRows = spDaySpan / max((double) m_pTimeScaleHeader->GetScaleInterval(), XTP_HALF_SECOND * 2);
//m_LayoutX.m_nRowCount = (int)(dRows + XTP_HALF_SECOND);
m_LayoutX.m_nRowCount = (int)(dRows + .5);
// to prevent loosing 1 : (int)(47.99999999999) = 47; // need 48 !
CRect rcView2 = rcView;
// alternative time scale
if (IsScale2Visible())
{
int nTimeScale2Width = XTP_SAFE_GET1(m_pTimeScaleHeader2, CalcWidth(pDC), 0);
m_pTimeScaleHeader2->m_Layout.m_rcHeader.SetRect(
rcView2.left, rcView2.top,
rcView2.left + nTimeScale2Width, rcView2.bottom);
rcView2.left += nTimeScale2Width;
AdjustScale2TimeZone();
}
// regular time scale
if (m_pTimeScaleHeader)
{
int nTimeScaleWidth = XTP_SAFE_GET1(m_pTimeScaleHeader, CalcWidth(pDC), 0);
m_pTimeScaleHeader->m_Layout.m_rcHeader.SetRect(
rcView2.left, rcView2.top,
rcView2.left + nTimeScaleWidth, rcView2.bottom);
rcView2.left += nTimeScaleWidth;
}
CXTPCalendarViewPart* pPart = XTP_SAFE_GET1(GetPaintManager(), GetDayViewHeaderPart(), NULL);
int nDaysCount = GetViewDayCount();
if (nDaysCount <= 0 || !pPart)
return;
int nColumnsCount = GetTotalGroupsCount();
// Adjust Header
int nCellWidth = rcView2.Width() / max(nDaysCount, 1);
int nDayHeaderHeight = CalculateHeaderFormatAndHeight(pDC, nCellWidth);
int nMinRowHeight = nDayHeaderHeight;
m_LayoutX.m_nAllDayEventsCountMax = max(1, GetAllDayEventsMaxCount());
if (m_eDraggingMode == xtpCalendaDragModeResizeBegin
|| m_eDraggingMode == xtpCalendaDragModeResizeEnd
|| _IsDragModeCopyMove(m_eDraggingMode))
{
m_LayoutX.m_nAllDayEventsCountMax = max(m_LayoutX.m_nAllDayEventsCountMax, m_nAllDayEventsCountMin_WhenDrag);
m_nAllDayEventsCountMin_WhenDrag = m_LayoutX.m_nAllDayEventsCountMax;
}
BOOL bGroupHeaderVisible = IsGroupHeaderVisible();
int nDGHeadersHeight = nDayHeaderHeight * (bGroupHeaderVisible ? 2 : 1);
// day view part
int nRowCount = m_LayoutX.m_nRowCount;
int nTotalRows = nRowCount + m_LayoutX.m_nAllDayEventsCountMax + (bGroupHeaderVisible ? 2 : 1);
m_Layout.m_nRowHeight = max(nMinRowHeight, rcView2.Height() / max(nTotalRows, 1));
double dVisibleRowCountMax = (double)(rcView2.Height()) / (double)(max(m_Layout.m_nRowHeight, 1));
double dVisibleRowCount = dVisibleRowCountMax - (0.2 + m_LayoutX.m_nAllDayEventsCountMax) -
(bGroupHeaderVisible ? 2 : 1);
m_LayoutX.m_nVisibleRowCount = max((int)dVisibleRowCount, max(0, (int)dVisibleRowCountMax/2));
m_LayoutX.m_nVisibleRowCount = max(0, min(nRowCount, m_LayoutX.m_nVisibleRowCount));
if (!pDC->IsPrinting() && m_LayoutX.m_nTopRow + m_LayoutX.m_nVisibleRowCount >= m_LayoutX.m_nRowCount)
m_LayoutX.m_nTopRow = m_LayoutX.m_nRowCount - m_LayoutX.m_nVisibleRowCount;
int nAllDayEventsHeight = max(0, rcView2.Height() - (m_LayoutX.m_nVisibleRowCount * m_Layout.m_nRowHeight + nDGHeadersHeight));
m_LayoutX.m_rcDayHeader.SetRect(
rcView2.left,
rcView2.top,
rcView2.right,
rcView2.top + nDayHeaderHeight);
m_LayoutX.m_rcAllDayEvents.SetRect(
rcView2.left,
rcView2.top + nDGHeadersHeight,
rcView2.right,
rcView2.top + nAllDayEventsHeight + nDGHeadersHeight);
m_LayoutX.m_nVisibleAllDayCount = max(1, nAllDayEventsHeight / m_Layout.m_nRowHeight);
int nCols = 0;
for (int i = 0; i < nDaysCount; i++)
{
CXTPCalendarDayViewDay* pDay = GetViewDay(i);
if (!pDay)
{
ASSERT(FALSE);
continue;
}
//int nWidth = (i == nDaysCount - 1) ? rcView2.Width() : rcView2.Width() / (nColumnsCount - nCols);
int nGroupsCount = pDay->GetViewGroupsCount();
int nWidth = (rcView2.Width() / (nColumnsCount - nCols)) * nGroupsCount;
//Last Column
if (i == nDaysCount - 1)
nWidth = rcView2.Width();
CRect rcDay(rcView2.left, rcView2.top, rcView2.left + nWidth, rcView2.bottom);
pDay->AdjustLayout(pDC, rcDay);
rcView2.left += nWidth;
nCols += pDay->GetViewGroupsCount();
}
//----------------------------------------------
if (nDaysCount && XTP_SAFE_GET1(GetViewDay(0), GetViewGroupsCount(), 0)
&& GetViewDay(0)->GetViewGroup(0))
{
CRect rcAllDayEvents = GetViewDay(0)->GetViewGroup(0)->GetAllDayEventsRect();
ASSERT(rcAllDayEvents.Height() == m_LayoutX.m_rcAllDayEvents.Height());
m_LayoutX.m_rcAllDayEvents.top = rcAllDayEvents.top;
m_LayoutX.m_rcAllDayEvents.bottom = rcAllDayEvents.bottom;
}
AdjustAllDayEvents();
//----------------------------------------------------------
XTP_SAFE_CALL1(m_pTimeScaleHeader, AdjustLayout(pDC) );
XTP_SAFE_CALL1(m_pTimeScaleHeader2, AdjustLayout(pDC) );
//---------------------------------------------------------------------------
int nDVCount = GetViewDayCount();
if (nDVCount)
{
COleDateTime dtFirstDay = GetViewDayDate(0);
COleDateTime dtLastDay = GetViewDayDate(nDVCount-1);
BOOL bSelChanged = FALSE;
if (m_selectedBlock.dtEnd.GetStatus() != COleDateTime::valid ||
m_selectedBlock.dtBegin.GetStatus() != COleDateTime::valid)
{
int nSelRow = GetTopRow() + min(2, GetVisibleRowCount());
m_selectedBlock.dtBegin = CXTPCalendarUtils::UpdateTime(dtFirstDay, GetCellTime(nSelRow));
m_selectedBlock.dtEnd = m_selectedBlock.dtBegin + GetCellDuration();
m_selectedBlock.bAllDayEvent = FALSE;
m_selectedBlock.nGroupIndex = 0;
bSelChanged = TRUE;
}
COleDateTime dtSelBeginDay = GetDateTimeDay(m_selectedBlock.dtBegin);
COleDateTime dtSelEndDay = GetDateTimeDay(m_selectedBlock.dtEnd - COleDateTimeSpan(0, 0, 0, 1));
// compare with the first day
if (dtSelBeginDay < dtFirstDay)
{
m_selectedBlock.dtBegin = CXTPCalendarUtils::UpdateDate(m_selectedBlock.dtBegin, dtFirstDay);
bSelChanged = TRUE;
}
if (dtSelEndDay < dtFirstDay)
{
m_selectedBlock.dtEnd = CXTPCalendarUtils::UpdateDate(m_selectedBlock.dtEnd, dtFirstDay);
bSelChanged = TRUE;
}
// compare with the last day
if (dtSelEndDay > dtLastDay)
{
m_selectedBlock.dtEnd = CXTPCalendarUtils::UpdateDate(m_selectedBlock.dtEnd, dtLastDay);
bSelChanged = TRUE;
}
if (dtSelBeginDay > dtLastDay)
{
m_selectedBlock.dtBegin = CXTPCalendarUtils::UpdateDate(m_selectedBlock.dtBegin, dtLastDay);
bSelChanged = TRUE;
}
if (bSelChanged)
CSelectionChangedContext selChanged(this, xtpCalendarSelectionDays);
}
//---------------------------------------------------------------------------
if (bCallPostAdjustLayout)
OnPostAdjustLayout();
}
void CXTPCalendarDayView::AdjustLayout2(CDC* pDC, const CRect& rcView, BOOL bCallPostAdjustLayout)
{
if (!pDC || !GetTheme())
{
ASSERT(FALSE);
return;
}
TBase::AdjustLayout2(pDC, rcView, bCallPostAdjustLayout);
//*** Pre-Theme Adjust Layout step
XTP_SAFE_CALL1(m_pTimeScaleHeader, SetCaption(GetScaleText()) );
XTP_SAFE_CALL1(m_pTimeScaleHeader, SetVisible(!m_bShowAllDayEventsOnly));
XTP_SAFE_CALL1(m_pTimeScaleHeader2, SetCaption(GetScale2Text()) );
XTP_SAFE_CALL1(m_pTimeScaleHeader2, SetVisible(IsScale2Visible()) );
if (IsScale2Visible())
{
AdjustScale2TimeZone();
}
COleDateTimeSpan spDaySpan(m_dtTimeScaleMax - m_dtTimeScaleMin);
double dRows = spDaySpan / max((double)m_pTimeScaleHeader->GetScaleInterval(), XTP_HALF_SECOND * 2);
//m_LayoutX.m_nRowCount = (int)(dRows + XTP_HALF_SECOND);
m_LayoutX.m_nRowCount = (int)(dRows + .5);
// to prevent loosing 1 : (int)(47.99999999999) = 47; // need 48 !
m_LayoutX.m_nAllDayEventsCountMax = max(1, GetAllDayEventsMaxCount());
if (m_eDraggingMode == xtpCalendaDragModeResizeBegin
|| m_eDraggingMode == xtpCalendaDragModeResizeEnd
|| _IsDragModeCopyMove(m_eDraggingMode))
{
m_LayoutX.m_nAllDayEventsCountMax = max(m_LayoutX.m_nAllDayEventsCountMax, m_nAllDayEventsCountMin_WhenDrag);
m_nAllDayEventsCountMin_WhenDrag = m_LayoutX.m_nAllDayEventsCountMax;
}
GetTheme()->GetDayViewPart()->AdjustLayout(pDC, rcView);
//*** Post-Theme Adjust Layout step
//---------------------------------------------------------------------------
int nDVCount = GetViewDayCount();
if (nDVCount)
{
COleDateTime dtFirstDay = GetViewDayDate(0);
COleDateTime dtLastDay = GetViewDayDate(nDVCount-1);
BOOL bSelChanged = FALSE;
if (m_selectedBlock.dtEnd.GetStatus() != COleDateTime::valid ||
m_selectedBlock.dtBegin.GetStatus() != COleDateTime::valid)
{
int nSelRow = GetTopRow() + min(2, GetVisibleRowCount());
m_selectedBlock.dtBegin = CXTPCalendarUtils::UpdateTime(dtFirstDay, GetCellTime(nSelRow));
m_selectedBlock.dtEnd = m_selectedBlock.dtBegin + GetCellDuration();
m_selectedBlock.bAllDayEvent = FALSE;
m_selectedBlock.nGroupIndex = 0;
bSelChanged = TRUE;
}
COleDateTime dtSelBeginDay = GetDateTimeDay(m_selectedBlock.dtBegin);
COleDateTime dtSelEndDay = GetDateTimeDay(m_selectedBlock.dtEnd-COleDateTimeSpan(0, 0, 0, 1));
// compare with the first day
if (dtSelBeginDay < dtFirstDay)
{
m_selectedBlock.dtBegin = CXTPCalendarUtils::UpdateDate(m_selectedBlock.dtBegin, dtFirstDay);
bSelChanged = TRUE;
}
if (dtSelEndDay < dtFirstDay)
{
m_selectedBlock.dtEnd = CXTPCalendarUtils::UpdateDate(m_selectedBlock.dtEnd, dtFirstDay);
bSelChanged = TRUE;
}
// compare with the last day
if (dtSelEndDay > dtLastDay)
{
m_selectedBlock.dtEnd = CXTPCalendarUtils::UpdateDate(m_selectedBlock.dtEnd, dtLastDay);
bSelChanged = TRUE;
}
if (dtSelBeginDay > dtLastDay)
{
m_selectedBlock.dtBegin = CXTPCalendarUtils::UpdateDate(m_selectedBlock.dtBegin, dtLastDay);
bSelChanged = TRUE;
}
if (bSelChanged)
{
CSelectionChangedContext selChanged(this, xtpCalendarSelectionDays);
}
}
//---------------------------------------------------------------------------
if (bCallPostAdjustLayout)
{
OnPostAdjustLayout();
GetTheme()->GetDayViewPart()->OnPostAdjustLayout();
}
}
void CXTPCalendarDayView::Draw2(CDC* pDC)
{
if (!GetTheme())
{
ASSERT(FALSE);
return;
}
GetTheme()->GetDayViewPart()->Draw(pDC);
m_dtLastRedrawTime = CXTPCalendarUtils::GetCurrentTime();
}
void CXTPCalendarDayView::OnDraw(CDC* pDC)
{
SCROLLINFO si;
if (!GetScrollBarInfoH(&si) || pDC->IsPrinting())
{
TBase::OnDraw(pDC);
return;
}
if (m_pTimeScaleHeader)
m_pTimeScaleHeader->MoveTo(m_nScrollOffsetX);
if (m_pTimeScaleHeader2 && IsScale2Visible())
m_pTimeScaleHeader2->MoveTo(m_nScrollOffsetX);
TBase::OnDraw(pDC);
}
void CXTPCalendarDayView::Draw(CDC* pDC)
{
pDC->SetBkMode(TRANSPARENT);
// days
int i = 0;
const int nCount = GetViewDayCount();
for (i = nCount - 1; i >= 0; i--)
{
XTP_SAFE_CALL1(GetViewDay(i), Draw(pDC));
}
for (i = nCount - 1; i >= 0; i--)
{
XTP_SAFE_CALL1(GetViewDay(i), DrawTopmostLayer(pDC));
}
// alternative time scale
if (IsScale2Visible() && m_pTimeScaleHeader2)
m_pTimeScaleHeader2->Draw(pDC);
// regular time scale
XTP_SAFE_CALL1(m_pTimeScaleHeader, Draw(pDC));
m_dtLastRedrawTime = CXTPCalendarUtils::GetCurrentTime();
}
BOOL CXTPCalendarDayView::HitTestEx(CPoint pt, XTP_CALENDAR_HITTESTINFO* pHitTest) const
{
if (!pHitTest)
{
ASSERT(FALSE);
return FALSE;
}
pHitTest->pt = pt;
if (m_pTimeScaleHeader2 && m_pTimeScaleHeader2->HitTestDateTime(pHitTest))
return TRUE;
if (m_pTimeScaleHeader && m_pTimeScaleHeader->HitTestDateTime(pHitTest))
return TRUE;
CXTPCalendarThemeOffice2007* pThemeX = DYNAMIC_DOWNCAST(CXTPCalendarThemeOffice2007, GetTheme());
BOOL bShowExpandButton = XTP_SAFE_GET1(GetCalendarOptions(), bShowAllDayExpandButton, TRUE);
BOOL bNeedScroll = FALSE;
int iVisibleEventsMaxCount = m_LayoutX.m_nAllDayEventsCountMax;
int nVisAllDayEvents = m_LayoutX.m_nVisibleAllDayCount;
bNeedScroll = (iVisibleEventsMaxCount > nVisAllDayEvents);
if ((pThemeX != NULL) && bShowExpandButton)
{
// check if allday expand button is hit
if (bNeedScroll && m_LayoutX.m_rcAllDayEvents.PtInRect(pt))
{
int nDaysCount = GetViewDayCount();
for (int nDayIdx = 0; nDayIdx < nDaysCount; nDayIdx++)
{
CXTPCalendarDayViewDay* pViewDay = GetViewDay(nDayIdx);
if (!pViewDay)
{
ASSERT(FALSE);
continue;
}
int nGroupsCount = pViewDay->GetViewGroupsCount();
for (int g = 0; g < nGroupsCount; g++)
{
CXTPCalendarDayViewGroup* pViewGroup = pViewDay->GetViewGroup(g);
ASSERT(pViewGroup);
if (!pViewGroup)
{
continue;
}
if(pThemeX->ExpandDayButton_HitTest(pt, pViewGroup->GetAllDayEventsScrollButtonRect(XTP_DAY_VIEW_GROUP_LAYOUT::xtpHotAllDayEventsScrollDown), FALSE))
{
XTP_CALENDAR_HITTESTINFO emptyData;
*pHitTest = emptyData;
pHitTest->uHitCode = xtpCalendarHitTestAllDayEventsScrollDown;
return TRUE;
}
if(pThemeX->ExpandDayButton_HitTest(pt, pViewGroup->GetAllDayEventsScrollButtonRect(XTP_DAY_VIEW_GROUP_LAYOUT::xtpHotAllDayEventsScrollUp), TRUE))
{
XTP_CALENDAR_HITTESTINFO emptyData;
*pHitTest = emptyData;
pHitTest->uHitCode = xtpCalendarHitTestAllDayEventsScrollUp;
return TRUE;
}
int iAllDayCount = pViewGroup->GetEventsCountInAllDayArea();
if (iAllDayCount > nVisAllDayEvents)
{
CRect rcIconsMax1 = pViewGroup->GetAllDayEventsRect();
rcIconsMax1.top = rcIconsMax1.bottom - 13;
rcIconsMax1.bottom = rcIconsMax1.top + 9;
rcIconsMax1.left = pViewGroup->GetAllDayEventsRect().right - 17;
rcIconsMax1.right = rcIconsMax1.left + 14;
if (pThemeX->ExpandDayButton_HitTest(pt, rcIconsMax1, FALSE))
{
XTP_CALENDAR_HITTESTINFO emptyData;
*pHitTest = emptyData;
//pHitTest->uHitCode = xtpCalendarHitTestDayExpandButton | xtpCalendarHitTestDayViewAllDayEvent;
pHitTest->uHitCode = xtpCalendarHitTestAllDayExpandButton;
return TRUE;
}
}
}
}
}
}
if(!pThemeX && m_LayoutX.m_rcAllDayEvents.PtInRect(pt))
{
int nDaysCount = GetViewDayCount();
for (int nDayIdx = 0; nDayIdx < nDaysCount; nDayIdx++)
{
CXTPCalendarDayViewDay* pViewDay = GetViewDay(nDayIdx);
if (!pViewDay)
{
ASSERT(FALSE);
continue;
}
int nGroupsCount = pViewDay->GetViewGroupsCount();
for (int g = 0; g < nGroupsCount; g++)
{
CXTPCalendarDayViewGroup* pViewGroup = pViewDay->GetViewGroup(g);
ASSERT(pViewGroup);
if (!pViewGroup)
{
continue;
}
if(!pViewGroup->NeedScrollAllDayEvents())
continue;
if(pViewGroup->HitTestAllDayEventsScrollIcons(pt, pHitTest) == TRUE)
return TRUE;
}
}
}
int nHit = XTP_SAFE_GET2(pThemeX, GetPrevNextEventButtonsPartX(), HitTest(&pt), 0);
if (nHit)
{
XTP_CALENDAR_HITTESTINFO emptyData;
*pHitTest = emptyData;
pHitTest->uHitCode = nHit;
return TRUE;
}
//<< fix for Multiday Events >>
XTPCalendarViewType cvt = GetCalendarControl()->GetActiveView()->GetViewType();
if (m_bUseNewHitTestCode
&& (cvt == xtpCalendarWorkWeekView
|| (cvt == xtpCalendarWeekView && GetCalendarControl()->m_bMultiColumnWeekMode)
|| (cvt == xtpCalendarFullWeekView && GetCalendarControl()->m_bMultiColumnWeekMode)))
{
for (int i = 0; i < GetViewDayCount(); i++)
{
CXTPCalendarDayViewDay* pViewDay = GetViewDay(i);
if (pViewDay)
{
for (int j = 0; j < pViewDay->GetViewGroupsCount(); j++)
{
CXTPCalendarDayViewGroup* pViewGroup = pViewDay->GetViewGroup(j);
if (pViewGroup)
{
for (int nEvent = 0; nEvent < pViewGroup->GetViewEventsCount(); nEvent++)
{
CXTPCalendarDayViewEvent* pViewEvent = pViewGroup->GetViewEvent(nEvent);
if (pViewEvent)
{
if (pViewEvent->IsMultidayEvent())
{
CRect rcEvent(pViewEvent->GetEventRect());
if (rcEvent.PtInRect(pt))
{
if ((pViewEvent->GetMultiDayEventFlags() & xtpCalendarMultiDaySlave) > 0)
return FALSE;
pt.x = rcEvent.left + 10;
pHitTest->pt = pt;
return TBase::HitTestEx(pt, pHitTest);
}
}
}
}
}
}
}
}
}
//<< fix for Multiday Events >>
return TBase::HitTestEx(pt, pHitTest);
}
BOOL CXTPCalendarDayView::IsUseCellAlignedDraggingInTimeArea() const
{
if (GetTheme() && GetTheme()->GetDayViewPart())
return GetTheme()->GetDayViewPart()->IsUseCellAlignedDraggingInTimeArea();
return CXTPCalendarView::IsUseCellAlignedDraggingInTimeArea();
}
void CXTPCalendarDayView::OnStartDragging(CPoint point, XTP_CALENDAR_HITTESTINFO* pHitTest)
{
if (!pHitTest || !m_pControl)
{
ASSERT(FALSE);
return;
}
m_dtDraggingStartPoint = pHitTest->dt;
m_spDraggingStartOffset_Time = 0.;
m_nAllDayEventsCountMin_WhenDrag = max(1, GetAllDayEventsMaxCount());
CXTPCalendarControl::CUpdateContext updateContext(m_pControl, xtpCalendarUpdateRedraw);
TBase::OnStartDragging(point, pHitTest);
//<<>
if (pHitTest->pViewEvent != NULL
&& pHitTest->pViewEvent->GetEvent()->IsAllDayEvent())
{
if (m_bPreventDragAllDayEventInDayView)
{
m_eDraggingMode = xtpCalendaDragModeUnknown;
return;
}
else
{
//TRACE(_T("OnStartDragging\n"));
m_bUseNewHitTestCode = FALSE;
}
}
//<<>
if (double(m_spDraggingStartOffset) != 0.0 && (DATE)m_dtTimeScaleMax <= 1
&& IsUseCellAlignedDraggingInTimeArea())
{
// Align to cell begin time
m_spDraggingStartOffset = pHitTest->dt - pHitTest->pViewEvent->GetEvent()->GetStartTime();
int nTmpCell = GetCellNumber((DATE)(double)m_spDraggingStartOffset, FALSE);
m_spDraggingStartOffset = (double)GetCellTime(nTmpCell);
}
m_selectedBlock.dtEnd = m_selectedBlock.dtBegin;
m_selectedBlock.bAllDayEvent = FALSE;
m_selectedBlock.nGroupIndex = pHitTest->nGroup;
CSelectionChangedContext selChanged(this, xtpCalendarSelectionDays);
}
BOOL CXTPCalendarDayView::OnDragging(CPoint point, XTP_CALENDAR_HITTESTINFO* pHitTest)
{
if (!pHitTest)
{
ASSERT(FALSE);
return FALSE;
}
if (!m_ptrDraggingEventNew
|| m_eDraggingMode == xtpCalendaDragModeEditSubject
|| !GetCalendarControl())
{
return FALSE;
}
// Restriction for Issue #: 18965
if (GetCalendarControl()->m_bPreventAutoAllDayMode)
{
if (pHitTest->uHitCode ==
(xtpCalendarHitTestDayViewAllDayEvent | xtpCalendarHitTestDayArea))
return FALSE;
}
XTP_CALENDAR_HITTESTINFO hitInfo2 = *pHitTest;
XTP_CALENDAR_HITTESTINFO* pHitTest2 = &hitInfo2;
BOOL bChanged = FALSE;
XTP_CALENDAR_HITTESTINFO hitTestInfo;
if (!HitTestEx(point, &hitTestInfo))
return FALSE;
//========================================================================
BOOL bScrolled = FALSE;
XTPCalendarDayViewScrollDirection scrollDir = GetNeededScrollDirection(point);
if (scrollDir != xtpCalendarDayViewScrollNotNeeded)
{
if (scrollDir == xtpCalendarDayViewScrollUp)
{
bScrolled = VertEventScroll(TRUE);//scroll up
SetMouseOutOfDragArea(FALSE);
if (bScrolled)
{
if (HitTestEx(point, &hitTestInfo))
pHitTest2->dt = hitTestInfo.dt;
}
}
else if (scrollDir == xtpCalendarDayViewScrollDown)
{
bScrolled = VertEventScroll(FALSE);//scroll down
SetMouseOutOfDragArea(FALSE);
if (bScrolled)
{
if (HitTestEx(point, &hitTestInfo))
pHitTest2->dt = hitTestInfo.dt;
}
}
//--------------------------------------------------------
else if (scrollDir == xtpCalendarDayViewScrollLeft)
bScrolled = HorzEventScroll(TRUE);//scroll left
else if (scrollDir == xtpCalendarDayViewScrollRight)
bScrolled = HorzEventScroll(FALSE);//scroll right
}
if (IsOutOfClientRect(point, &hitTestInfo))
{
SetMouseOutOfDragArea(TRUE);
StopVertEventScroll();
bScrolled = TRUE;
return TRUE;
}
if (!bScrolled)
{
SetMouseOutOfDragArea(FALSE);
StopVertEventScroll();
}
// check drag on TimeScale:
if (_IsDragModeCopyMove(m_eDraggingMode)
&& (m_pTimeScaleHeader2 && m_pTimeScaleHeader2->HitTestDateTime(&hitTestInfo) ||
(m_pTimeScaleHeader && m_pTimeScaleHeader->HitTestDateTime(&hitTestInfo))))
{
COleDateTime dtNewTime = pHitTest->dt;
dtNewTime = COleDateTime(m_dtDraggingStartPoint.GetYear(),
m_dtDraggingStartPoint.GetMonth(), m_dtDraggingStartPoint.GetDay(),
dtNewTime.GetHour(), dtNewTime.GetMinute(), dtNewTime.GetSecond());
m_ptrDraggingEventNew->MoveEvent(dtNewTime);
return TRUE;
}
if (!m_ptrDraggingEventOrig)
{
ASSERT(FALSE);
return FALSE;
}
BOOL bAllDayEventArea = 0 != (hitTestInfo.uHitCode & xtpCalendarHitTestDayViewAllDayEvent);
BOOL bAllDayEventNew_prev = m_ptrDraggingEventNew->IsAllDayEvent();
BOOL bAllMultiDayEvent = bAllDayEventNew_prev || m_ptrDraggingEventNew->GetDurationMinutes() > 24 * 60;
BOOL bAllMultiDayEventOrig = m_ptrDraggingEventOrig->IsAllDayEvent();
bAllMultiDayEventOrig |= m_ptrDraggingEventOrig->GetDurationMinutes() > 24 * 60;
bChanged = (bAllDayEventArea != bAllMultiDayEvent);// && !bAllDayEventNew_prev;
if (bChanged)
{
//TRACE(_T("bAllDayEventArea != bAllMultiDayEvent\n"));
if (!bAllDayEventArea && bAllMultiDayEventOrig && _IsDragModeCopyMove(m_eDraggingMode))
{
//m_ptrDraggingEventNew->SetDuration(GetCellDuration());
m_ptrDraggingEventNew->SetDuration(GetCellDuration(), FALSE);
}
else if (bAllDayEventArea && !bAllMultiDayEventOrig && _IsDragModeCopyMove(m_eDraggingMode))
{
m_ptrDraggingEventNew->SetStartTime(GetDateTimeDay(m_ptrDraggingEventOrig->GetStartTime()));
m_ptrDraggingEventNew->SetEndTime(m_ptrDraggingEventNew->GetStartTime() + COleDateTimeSpan(1, 0, 0, 0));
}
else
{
m_ptrDraggingEventNew->SetStartTime(m_ptrDraggingEventOrig->GetStartTime());
m_ptrDraggingEventNew->SetEndTime(m_ptrDraggingEventOrig->GetEndTime());
}
if (_IsDragModeCopyMove(m_eDraggingMode))
{
if (bAllDayEventArea == bAllMultiDayEventOrig)
{
m_spDraggingStartOffset = m_spDraggingStartOffset_Time;
m_spDraggingStartOffset_Time = 0.;
}
else
{
m_spDraggingStartOffset_Time = m_spDraggingStartOffset;
m_spDraggingStartOffset = 0.;
}
if (bAllDayEventArea)
{
if (GetCalendarControl()->DayView_IsAutoResetBusyFlag())
{
if (!bAllDayEventNew_prev &&
xtpCalendarBusyStatusBusy == m_ptrDraggingEventNew->GetBusyStatus()
&&
!(bAllMultiDayEventOrig &&
xtpCalendarBusyStatusBusy == m_ptrDraggingEventOrig->GetBusyStatus()))
{
m_ptrDraggingEventNew->SetBusyStatus(xtpCalendarBusyStatusFree);
}
}
}
else
{
if (GetCalendarControl()->DayView_IsAutoResetBusyFlag())
{
if (bAllMultiDayEvent &&
xtpCalendarBusyStatusFree == m_ptrDraggingEventNew->GetBusyStatus()
&&
!(!bAllMultiDayEventOrig &&
xtpCalendarBusyStatusFree == m_ptrDraggingEventOrig->GetBusyStatus()))
{
m_ptrDraggingEventNew->SetBusyStatus(xtpCalendarBusyStatusBusy);
}
}
}
}
}
//========================================================================
if (m_eDraggingMode == xtpCalendaDragModeResizeEnd)
{
if (pHitTest2->bTimePartValid)
{
pHitTest2->dt += GetCellDuration();
}
}
BOOL bChangedBase = TBase::OnDragging(point, pHitTest2);
//-------------------------------------------------------------------------
// multi-resources movement
if (_IsDragModeCopyMove(m_eDraggingMode))
{
UINT uScheduleID = XTP_SAFE_GET2(pHitTest2, pViewGroup, GetScheduleID(), 0);
if (uScheduleID != m_ptrDraggingEventNew->GetScheduleID())
{
if (uScheduleID != XTP_CALENDAR_UNKNOWN_SCHEDULE_ID)
{
m_ptrDraggingEventNew->SetScheduleID(uScheduleID);
bChanged = TRUE;
}
else if (m_ptrDraggingEventNew->GetScheduleID() != m_ptrDraggingEventOrig->GetScheduleID())
{
m_ptrDraggingEventNew->SetScheduleID(m_ptrDraggingEventOrig->GetScheduleID());
bChanged = TRUE;
}
}
}
//---
CXTPCalendarData* pHitData = XTP_SAFE_GET2(pHitTest2, pViewGroup, GetDataProvider(), NULL);
if (pHitData && pHitData != m_ptrDraggingEventNew->GetDataProvider())
{
CXTPCalendarEventPtr ptrHitEventNew = pHitData->CreateNewEvent();
if (ptrHitEventNew)
{
if (m_ptrDraggingEventNew->CloneEventTo(ptrHitEventNew))
{
m_ptrDraggingEventNew = ptrHitEventNew;
bChanged = TRUE;
}
}
}
BOOL bIsResizing = m_eDraggingMode == xtpCalendaDragModeResizeBegin ||
m_eDraggingMode == xtpCalendaDragModeResizeEnd;
BOOL bIsZeroLen = CXTPCalendarUtils::IsEqual(m_ptrDraggingEventNew->GetStartTime(),
m_ptrDraggingEventNew->GetEndTime());
if (bAllDayEventArea && (bIsResizing && !bIsZeroLen || !bIsResizing) &&
(m_ptrDraggingEventOrig->IsAllDayEvent() || !bAllMultiDayEventOrig
|| m_ptrDraggingEventNew->IsAllDayEvent()))
{
m_ptrDraggingEventNew->SetAllDayEvent(TRUE);
}
else
{
m_ptrDraggingEventNew->SetAllDayEvent(FALSE);
}
return bChanged || bChangedBase;
}
XTPCalendarDayViewScrollDirection CXTPCalendarDayView::GetNeededScrollDirection(CPoint pnt) const
{
static const int nVScrollZone = 20;
static const int nHScrollZone = 80;
CRect rcCtrl;
if (!m_pControl)
return xtpCalendarDayViewScrollNotNeeded;
m_pControl->GetWindowRect(rcCtrl);
int nHeight = rcCtrl.Height();
CRect rcAllDayEvents = GetAllDayEventsRectangle();
CRect rcVisible = _GetScrollRectClient();
int nRight = rcVisible.right;
int nLeft = rcVisible.left;
int nTop = rcAllDayEvents.bottom;
int nCurPosH = 0;
int nLimitH = rcVisible.Width();
int nCurPos = 0;
int nLimit = rcVisible.Height();
SCROLLINFO si;
if (GetScrollBarInfoV(&si))
{
nCurPos = si.nPos;
nLimit = m_pControl->GetScrollLimit(SB_VERT);
}
SCROLLINFO siH;
if (GetScrollBarInfoH(&siH))
{
nCurPosH = siH.nPos;
nLimitH = m_pControl->GetScrollLimit(SB_HORZ);
}
BOOL bWidtdhOK = (nLeft <= pnt.x) && (pnt.x <= nRight);
if (!bWidtdhOK)
return xtpCalendarDayViewScrollNotNeeded;
BOOL b2Up = (m_ptLBtnDownMousePos.y - pnt.y) > 2;
BOOL b2Down = (pnt.y - m_ptLBtnDownMousePos.y) > 2;
if (b2Up
&& pnt.y >= nTop
&& pnt.y <= (nTop + nVScrollZone)
&& nCurPos > 0)
return xtpCalendarDayViewScrollUp;
if (b2Down
&& (pnt.y + 3) < nHeight
&& (pnt.y + 3) >= (nHeight - nVScrollZone)
&& nCurPos < nLimit)
return xtpCalendarDayViewScrollDown;
int iCnt = 1;
if (GetResources())
iCnt = GetResources()->GetCount();
if (iCnt == 1)
return xtpCalendarDayViewScrollNotNeeded;
BOOL b2Left = (m_ptLBtnDownMousePos.x - pnt.x) > 2;
BOOL b2Right = (pnt.x - m_ptLBtnDownMousePos.x) > 2;
if (b2Left
&& pnt.x > rcVisible.left
&& pnt.x <= (rcVisible.left + nHScrollZone)
&& nCurPosH > 0)
return xtpCalendarDayViewScrollLeft;
if (b2Right
&& (pnt.x + 3) < rcVisible.right
&& (pnt.x + 3) >= (rcVisible.right - nHScrollZone)
&& nCurPosH < nLimitH)
return xtpCalendarDayViewScrollRight;
return xtpCalendarDayViewScrollNotNeeded;
}
BOOL CXTPCalendarDayView::IsOutOfClientRect(CPoint pnt, XTP_CALENDAR_HITTESTINFO* pHitInfo)
{
if (!m_pControl)
return FALSE;
CRect rcCtrl;
m_pControl->GetWindowRect(rcCtrl);
if (m_pTimeScaleHeader2 && m_pTimeScaleHeader2->HitTestDateTime(pHitInfo))
return FALSE;
if (m_pTimeScaleHeader && m_pTimeScaleHeader->HitTestDateTime(pHitInfo))
return FALSE;
//bottom
if (pnt.y + 3 >= rcCtrl.Height())
return TRUE;
//top
CRect rcAllDayEvents = GetAllDayEventsRectangle();
if (pnt.y <= rcAllDayEvents.top)
return TRUE;
//left
if (pnt.x < rcAllDayEvents.left)
return TRUE;
//right
if (pnt.x > rcAllDayEvents.right)
return TRUE;
if (pHitInfo->uHitCode & xtpCalendarHitTestDayViewTimeScale)
return TRUE;
return FALSE;
}
void CXTPCalendarDayView::StopVertEventScroll()
{
if (m_dwScrollingEventTimerID)
{
KillTimer(m_dwScrollingEventTimerID);
m_dwScrollingEventTimerID = 0;
}
}
void CXTPCalendarDayView::StopHorzEventScroll()
{
if (m_dwScrollingEventTimerHorID)
{
KillTimer(m_dwScrollingEventTimerHorID);
m_dwScrollingEventTimerHorID = 0;
}
}
void CXTPCalendarDayView::SetMouseOutOfDragArea(BOOL bOutOfArea)
{
BOOL bChanged = m_bMouseOutOfDragArea != bOutOfArea;
m_bMouseOutOfDragArea = bOutOfArea;
BOOL bNeedUpd = FALSE;
if (m_bMouseOutOfDragArea)
{
if (m_ptrDraggingEventNew)
m_ptrDraggingEventNew->MoveEvent(m_dtDraggingStartPoint);
if (m_pControl && m_pControl->m_mouseMode != xtpCalendarMouseEventDraggingOut)
{
m_pControl->m_mouseMode = xtpCalendarMouseEventDraggingOut;
bNeedUpd = TRUE;
}
}
if (bChanged && !m_bMouseOutOfDragArea)
{
XTPCalendarMouseMode mouseMode = xtpCalendarMouseNothing;
switch (m_eDraggingMode)
{
case xtpCalendaDragModeUnknown:
case xtpCalendaDragModeEditSubject:
mouseMode = xtpCalendarMouseNothing;
break;
case xtpCalendaDragModeCopy:
mouseMode = xtpCalendarMouseEventDragCopy;
break;
case xtpCalendaDragModeMove:
mouseMode = xtpCalendarMouseEventDragMove;
break;
case xtpCalendaDragModeResizeBegin:
case xtpCalendaDragModeResizeEnd:
mouseMode = xtpCalendarMouseEventResizingV;
break;
}
XTP_SAFE_SET1(m_pControl, m_mouseMode, mouseMode);
bNeedUpd = TRUE;
}
if (bNeedUpd && m_pControl)
m_pControl->UpdateMouseCursor();
}
BOOL CXTPCalendarDayView::VertEventScroll(BOOL bUp)
{
if (!m_pControl)
{
ASSERT(FALSE);
return FALSE;
}
SCROLLINFO si;
if (!GetScrollBarInfoV(&si))
return FALSE;
int nCurPos = si.nPos;
int nCurPos_raw = si.nPos;
int nLimit = m_pControl->GetScrollLimit(SB_VERT);
if (bUp && nCurPos > 0)
{
//scroll up
nCurPos = max(nCurPos - 1, 0);
nCurPos_raw--;
m_bScrollingEventUp = TRUE;
}
else if (!bUp && nCurPos < nLimit)
{
//scroll down
nCurPos = min(nCurPos + 1, nLimit);
nCurPos_raw++;
m_bScrollingEventUp = FALSE;
}
else
{
//limit is reached
StopVertEventScroll();
return FALSE;//not handled
}
ScrollV(nCurPos, nCurPos_raw);
m_pControl->SetScrollPos(SB_VERT, nCurPos, FALSE);
m_pControl->AdjustScrollBar();
if (!m_dwScrollingEventTimerID)
m_dwScrollingEventTimerID = SetTimer(XTP_SCROLL_TIMER_RESOLUTION_MS);
return TRUE;
}
BOOL CXTPCalendarDayView::HorzEventScroll(BOOL bLeft)
{
if (!m_pControl)
{
ASSERT(FALSE);
return FALSE;
}
SCROLLINFO si;
if (!GetScrollBarInfoH(&si))
return FALSE;
BOOL bFast = TRUE;
int nCurPos = si.nPos;
int nCurPos_raw = si.nPos;
int nPage = si.nPage;
int nLimit = m_pControl->GetScrollLimit(SB_HORZ);
if (bLeft && nCurPos > 0)
{
//scroll left
if (bFast)
{
nCurPos -= nPage;
nCurPos = max(nCurPos, 0);
nCurPos_raw -= nPage;
}
else
{
nCurPos = max(nCurPos - 1, 0);
nCurPos_raw--;
}
m_bScrollingEventLeft = TRUE;
}
else if (!bLeft && nCurPos < nLimit)
{
//scroll right
if (bFast)
{
nCurPos += nPage;
nCurPos = min(nCurPos, nLimit);
nCurPos_raw += nPage;
}
else
{
nCurPos = min(nCurPos + 1, nLimit);
nCurPos_raw++;
}
m_bScrollingEventLeft = FALSE;
}
else
{
//limit is reached
return FALSE;//not handled
}
ScrollH(nCurPos, nCurPos_raw);
m_pControl->SetScrollPos(SB_HORZ, nCurPos, FALSE);
m_pControl->AdjustScrollBar();
return TRUE;
}
void CXTPCalendarDayView::OnActivateView(BOOL bActivate, CXTPCalendarView* pActivateView,
CXTPCalendarView* pInactiveView)
{
TBase::OnActivateView(bActivate, pActivateView, pInactiveView);
if (!bActivate)
{
if (m_dwRedrawNowLineTimerID)
{
KillTimer(m_dwRedrawNowLineTimerID);
m_dwRedrawNowLineTimerID = 0;
}
StopVertEventScroll();
}
if (bActivate && m_dwRedrawNowLineTimerID == 0)
m_dwRedrawNowLineTimerID = SetTimer(XTP_REDRAW_TIMER_RESOLUTION_MS);
}
BOOL CXTPCalendarDayView::OnTimer(UINT_PTR uTimerID)
{
if (uTimerID == m_dwScrollingEventTimerID)
{
OnMouseMove(MK_LBUTTON, m_ptLastMousePos);
return TRUE;
}
else if (uTimerID == m_dwRedrawNowLineTimerID)
{
COleDateTime dtNow = CXTPCalendarUtils::GetCurrentTime();
if (dtNow.GetMinute() != m_dtLastRedrawTime.GetMinute())
CXTPCalendarControl::CUpdateContext updateContext(m_pControl, xtpCalendarUpdateRedraw);
return TRUE;
}
return TBase::OnTimer(uTimerID);
}
BOOL CXTPCalendarDayView::OnEndDragging(CPoint point, XTP_CALENDAR_HITTESTINFO* pHitInfo)
{
//TRACE(_T("OnEndDragging\n"));
m_bUseNewHitTestCode = TRUE;
if (!m_pControl || !pHitInfo)
{
ASSERT(FALSE);
return FALSE;
}
CRect rcCtrl;
m_pControl->GetWindowRect(rcCtrl);
BOOL bReturnBack = point.y + 3 >= rcCtrl.Height();
if (m_dwScrollingEventTimerID)
{
if (bReturnBack)
{
pHitInfo->dt = m_dtDraggingStartPoint;
OnDragging(point, pHitInfo);
}
else
{
OnDragging(point, pHitInfo);
}
}
StopVertEventScroll();
m_dtDraggingStartPoint = COleDateTime(0, 0, 0, 0, 0, 0);
if (_IsDragModeCopyMove(m_eDraggingMode) && m_ptrDraggingEventNew && m_ptrDraggingEventOrig)
{
if (!m_ptrDraggingEventNew->IsEqualStartEnd(m_ptrDraggingEventOrig))
{
COleDateTime dtS = m_ptrDraggingEventNew->GetStartTime();
COleDateTime dtE = m_ptrDraggingEventNew->GetEndTime();
COleDateTime dtS0 = GetDateTimeTime(dtS);
COleDateTime dtE0 = GetDateTimeTime(dtE);
m_selectedBlock.dtBegin = CXTPCalendarUtils::UpdateTime(dtS, GetCellTime(GetCellNumber(dtS0, FALSE)));
m_selectedBlock.dtEnd = GetCellTime(GetCellNumber(dtE0, dtS0 == dtE0 ? FALSE : TRUE)) + GetCellDuration();
m_selectedBlock.dtEnd = CXTPCalendarUtils::UpdateTime(dtE, m_selectedBlock.dtEnd);
if (m_ptrDraggingEventNew->IsAllDayEvent() ||
m_ptrDraggingEventNew->GetDurationMinutes() > 24 * 60)
{
m_selectedBlock.bAllDayEvent = TRUE;
}
m_selectedBlock.nGroupIndex = pHitInfo->nGroup;
CSelectionChangedContext selChanged(this, xtpCalendarSelectionDays);
}
}
m_nAllDayEventsCountMin_WhenDrag = 0;
CXTPCalendarControl::CUpdateContext updateContext(m_pControl, xtpCalendarUpdateScrollBar);
return TBase::OnEndDragging(point, pHitInfo);
}
BOOL CXTPCalendarDayView::OnLButtonUp(UINT nFlags, CPoint point)
{
return TBase::OnLButtonUp(nFlags, point);
}
BOOL CXTPCalendarDayView::OnLButtonDown(UINT nFlags, CPoint point)
{
CSelectionChangedContext selChanged(this);
TBase::OnLButtonDown(nFlags, point);
if (m_eDraggingMode != xtpCalendaDragModeUnknown)
return FALSE;
XTP_CALENDAR_HITTESTINFO hitTestInfo;
m_bUseNewHitTestCode = FALSE;
if (HitTestEx(point, &hitTestInfo))
{
m_bUseNewHitTestCode = TRUE;
BOOL bExpandButton = (hitTestInfo.uHitCode & xtpCalendarHitTestDayExpandButton) != 0;
if (bExpandButton)
{
return TRUE;
}
if (hitTestInfo.dt.GetStatus() != COleDateTime::valid)
return FALSE;
ASSERT(hitTestInfo.dt.GetStatus() == COleDateTime::valid);
BOOL bEvent = (hitTestInfo.uHitCode & xtpCalendarHitTestEvent_Mask) != 0;
if (bEvent)
{
CXTPCalendarControl::CUpdateContext updateContext(m_pControl, xtpCalendarUpdateRedraw);
m_selectedBlock.dtEnd = m_selectedBlock.dtBegin = hitTestInfo.dt;
m_dtSelectionStart = hitTestInfo.dt;
m_selectedBlock.bAllDayEvent = FALSE;
m_selectedBlock.nGroupIndex = hitTestInfo.nGroup;
CSelectionChangedContext selChanged1(this, xtpCalendarSelectionDays);
}
else
{
BOOL bFixBegin = (nFlags & MK_SHIFT);
BOOL bAllDay = 0 != (hitTestInfo.uHitCode & xtpCalendarHitTestDayViewAllDayEvent);
COleDateTime dtNewEnd = m_selectedBlock.dtEnd;
if (hitTestInfo.uHitCode & xtpCalendarHitTestDayViewTimeScale)
{
dtNewEnd = CXTPCalendarUtils::UpdateTime(dtNewEnd, hitTestInfo.dt + GetCellDuration());
hitTestInfo.nGroup = max(0, m_selectedBlock.nGroupIndex);
}
else if (hitTestInfo.uHitCode & xtpCalendarHitTestDayViewCell)
{
dtNewEnd = hitTestInfo.dt + GetCellDuration();
}
else if (bAllDay)
{
dtNewEnd = hitTestInfo.dt + COleDateTimeSpan(1, 0, 0, 0);
}
else
{
return TRUE;
}
ProcessCellSelection(dtNewEnd, bFixBegin, bAllDay, hitTestInfo.nGroup);
}
return TRUE;
}
return FALSE;
}
void CXTPCalendarDayView::OnMouseMove(UINT nFlags, CPoint point)
{
CXTPCalendarControl::CUpdateContext updateContext(m_pControl, xtpCalendarUpdateRedrawIfNeed);
CSelectionChangedContext selChanged(this);
m_ptLastMousePos = point;
TBase::OnMouseMove(nFlags, point);
if ((m_eDraggingMode != xtpCalendaDragModeUnknown)
|| ((nFlags & MK_LBUTTON) == 0)
|| !m_bStartedClickInside)
return;
// process selection mode
BOOL bScrolled = FALSE;
XTPCalendarDayViewScrollDirection direction = GetNeededScrollDirection(point);
if (direction == xtpCalendarDayViewScrollLeft)
{
bScrolled = HorzEventScroll(TRUE);//scroll left
return;
}
else if (direction == xtpCalendarDayViewScrollRight)
{
bScrolled = HorzEventScroll(FALSE);
return;
}
//----------------------------------------------------------------------------------
XTP_CALENDAR_HITTESTINFO hitTestInfo;
bScrolled = FALSE;
if (HitTestEx(point, &hitTestInfo))
{
COleDateTime dtEnd = m_selectedBlock.dtEnd;
BOOL bAllDayEvent = m_selectedBlock.bAllDayEvent;
if (direction != xtpCalendarDayViewScrollNotNeeded &&
hitTestInfo.dt.GetStatus() == COleDateTime::valid)
{
if (direction == xtpCalendarDayViewScrollUp)
{
bScrolled = VertEventScroll(TRUE);//scroll up
hitTestInfo.dt -= GetCellDuration();
}
else if (direction == xtpCalendarDayViewScrollDown)
{
bScrolled = VertEventScroll(FALSE);
hitTestInfo.dt += GetCellDuration();
}
}
if (!bScrolled)
StopVertEventScroll();
// selection processing
if (hitTestInfo.uHitCode & xtpCalendarHitTestDayViewTimeScale)
{
m_selectedBlock.bAllDayEvent = FALSE;
if (bAllDayEvent)
m_selectedBlock.dtBegin = m_dtSelectionStart;
m_selectedBlock.dtEnd = CXTPCalendarUtils::UpdateTime(m_selectedBlock.dtEnd, hitTestInfo.dt);
if (m_selectedBlock.dtEnd >= m_selectedBlock.dtBegin)
m_selectedBlock.dtEnd += GetCellDuration();
}
else if (hitTestInfo.uHitCode & xtpCalendarHitTestDayViewCell)
{
m_selectedBlock.bAllDayEvent = FALSE;
if (bAllDayEvent)
m_selectedBlock.dtBegin = m_dtSelectionStart;
m_selectedBlock.dtEnd = hitTestInfo.dt;
if (m_selectedBlock.dtEnd >= m_selectedBlock.dtBegin)
m_selectedBlock.dtEnd += GetCellDuration();
}
else if (hitTestInfo.uHitCode & xtpCalendarHitTestDayViewAllDayEvent)
{
if (!bAllDayEvent)
{
m_dtSelectionStart = m_selectedBlock.dtBegin;
m_selectedBlock.dtBegin = GetDateTimeDay(m_selectedBlock.dtBegin);
}
m_selectedBlock.dtEnd = hitTestInfo.dt;
if (m_selectedBlock.dtEnd >= m_selectedBlock.dtBegin)
m_selectedBlock.dtEnd += COleDateTimeSpan(1, 0, 0, 0);
m_selectedBlock.bAllDayEvent = TRUE;
}
if (m_selectedBlock.dtEnd != dtEnd || m_selectedBlock.bAllDayEvent != bAllDayEvent)
{
CXTPCalendarControl::CUpdateContext updateContext1(m_pControl, xtpCalendarUpdateRedraw);
CSelectionChangedContext selChanged1(this, xtpCalendarSelectionDays);
}
}
}
BOOL CXTPCalendarDayView::GetSelection(COleDateTime* pBegin, COleDateTime* pEnd,
BOOL* pbAllDayEvent, int* pnGroupIndex,
COleDateTimeSpan* pspSelectionResolution) const
{
if (!m_selectedBlock.IsValid())
return FALSE;
COleDateTime dtBegin = m_selectedBlock.dtBegin;
COleDateTime dtEnd = m_selectedBlock.dtEnd;
BOOL bAllDayEvent = m_selectedBlock.bAllDayEvent;
if (pbAllDayEvent)
*pbAllDayEvent = bAllDayEvent;
if (bAllDayEvent)
{
if (dtBegin > dtEnd)
{
COleDateTime dt = dtEnd;
dtEnd = dtBegin + COleDateTimeSpan(1, 0, 0, 0);
dtBegin = dt;
}
dtBegin = CXTPCalendarUtils::ResetTime(dtBegin);
if (!CXTPCalendarUtils::IsZeroTime(dtEnd))
dtEnd += COleDateTimeSpan(1, 0, 0, 0);
dtEnd = CXTPCalendarUtils::ResetTime(dtEnd);
}
else
{
if (dtBegin >= dtEnd)
{
COleDateTime dt = dtEnd;
dtEnd = dtBegin + GetCellDuration();
dtBegin = dt;
}
bAllDayEvent = CXTPCalendarUtils::IsZeroTime(dtBegin) && CXTPCalendarUtils::IsZeroTime(dtEnd);
}
if (pBegin)
*pBegin = dtBegin;
if (pEnd)
*pEnd = dtEnd;
if (pnGroupIndex)
*pnGroupIndex = m_selectedBlock.nGroupIndex;
if (pspSelectionResolution)
{
if (bAllDayEvent)
*pspSelectionResolution = COleDateTimeSpan(1, 0, 0, 0);
else
*pspSelectionResolution = GetCellDuration();
}
return TRUE;
}
void CXTPCalendarDayView::ShowDay(const COleDateTime& date, BOOL bSelect)
{
CXTPCalendarControl::CUpdateContext updateContext(m_pControl);
ClearDays();
AddDay(date);
if (bSelect)
{
CXTPCalendarViewDay* pDay = m_arDays.GetCount() > 0 ? m_arDays.GetAt(0) : NULL;
if (pDay)
SelectDay(pDay);
}
}
void CXTPCalendarDayView::AddDay(const COleDateTime& date)
{
CXTPCalendarControl::CViewChangedContext viewChanged(this);
_AddDay(date);
}
void CXTPCalendarDayView::_AddDay(const COleDateTime& date)
{
CXTPCalendarControl::CUpdateContext updateContext(m_pControl);
CXTPCalendarDayViewDay* pDay = new CXTPCalendarDayViewDay(this, date);
if (pDay)
{
m_arDays.Add(pDay);
m_pControl->m_bShowLinks = m_bShowLinks;
m_pControl->m_bHideLinkContainer = m_bHideLinkContainer;
pDay->Populate(date);
}
}
void CXTPCalendarDayView::ShowDays(const COleDateTime& dtBegin, const COleDateTime& dtEnd)
{
CXTPCalendarControl::CUpdateContext updateContext(m_pControl);
CXTPCalendarControl::CViewChangedContext viewChanged(this);
ClearDays();
COleDateTimeSpan spDay(1, 0, 0, 0);
COleDateTimeSpan spDaysRange = GetDateTimeDay(dtEnd) - GetDateTimeDay(dtBegin);
int nDays = CXTPCalendarUtils::GetTotalDays(spDaysRange) + 1;
COleDateTime dtDay = GetDateTimeDay(dtBegin);
nDays = max(1, nDays); // to be sure that at leas one day will be added
for (int i = 0; i < nDays; i++)
{
_AddDay(dtDay);
dtDay += spDay;
}
}
void CXTPCalendarDayView::ShowWorkingDays(const COleDateTime& dtDay)
{
if (!m_pControl)
{
ASSERT(FALSE);
return;
}
CXTPCalendarControl::CUpdateContext updateContext(m_pControl);
CXTPCalendarControl::CViewChangedContext viewChanged(this);
COleDateTime dtWeekDay(dtDay);
int nFirstWeekDay = m_pControl->GetFirstDayOfWeek();
// adjust beginning of the week iteration period to the FirstDayOfWeek
while (dtWeekDay.GetDayOfWeek() != nFirstWeekDay)
{
dtWeekDay -= COleDateTimeSpan(1);
}
// add all working days during the week to the collection
ClearDays();
for (int nWeekDay = 0; nWeekDay < 7; nWeekDay++)
{
int nWWMask = m_pControl->GetWorkWeekMask();
int nDayOfWeek = dtWeekDay.GetDayOfWeek();
int nDayMask = CXTPCalendarUtils::GetDayOfWeekMask(nDayOfWeek);
if (nWWMask & nDayMask)
{
_AddDay(dtWeekDay);
}
dtWeekDay += COleDateTimeSpan(1);
}
if (GetViewDayCount() == 0)
{
_AddDay(GetDateTimeDay(COleDateTime::GetCurrentTime()));
}
}
COleDateTimeSpan CXTPCalendarDayView::GetScaleInterval() const
{
int nSI_min = XTP_SAFE_GET1(GetCalendarOptions(), nDayView_ScaleInterval, 30);
return COleDateTimeSpan(0, 0, nSI_min, 0);
}
void CXTPCalendarDayView::SetScaleInterval(const COleDateTimeSpan spScaleInterval)
{
BOOL bValidSVal = CXTPCalendarUtils::GetTotalMinutes(spScaleInterval) >= 1;
ASSERT(bValidSVal);
if (m_pTimeScaleHeader && bValidSVal)
{
int nOldScaleInterval = XTP_SAFE_GET1(GetCalendarOptions(), nDayView_ScaleInterval, 30);
int nScaleInterval = (int)CXTPCalendarUtils::GetTotalMinutes(spScaleInterval);
if (nScaleInterval != nOldScaleInterval)
{
XTP_SAFE_SET1(GetCalendarOptions(), nDayView_ScaleInterval, nScaleInterval);
CXTPCalendarControl::CUpdateContext updateContext(m_pControl, xtpCalendarUpdateAll);
SendNotification(XTP_NC_CALENDAROPTIONSWASCHANGED, xtpCalendarDayView, 0);
SendNotification(XTP_NC_CALENDARVIEWTIMESCALEWASCHANGED, 0, 0);
}
}
}
COleDateTime CXTPCalendarDayView::GetScaleMinTime() const
{
return m_dtTimeScaleMin;
}
void CXTPCalendarDayView::SetScaleMinTime(const COleDateTime dtNewScaleMinTime)
{
if (dtNewScaleMinTime.GetStatus() == COleDateTime::valid)
{
m_dtTimeScaleMin = CXTPCalendarUtils::ResetDate(dtNewScaleMinTime);
CXTPCalendarControl::CUpdateContext updateContext(m_pControl, xtpCalendarUpdateRedraw);
}
}
COleDateTime CXTPCalendarDayView::GetScaleMaxTime() const
{
return m_dtTimeScaleMax;
}
void CXTPCalendarDayView::SetScaleMaxTime(const COleDateTime dtNewScaleMaxTime)
{
if (dtNewScaleMaxTime.GetStatus() == COleDateTime::valid)
{
m_dtTimeScaleMax = CXTPCalendarUtils::ResetDate(dtNewScaleMaxTime);
if ((double)dtNewScaleMaxTime > 1 && (double)dtNewScaleMaxTime < 2) // Special Case for 6:00 - 5:59 of second day.
m_dtTimeScaleMax += COleDateTimeSpan(1, 0, 0, 0);
CXTPCalendarControl::CUpdateContext updateContext(m_pControl, xtpCalendarUpdateRedraw);
}
//else
//{
// CXTPCalendarUtils::SetTime_235959(m_dtTimeScaleMax);
//
// CXTPCalendarControl::CUpdateContext updateContext(m_pControl, xtpCalendarUpdateRedraw);
//}
}
//void CXTPCalendarDayView::SetScaleMaxTime(const COleDateTime dtNewScaleMaxTime)
//{
// if (dtNewScaleMaxTime.GetStatus() == COleDateTime::valid)
// {
// m_dtTimeScaleMax = dtNewScaleMaxTime;
// if (m_dtTimeScaleMax.m_dt != 1.0)
// m_dtTimeScaleMax = CXTPCalendarUtils::ResetDate(m_dtTimeScaleMax);
// CXTPCalendarControl::CUpdateContext updateContext(m_pControl, xtpCalendarUpdateRedraw);
// }
//}
void CXTPCalendarDayView::SetScaleText(LPCTSTR strText)
{
XTP_SAFE_CALL1(m_pTimeScaleHeader, SetCaption(strText));
XTP_SAFE_SET1(GetCalendarOptions(), strDayView_ScaleLabel, strText);
SendNotification(XTP_NC_CALENDAROPTIONSWASCHANGED, xtpCalendarDayView, 0);
SendNotification(XTP_NC_CALENDARVIEWTIMESCALEWASCHANGED, 0, 0);
}
CString CXTPCalendarDayView::GetScaleText() const
{
return XTP_SAFE_GET2(m_pControl, GetCalendarOptions(), strDayView_ScaleLabel, _T(""));
}
void CXTPCalendarDayView::SetScale2Text(LPCTSTR strText)
{
XTP_SAFE_CALL1(m_pTimeScaleHeader2, SetCaption(strText));
XTP_SAFE_SET1(GetCalendarOptions(), strDayView_Scale2Label, strText);
SendNotification(XTP_NC_CALENDAROPTIONSWASCHANGED, xtpCalendarDayView, 0);
SendNotification(XTP_NC_CALENDARVIEWTIMESCALEWASCHANGED, 0, 0);
}
CString CXTPCalendarDayView::GetScale2Text() const
{
return XTP_SAFE_GET2(m_pControl, GetCalendarOptions(), strDayView_Scale2Label, _T(""));
}
void CXTPCalendarDayView::SetScale2TimeZone(const TIME_ZONE_INFORMATION* pTzInfo)
{
if (!pTzInfo || !m_pControl || !m_pControl->GetCalendarOptions())
{
ASSERT(FALSE);
return;
}
m_pControl->GetCalendarOptions()->tziDayView_Scale2TimeZone = *pTzInfo;
AdjustScale2TimeZone();
SendNotification(XTP_NC_CALENDAROPTIONSWASCHANGED, xtpCalendarDayView, 0);
SendNotification(XTP_NC_CALENDARVIEWTIMESCALEWASCHANGED, 0, 0);
}
void CXTPCalendarDayView::AdjustScale2TimeZone()
{
TIME_ZONE_INFORMATION tziCurrent;
::ZeroMemory(&tziCurrent, sizeof(tziCurrent));
if (::GetTimeZoneInformation(&tziCurrent) == TIME_ZONE_ID_INVALID)
{
ASSERT(FALSE);
return;
}
TIME_ZONE_INFORMATION tziScale2 = GetScale2TimeZone();
SYSTEMTIME systm00, systmScale1, systmScale2;
ZeroMemory(&systm00, sizeof(systm00));
ZeroMemory(&systmScale1, sizeof(systmScale1));
ZeroMemory(&systmScale2, sizeof(systmScale2));
::GetLocalTime(&systm00);
systm00.wHour = systm00.wMinute = systm00.wSecond = 0;
if (!CXTPCalendarUtils::SystemTimeToTzSpecificLocalTime(&tziCurrent,
&systm00, &systmScale1))
{
ASSERT(FALSE);
return;
}
if (!CXTPCalendarUtils::SystemTimeToTzSpecificLocalTime(&tziScale2,
&systm00, &systmScale2))
{
ASSERT(FALSE);
return;
}
COleDateTime dtScale1(systmScale1), dtScale2(systmScale2);
COleDateTimeSpan spScale2Offset = dtScale2 - dtScale1;
ASSERT((CXTPCalendarUtils::GetTotalSeconds(spScale2Offset) % 60) == 0);
int nTimeShift2_min = CXTPCalendarUtils::GetTotalMinutes(spScale2Offset);
XTP_SAFE_CALL1(m_pTimeScaleHeader2, SetTimeshift(nTimeShift2_min));
}
const TIME_ZONE_INFORMATION& CXTPCalendarDayView::GetScale2TimeZone() const
{
static TIME_ZONE_INFORMATION s_tzEmty = {0};
return XTP_SAFE_GET2(m_pControl, GetCalendarOptions(), tziDayView_Scale2TimeZone, s_tzEmty);
}
void CXTPCalendarDayView::ShowScale2(BOOL bShow)
{
if (!m_pTimeScaleHeader2 || !m_pControl)
{
ASSERT(FALSE);
return;
}
m_pTimeScaleHeader2->SetVisible(bShow);
m_pControl->GetCalendarOptions()->bDayView_Scale2Visible = bShow;
m_pControl->AdjustLayout();
SendNotification(XTP_NC_CALENDAROPTIONSWASCHANGED, xtpCalendarDayView, 0);
SendNotification(XTP_NC_CALENDARVIEWTIMESCALEWASCHANGED, 0, 0);
}
BOOL CXTPCalendarDayView::IsScale2Visible() const
{
return XTP_SAFE_GET2(m_pControl, GetCalendarOptions(), bDayView_Scale2Visible, FALSE);
}
COleDateTime CXTPCalendarDayView::GetViewDayDate(int nIndex) const
{
CXTPCalendarDayViewDay* pViewDay = GetViewDay(nIndex);
ASSERT(pViewDay);
return pViewDay ? pViewDay->m_dtDate :
GetDateTimeDay(CXTPCalendarUtils::GetCurrentTime());
}
void CXTPCalendarDayView::_ScrollDays(int nScrollDaysCount, BOOL bPrev)
{
ASSERT(nScrollDaysCount >= 1 && nScrollDaysCount <= 14);
nScrollDaysCount = min(14, max(1, nScrollDaysCount));
int nCount = GetViewDayCount();
if (!nCount)
{
ASSERT(FALSE);
return;
}
CXTPCalendarControl::CUpdateContext updateContext(m_pControl);
CXTPCalendarControl::CViewChangedContext viewChanged(this);
COleDateTimeSpan spDay(bPrev ? -1 : 1, 0, 0, 0);
COleDateTime dtNewDay = GetViewDayDate(bPrev ? 0 : nCount-1);
for (int i = 0; i < nScrollDaysCount; i++)
{
dtNewDay += spDay;
CXTPCalendarDayViewDay* pDay = new CXTPCalendarDayViewDay(this, dtNewDay);
if (pDay)
{
// when a day scrolls, the tooltip should be hidden
// moreover without this check there was a crash when Calendar.Unicode.ocx is built on VC6
// and vb calendar sample tried scrolling days (with keyboard) and tooltip was active
// possible reason of the crash was calling HideToolTip from the smart pointer destructor (invoked by RemoveAt)
// when a pointer on the call stack became invalid
if (m_pControl)
m_pControl->HideToolTip();
m_arDays.RemoveAt(bPrev ? nCount-1 : 0);
m_arDays.InsertAt(bPrev ? 0 : nCount-1, pDay);
pDay->Populate(dtNewDay);
}
}
}
void CXTPCalendarDayView::ScrollDaysToPrev(int nScrollDaysCount)
{
_ScrollDays(nScrollDaysCount, TRUE);
}
void CXTPCalendarDayView::ScrollDaysToNext(int nScrollDaysCount)
{
_ScrollDays(nScrollDaysCount, FALSE);
}
BOOL CXTPCalendarDayView::IsExpandDown() const
{
int nDays = GetViewDayCount();
for (int nDay = 0; nDay < nDays; nDay++)
{
CXTPCalendarDayViewDay* pDay = GetViewDay(nDay);
ASSERT(pDay);
if (!pDay)
continue;
int nGroupsCount = pDay->GetViewGroupsCount();
for (int i = 0; i < nGroupsCount; i++)
{
if (pDay->GetViewGroup(i) && pDay->GetViewGroup(i)->IsExpandDown())
return TRUE;
}
}
return FALSE;
}
BOOL CXTPCalendarDayView::IsExpandUp() const
{
int nDays = GetViewDayCount();
for (int nDay = 0; nDay < nDays; nDay++)
{
CXTPCalendarDayViewDay* pDay = GetViewDay(nDay);
ASSERT(pDay);
if (!pDay)
continue;
int nGroupsCount = pDay->GetViewGroupsCount();
for (int i = 0; i < nGroupsCount; i++)
{
if (pDay->GetViewGroup(i) && pDay->GetViewGroup(i)->IsExpandUp())
return TRUE;
}
}
return FALSE;
}
CXTPCalendarDayViewDay* CXTPCalendarDayView::GetDay(COleDateTime dtDay)
{
dtDay = GetDateTimeDay(dtDay);
int nDays = GetViewDayCount();
for (int i = 0; i < nDays; i++)
{
COleDateTime dtDay_I = GetViewDayDate(i);
if (CXTPCalendarUtils::IsEqual(dtDay, dtDay_I))
{
return GetViewDay(i);
}
}
return NULL;
}
void CXTPCalendarDayView::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
{
CSelectionChangedContext selChanged(this);
TBase::OnKeyDown(nChar, nRepCnt, nFlags);
if (nChar == VK_LEFT
|| nChar == VK_RIGHT
|| nChar == VK_UP
|| nChar == VK_DOWN
|| nChar == VK_PRIOR
|| nChar == VK_NEXT
|| nChar == VK_HOME
|| nChar == VK_END)
{
CXTPCalendarControl::CUpdateContext updateContext(m_pControl, xtpCalendarUpdateRedraw);
UnselectAllEvents();
BOOL bVKShift = (GetKeyState(VK_SHIFT) < 0);
BOOL bVKControl = (GetKeyState(VK_CONTROL) < 0);
COleDateTimeSpan spCell = GetCellDuration();
COleDateTimeSpan spDay(1, 0, 0, 0);
COleDateTime dtNewSelEnd = m_selectedBlock.dtEnd;
BOOL bEndIsEnd = m_selectedBlock.dtEnd > m_selectedBlock.dtBegin || !bVKShift;
int nSelCell = GetCellNumber(GetDateTimeTime(m_selectedBlock.dtEnd -
COleDateTimeSpan(0, 0, 0, bEndIsEnd ? 1 : 0)), bEndIsEnd);
CXTPDrawHelpers::KeyToLayout(m_pControl, nChar);
int nDVCount = GetViewDayCount();
COleDateTime dtFirstDay = GetViewDayDate(0);
COleDateTime dtLastDay = GetViewDayDate(nDVCount-1);
int iStP = RecalcMinColumnWidth();
int iGrCnt = GetTotalGroupsCount();
int iResCnt = 0;
if (GetResources())
{
iResCnt = GetResources()->GetCount();
if (iResCnt > 0)
iResCnt = iGrCnt / iResCnt;
//TRACE(_T("iGrCnt=%d iResCnt=%d\n"), iGrCnt, iResCnt);
}
SCROLLINFO si;
int nScrollStep = 1;
if (GetScrollBarInfoH(&si, &nScrollStep))
{
int nCurPos = si.nPos;
int nLimit = m_pControl->GetScrollLimit(SB_HORZ);
if (bVKControl && iStP > 0 && iResCnt > 1) //control horizontal scrolling for multi-schedules case
{
if (nChar == VK_LEFT)
{
if (bVKShift)
nCurPos = max(nCurPos - iResCnt * iStP, 0);
else
nCurPos = max(nCurPos - iStP, 0);
}
else if (nChar == VK_RIGHT)
{
if (bVKShift)
nCurPos = min(nCurPos + iResCnt * iStP, nLimit);
else
nCurPos = min(nCurPos + iStP, nLimit);
}
else if (nChar == VK_PRIOR)
{
if (bVKShift)
nCurPos = max(nCurPos - 2 * (int)si.nPage, 0);
else
nCurPos = max(nCurPos - (int)si.nPage, 0);
}
else if (nChar == VK_NEXT)
{
if (bVKShift)
nCurPos = min(nCurPos + 2 * (int)si.nPage, nLimit);
else
nCurPos = min(nCurPos + (int)si.nPage, nLimit);
}
else if (nChar == VK_HOME)
{
nCurPos = 0;
}
else if (nChar == VK_END)
{
nCurPos = nLimit;
}
int nCurPos_raw = nCurPos;
ScrollH(nCurPos, nCurPos_raw);
m_pControl->SetScrollPos(SB_HORZ, nCurPos, TRUE);
m_pControl->AdjustScrollBar();
return;
}
COleDateTime dtNSel = GetDateTimeDay(dtNewSelEnd);
if (nChar == VK_LEFT)
{
BOOL bCanHScrollGroupsLeft = GetIsCanHScrollGroupsLeft(dtNewSelEnd, bVKShift);
if (!m_bScrollH_Disabled || dtNSel > dtFirstDay || bCanHScrollGroupsLeft)
{
if (!bVKShift && m_selectedBlock.nGroupIndex > 0)
{
m_selectedBlock.nGroupIndex--;
}
else if (!bVKShift && m_selectedBlock.nGroupIndex == 0)
{
dtNewSelEnd -= spDay;
CXTPCalendarDayViewDay* pDay = GetDay(dtNewSelEnd);
if (!bVKShift && pDay)
{
if (m_selectedBlock.bAllDayEvent && iResCnt > 1)
m_selectedBlock.nGroupIndex = pDay->GetViewGroupsCount() - 1;
}
}
if (m_selectedBlock.bAllDayEvent)
{
nCurPos = max(nCurPos - iStP, 0);
ScrollH(nCurPos, nCurPos);
m_pControl->SetScrollPos(SB_HORZ, nCurPos, TRUE);
m_pControl->AdjustScrollBar();
}
}
}
else if (nChar == VK_RIGHT)
{
BOOL bCanHScrollGroupsRight = GetIsCanHScrollGroupsRight(dtNewSelEnd, bVKShift);
if (!m_bScrollH_Disabled || dtNSel < dtLastDay || bCanHScrollGroupsRight)
{
CXTPCalendarDayViewDay* pDay = GetDay(dtNewSelEnd);
if (!bVKShift && pDay)
{
if (m_selectedBlock.nGroupIndex < pDay->GetViewGroupsCount() - 1)
{
m_selectedBlock.nGroupIndex++;
}
else
{
dtNewSelEnd += spDay;
m_selectedBlock.nGroupIndex = 0;
}
}
else //outside the range
{
dtNewSelEnd += spDay;
m_selectedBlock.nGroupIndex = 0;
}
//TRACE(_T("nGroupIndex=%d %s nCurPos=%d\n"), m_selectedBlock.nGroupIndex, dtNewSelEnd.Format(_T("%d %m %Y")), nCurPos);
if (m_selectedBlock.bAllDayEvent)
{
nCurPos = min(nCurPos + iStP, nLimit);
ScrollH(nCurPos, nCurPos);
m_pControl->SetScrollPos(SB_HORZ, nCurPos, TRUE);
m_pControl->AdjustScrollBar();
}
}
}
else if (nChar == VK_UP)
{
BOOL bRange = !m_bScrollV_Disabled || nSelCell > m_LayoutX.m_nTopRow;
if (nSelCell > 0 && bRange)
{
dtNewSelEnd = CXTPCalendarUtils::UpdateTime(dtNewSelEnd, GetCellTime(nSelCell));
}
if (m_selectedBlock.bAllDayEvent)
{
m_selectedBlock.bAllDayEvent = FALSE;
dtNewSelEnd -= spDay;
}
}
else if (nChar == VK_DOWN)
{
BOOL bRange = !m_bScrollV_Disabled || nSelCell < m_LayoutX.m_nTopRow + m_LayoutX.m_nVisibleRowCount - 1;
if (nSelCell + 1 < GetRowCount() && bRange)
{
dtNewSelEnd = CXTPCalendarUtils::UpdateTime(dtNewSelEnd, GetCellTime(nSelCell+1)) + spCell;
if (nSelCell == GetRowCount()-2)
{
dtNewSelEnd -= COleDateTimeSpan(0, 0, 0, 1);
}
}
}
else if (nChar == VK_PRIOR)
{
if (!m_bScrollV_Disabled)
{
nSelCell = max(1, nSelCell - m_LayoutX.m_nVisibleRowCount + 1);
m_LayoutX.m_nTopRow = max(0, m_LayoutX.m_nTopRow - m_LayoutX.m_nVisibleRowCount);
dtNewSelEnd = CXTPCalendarUtils::UpdateTime(dtNewSelEnd, GetCellTime(nSelCell));
CXTPCalendarControl::CUpdateContext updateContext1(m_pControl, xtpCalendarUpdateScrollBar);
}
}
else if (nChar == VK_NEXT)
{
if (!m_bScrollV_Disabled)
{
nSelCell = min(max(0, GetRowCount()-1), nSelCell + m_LayoutX.m_nVisibleRowCount);
m_LayoutX.m_nTopRow += m_LayoutX.m_nVisibleRowCount;
dtNewSelEnd = CXTPCalendarUtils::UpdateTime(dtNewSelEnd, GetCellTime(nSelCell)) + spCell;
if (nSelCell == GetRowCount()-1)
{
dtNewSelEnd -= COleDateTimeSpan(0, 0, 0, 1);
}
CXTPCalendarControl::CUpdateContext updateContext1(m_pControl, xtpCalendarUpdateScrollBar);
}
}
ProcessCellSelection(dtNewSelEnd, bVKShift, m_selectedBlock.bAllDayEvent, m_selectedBlock.nGroupIndex);
}
else
{
if (nChar == VK_LEFT)
{
BOOL bCanHScrollGroupsLeft = GetIsCanHScrollGroupsLeft(dtNewSelEnd, bVKShift);
if (!m_bScrollH_Disabled || GetDateTimeDay(dtNewSelEnd) > dtFirstDay || bCanHScrollGroupsLeft)
{
if (bCanHScrollGroupsLeft)
{
m_selectedBlock.nGroupIndex--;
}
else
{
dtNewSelEnd -= spDay;
CXTPCalendarDayViewDay* pDay = GetDay(dtNewSelEnd);
if (!bVKShift && pDay)
{
m_selectedBlock.nGroupIndex = pDay->GetViewGroupsCount() - 1;
}
}
}
}
else if (nChar == VK_RIGHT)
{
BOOL bCanHScrollGroupsRight = GetIsCanHScrollGroupsRight(dtNewSelEnd, bVKShift);
if (!m_bScrollH_Disabled || GetDateTimeDay(dtNewSelEnd) < dtLastDay || bCanHScrollGroupsRight)
{
if (bCanHScrollGroupsRight)
{
m_selectedBlock.nGroupIndex++;
}
else
{
dtNewSelEnd += spDay;
m_selectedBlock.nGroupIndex = 0;
}
}
}
else if (nChar == VK_UP)
{
BOOL bRange = !m_bScrollV_Disabled || nSelCell > m_LayoutX.m_nTopRow;
if (nSelCell > 0 && bRange)
{
dtNewSelEnd = CXTPCalendarUtils::UpdateTime(dtNewSelEnd, GetCellTime(nSelCell));
}
if (m_selectedBlock.bAllDayEvent)
{
m_selectedBlock.bAllDayEvent = FALSE;
dtNewSelEnd -= spDay;
}
}
else if (nChar == VK_DOWN)
{
BOOL bRange = !m_bScrollV_Disabled || nSelCell < m_LayoutX.m_nTopRow + m_LayoutX.m_nVisibleRowCount - 1;
if (nSelCell + 1 < GetRowCount() && bRange)
{
dtNewSelEnd = CXTPCalendarUtils::UpdateTime(dtNewSelEnd, GetCellTime(nSelCell+1)) + spCell;
if (nSelCell == GetRowCount()-2)
{
dtNewSelEnd -= COleDateTimeSpan(0, 0, 0, 1);
}
}
}
else if (nChar == VK_PRIOR)
{
if (!m_bScrollV_Disabled)
{
nSelCell = max(1, nSelCell - m_LayoutX.m_nVisibleRowCount + 1);
m_LayoutX.m_nTopRow = max(0, m_LayoutX.m_nTopRow - m_LayoutX.m_nVisibleRowCount);
dtNewSelEnd = CXTPCalendarUtils::UpdateTime(dtNewSelEnd, GetCellTime(nSelCell));
CXTPCalendarControl::CUpdateContext updateContext1(m_pControl, xtpCalendarUpdateScrollBar);
}
}
else if (nChar == VK_NEXT)
{
if (!m_bScrollV_Disabled)
{
nSelCell = min(max(0, GetRowCount()-1), nSelCell + m_LayoutX.m_nVisibleRowCount);
m_LayoutX.m_nTopRow += m_LayoutX.m_nVisibleRowCount;
dtNewSelEnd = CXTPCalendarUtils::UpdateTime(dtNewSelEnd, GetCellTime(nSelCell)) + spCell;
if (nSelCell == GetRowCount()-1)
{
dtNewSelEnd -= COleDateTimeSpan(0, 0, 0, 1);
}
CXTPCalendarControl::CUpdateContext updateContext1(m_pControl, xtpCalendarUpdateScrollBar);
}
}
ProcessCellSelection(dtNewSelEnd, bVKShift, m_selectedBlock.bAllDayEvent, m_selectedBlock.nGroupIndex);
}
}
}
BOOL CXTPCalendarDayView::GetIsCanHScrollGroupsLeft(COleDateTime dtNewSelEnd, BOOL bVKShift)
{
BOOL bCanHScrollGroupsLeft = FALSE;
CXTPCalendarDayViewDay* pDay = GetDay(dtNewSelEnd);
if(!bVKShift && m_selectedBlock.nGroupIndex > 0 && pDay->GetViewGroupsCount() > 1)
bCanHScrollGroupsLeft = TRUE;
return bCanHScrollGroupsLeft;
}
BOOL CXTPCalendarDayView::GetIsCanHScrollGroupsRight(COleDateTime dtNewSelEnd, BOOL bVKShift)
{
BOOL bCanHScrollGroupsRight = FALSE;
CXTPCalendarDayViewDay* pDay = GetDay(dtNewSelEnd);
if (!bVKShift && pDay && m_selectedBlock.nGroupIndex < pDay->GetViewGroupsCount() - 1 && pDay->GetViewGroupsCount() > 1)
bCanHScrollGroupsRight = TRUE;
return bCanHScrollGroupsRight;
}
COleDateTime CXTPCalendarDayView::GetDateTimeDay(const COleDateTime& dt) const
{
if ((DATE)m_dtTimeScaleMax <= 1)
return CXTPCalendarUtils::ResetTime(dt);
return CXTPCalendarUtils::ResetTime(dt - m_dtTimeScaleMin);
}
COleDateTime CXTPCalendarDayView::GetDateTimeTime(const COleDateTime& dt) const
{
if ((DATE)m_dtTimeScaleMax <= 1)
return CXTPCalendarUtils::ResetDate(dt);
return CXTPCalendarUtils::ResetDate((DATE)dt - m_dtTimeScaleMin) + m_dtTimeScaleMin;
}
void CXTPCalendarDayView::ProcessCellSelection(COleDateTime dtNewSelEnd,
BOOL bFixSelBegin, BOOL bAllDayEventSel, int nGroupIndex)
{
int nCount = GetViewDayCount();
if (!nCount)
{
ASSERT(FALSE);
return;
}
CXTPCalendarControl::CUpdateContext updateContext(m_pControl, xtpCalendarUpdateRedraw);
COleDateTimeSpan spDay(1, 0, 0, 0);
COleDateTimeSpan spCell = GetCellDuration();
COleDateTimeSpan spSelStep = bAllDayEventSel ? spDay : spCell;
COleDateTime dtFirstDay = GetViewDayDate(0);
COleDateTime dtSelBegin_prev = m_selectedBlock.dtBegin;
COleDateTime dtSelEnd_prev = m_selectedBlock.dtEnd;
if (CXTPCalendarUtils::IsEqual(m_selectedBlock.dtEnd, m_selectedBlock.dtBegin))
{
int nSelRow = GetTopRow() + min(2, GetVisibleRowCount());
m_selectedBlock.dtBegin = CXTPCalendarUtils::UpdateTime(dtFirstDay, GetCellTime(nSelRow));
m_dtSelectionStart = m_selectedBlock.dtBegin;
m_selectedBlock.dtEnd = m_selectedBlock.dtBegin + spCell;
}
m_selectedBlock.dtEnd = dtNewSelEnd;
if (!bFixSelBegin)
{
m_selectedBlock.dtBegin = m_selectedBlock.dtEnd - spSelStep;
m_dtSelectionStart = m_selectedBlock.dtBegin;
}
else if (CXTPCalendarUtils::IsEqual(m_selectedBlock.dtEnd, m_selectedBlock.dtBegin)
|| (!bAllDayEventSel
&& m_selectedBlock.dtEnd < m_selectedBlock.dtBegin
&& dtSelEnd_prev > dtSelBegin_prev))
{
m_selectedBlock.dtEnd -= spSelStep;
}
m_selectedBlock.bAllDayEvent = bAllDayEventSel;
m_selectedBlock.nGroupIndex = nGroupIndex;
//===========================================================================
int nDVCount = GetViewDayCount();
COleDateTime dtLastDay = GetViewDayDate(nDVCount-1);
COleDateTime& rdtSel1 = m_selectedBlock.dtEnd < m_selectedBlock.dtBegin ?
m_selectedBlock.dtEnd : m_selectedBlock.dtBegin;
COleDateTime& rdtSel2 = m_selectedBlock.dtEnd > m_selectedBlock.dtBegin ?
m_selectedBlock.dtEnd : m_selectedBlock.dtBegin;
COleDateTime dtSelDay1 = bAllDayEventSel ? rdtSel1 : GetDateTimeDay(rdtSel1);
COleDateTime dtSelDay2 = GetDateTimeDay(rdtSel2 - COleDateTimeSpan(0, 0, 0, 1));
//---------------------------------------------------------------------------
if (!m_bScrollH_Disabled)
{
if (dtSelDay1 < dtFirstDay)
ScrollDaysToPrev();
else if (dtSelDay2 > dtLastDay)
ScrollDaysToNext();
}
//---------------------------------------------------------------------------
// update variables after scrolling
nDVCount = GetViewDayCount();
dtFirstDay = GetViewDayDate(0);
dtLastDay = GetViewDayDate(nDVCount-1);
if (dtSelDay1 < dtFirstDay || (!bFixSelBegin && dtSelDay2 >= dtLastDay))
{
if (bFixSelBegin)
{
rdtSel1 = CXTPCalendarUtils::UpdateTime(dtFirstDay, rdtSel1);
rdtSel2 = rdtSel1 + spSelStep;
}
}
//---------------------------------------------------------------------------
if (dtSelDay2 > dtLastDay || (!bFixSelBegin && dtSelDay1 <= dtFirstDay))
rdtSel2 = rdtSel1 + spSelStep;
//---------------------------------------------------------------------------
BOOL bEndIsEnd = m_selectedBlock.dtEnd > m_selectedBlock.dtBegin;
int nSelEndCell = GetCellNumber(GetDateTimeTime(m_selectedBlock.dtEnd -
COleDateTimeSpan(0, 0, 0, bEndIsEnd ? 1 : 0)), bEndIsEnd);
if (nSelEndCell < m_LayoutX.m_nTopRow && !bAllDayEventSel)
{
if (!m_bScrollV_Disabled)
{
m_LayoutX.m_nTopRow = min(max(0, nSelEndCell), max(0, GetRowCount()-1));
CXTPCalendarControl::CUpdateContext updateContext1(m_pControl, xtpCalendarUpdateScrollBar);
}
}
else if (nSelEndCell >= m_LayoutX.m_nTopRow + m_LayoutX.m_nVisibleRowCount && !bAllDayEventSel)
{
if (!m_bScrollV_Disabled)
{
m_LayoutX.m_nTopRow = nSelEndCell - m_LayoutX.m_nVisibleRowCount + 1;
m_LayoutX.m_nTopRow = min(max(0, m_LayoutX.m_nTopRow), max(0, GetRowCount() - 1));
CXTPCalendarControl::CUpdateContext updateContext1(m_pControl, xtpCalendarUpdateScrollBar);
}
}
if (!bAllDayEventSel || m_ptLBtnUpMousePos.x == m_ptLBtnDownMousePos.x)
{
if (_EnsureVisibleSelectionH())
{
GetCalendarControl()->AdjustLayout();
CXTPCalendarControl::CUpdateContext updateContext1(m_pControl, xtpCalendarUpdateScrollBar);
}
}
CSelectionChangedContext selChanged(this, xtpCalendarSelectionDays);
}
BOOL CXTPCalendarDayView::_EnsureVisibleSelectionH()
{
if (!m_selectedBlock.IsValid())
return FALSE;
CXTPCalendarViewDay* pVDay = _GetViewDay(m_selectedBlock.bAllDayEvent ? m_selectedBlock.dtEnd : GetDateTimeDay(m_selectedBlock.dtEnd));
ASSERT(pVDay);
if (!pVDay)
return FALSE;
CRect rcGroup = pVDay->GetDayRect();
{
CXTPCalendarViewGroup* pVGroup = pVDay->GetViewGroup_(m_selectedBlock.nGroupIndex);
ASSERT(pVGroup);
if (pVGroup)
rcGroup = pVGroup->GetRect();
}
CRect rcVisible = _GetScrollRectClient();
int nNewScrollPos = m_nScrollOffsetX;
if (rcGroup.left < rcVisible.left)
{
nNewScrollPos -= rcVisible.left - rcGroup.left;
if (nNewScrollPos <= 2) nNewScrollPos = 0;
}
else if (rcGroup.right > rcVisible.right)
{
nNewScrollPos += rcGroup.right - rcVisible.right + 1;
}
if (nNewScrollPos != m_nScrollOffsetX)
{
ScrollH(nNewScrollPos, nNewScrollPos);
return TRUE;
}
return FALSE;
}
BOOL CXTPCalendarDayView::EnsureVisibleH(CXTPCalendarViewGroup* pViewGroup)
{
ASSERT(pViewGroup);
if (!pViewGroup)
return FALSE;
SCROLLINFO si;
if (!GetScrollBarInfoH(&si))
return FALSE;
CRect rcVisible = _GetScrollRectClient();
CRect rcGroup = pViewGroup->GetRect();
int nNewScrollPos = m_nScrollOffsetX;
if (rcGroup.left < rcVisible.left)
{
nNewScrollPos -= rcVisible.left - rcGroup.left;
}
else if (rcGroup.right > rcVisible.right)
{
nNewScrollPos += rcGroup.right - rcVisible.right + 1;
}
if (nNewScrollPos != m_nScrollOffsetX)
{
ScrollH(nNewScrollPos, nNewScrollPos);
GetCalendarControl()->AdjustLayout();
CXTPCalendarControl::CUpdateContext updateContext(m_pControl, xtpCalendarUpdateScrollBar);
return TRUE;
}
return FALSE;
}
BOOL CXTPCalendarDayView::_EnsureVisibleH(CXTPCalendarViewEvent* pViewEvent)
{
ASSERT(pViewEvent);
CXTPCalendarViewGroup* pVGroup = pViewEvent ? pViewEvent->GetViewGroup_() : NULL;
ASSERT(pVGroup);
if (!pVGroup)
return FALSE;
SCROLLINFO si;
if (!GetScrollBarInfoH(&si))
return FALSE;
CRect rcVisible = _GetScrollRectClient();
CRect rcObj = pViewEvent->GetEventRect();
CRect rcGroup = pVGroup->GetRect();
if (pViewEvent->IsMultidayEvent()
&& (pViewEvent->GetMultiDayEventFlags() & xtpCalendarMultiDayMaster))
{
rcObj.left = max(rcObj.left, rcVisible.left);
rcObj.right = min(rcObj.right, rcVisible.right);
rcGroup.right = rcGroup.left + rcVisible.Width();
}
int nNewScrollPos = m_nScrollOffsetX;
if (rcObj.left < rcVisible.left)
nNewScrollPos -= rcVisible.left - rcGroup.left;
else if (rcObj.right > rcVisible.right)
nNewScrollPos += rcGroup.right - rcVisible.right + 1;
if (nNewScrollPos != m_nScrollOffsetX)
{
ScrollH(nNewScrollPos, nNewScrollPos);
return TRUE;
}
return FALSE;
}
BOOL CXTPCalendarDayView::_EnsureVisibleV(CXTPCalendarViewEvent* pViewEvent)
{
if (!pViewEvent || !pViewEvent->GetEvent() || !GetCalendarControl() ||
!XTP_SAFE_GET2(pViewEvent, GetViewGroup_(), GetViewDay_(), NULL) )
{
ASSERT(FALSE);
return FALSE;
}
//---------------------------------------------------------------------------
if (pViewEvent->IsMultidayEvent())
{
int nEventIndex = (pViewEvent->m_rcEvent.top - m_LayoutX.m_rcAllDayEvents.top) / m_LayoutX.m_nAllDayEventHeight + m_LayoutX.m_nTopAllDayRow;
if (nEventIndex >= m_LayoutX.m_nTopAllDayRow + m_LayoutX.m_nVisibleAllDayCount)
{
m_LayoutX.m_nTopAllDayRow = nEventIndex - m_LayoutX.m_nVisibleAllDayCount + 1;
return TRUE;
}
else if (nEventIndex < m_LayoutX.m_nTopAllDayRow)
{
m_LayoutX.m_nTopAllDayRow = nEventIndex;
return TRUE;
}
return FALSE;
}
//---------------------------------------------------------------------------
COleDateTime dtDay = XTP_SAFE_GET3(pViewEvent, GetViewGroup_(), GetViewDay_(), GetDayDate(), (DATE)0);
dtDay = GetDateTimeDay(dtDay);
COleDateTime dtStart = pViewEvent->GetEvent()->GetStartTime();
COleDateTime dtEnd = pViewEvent->GetEvent()->GetEndTime();
COleDateTime stSTime = GetDateTimeTime(dtStart);
COleDateTime stETime = GetDateTimeTime(dtEnd);
if (CXTPCalendarUtils::IsZeroTime(stETime))
stETime = CXTPCalendarUtils::SetTime_235959(stETime);
int nSCell = 0;
int nECell = max(0, GetRowCount() - 1);
if (GetDateTimeDay(dtStart) == dtDay)
nSCell = GetCellNumber(stSTime, FALSE);
if (GetDateTimeDay(dtEnd) == dtDay)
nECell = GetCellNumber(stETime, TRUE);
if (nSCell < m_LayoutX.m_nTopRow)
{
m_LayoutX.m_nTopRow = min(max(0, nSCell-1), max(0, GetRowCount()-1));
return TRUE;
}
else if (nECell >= m_LayoutX.m_nTopRow + m_LayoutX.m_nVisibleRowCount)
{
int nTopRowPrev = m_LayoutX.m_nTopRow;
m_LayoutX.m_nTopRow = nECell - m_LayoutX.m_nVisibleRowCount + 1;
m_LayoutX.m_nTopRow = min(max(0, m_LayoutX.m_nTopRow), max(0, GetRowCount()-1));
m_LayoutX.m_nTopRow = min(max(0, nSCell-1), m_LayoutX.m_nTopRow);
if (nTopRowPrev != m_LayoutX.m_nTopRow)
{
return TRUE;
}
}
return FALSE;
}
BOOL CXTPCalendarDayView::EnsureVisible(CXTPCalendarViewEvent* pViewEvent)
{
ASSERT(pViewEvent);
if (!pViewEvent)
return FALSE;
BOOL bChanged1 = _EnsureVisibleH(pViewEvent);
BOOL bChanged2 = _EnsureVisibleV(pViewEvent);
if (bChanged1 || bChanged2)
{
GetCalendarControl()->AdjustLayout();
CXTPCalendarControl::CUpdateContext updateContext(m_pControl, xtpCalendarUpdateScrollBar);
}
ASSERT(pViewEvent->IsVisible());
return TRUE;
}
BOOL CXTPCalendarDayView::EnsureVisibleH(CXTPCalendarViewEvent* pViewEvent)
{
ASSERT(pViewEvent);
if (!pViewEvent)
return FALSE;
BOOL bChanged1 = _EnsureVisibleH(pViewEvent);
if (bChanged1)
{
GetCalendarControl()->AdjustLayout();
CXTPCalendarControl::CUpdateContext updateContext(m_pControl, xtpCalendarUpdateScrollBar);
}
ASSERT(pViewEvent->IsVisible());
return TRUE;
}
CXTPCalendarViewEvent* CXTPCalendarDayView::FindEventToEditByTAB(COleDateTime dtMinStart,
BOOL bReverse, CXTPCalendarEvent* pAfterEvent)
{
CXTPCalendarViewEvent* pViewEvent = TBase::FindEventToEditByTAB(dtMinStart, bReverse, pAfterEvent);
if (pViewEvent)
{
if (EnsureVisible(pViewEvent))
return pViewEvent;
}
return NULL;
}
COleDateTime CXTPCalendarDayView::GetNextTimeEditByTAB() const
{
COleDateTime dtSel1 = min(m_selectedBlock.dtBegin, m_selectedBlock.dtEnd);
COleDateTime dtSel2 = max(m_selectedBlock.dtBegin, m_selectedBlock.dtEnd);
COleDateTime dtSel1Day = GetDateTimeDay(dtSel1);
COleDateTime dtSel2Day = GetDateTimeDay(dtSel2);
int nDVCount = GetViewDayCount();
COleDateTime dtFirstDay = GetViewDayDate(0);
COleDateTime dtLastDay = GetViewDayDate(nDVCount-1);
if (dtSel1Day >= dtFirstDay && dtSel1Day <= dtLastDay)
return dtSel1;
else if (dtSel2Day >= dtFirstDay && dtSel2Day <= dtLastDay)
return dtSel2;
return TBase::GetNextTimeEditByTAB();
}
void CXTPCalendarDayView::UpdateNextTimeEditByTAB(COleDateTime dtNext, BOOL bReverse, BOOL bReset)
{
m_selectedBlock.dtBegin = m_selectedBlock.dtEnd = GetNextTimeEditByTAB();
m_dtSelectionStart = m_selectedBlock.dtBegin;
COleDateTime dtNextDay = GetDateTimeDay(dtNext);
COleDateTime dtCurrDay = GetDateTimeDay(GetNextTimeEditByTAB());
if (dtNextDay != dtCurrDay || bReset)
{
m_selectedBlock.dtBegin = m_selectedBlock.dtEnd = dtNextDay;
m_dtSelectionStart = m_selectedBlock.dtBegin;
COleDateTime dtFirstDay = GetViewDayDate(bReverse ? GetViewDayCount()-1 : 0);
if (dtNextDay == dtFirstDay || bReset)
{
if (bReverse)
{
m_selectedBlock.dtBegin = m_selectedBlock.dtEnd = dtNextDay + COleDateTimeSpan(1, 0, 0, 0);
m_selectedBlock.dtBegin = m_selectedBlock.dtEnd - GetCellDuration();
}
else
{
m_selectedBlock.dtEnd = m_selectedBlock.dtBegin + GetCellDuration();
}
ProcessCellSelection(m_selectedBlock.dtEnd, FALSE, FALSE, 0);
}
}
}
COleDateTimeSpan CXTPCalendarDayView::GetEventDurationMin() const
{
return GetCellDuration();
}
CXTPCalendarTimeZonePtr CXTPCalendarDayView::GetCurrentTimeZoneInfo() const
{
TIME_ZONE_INFORMATION tziCurrent;
::ZeroMemory(&tziCurrent, sizeof(tziCurrent));
if (::GetTimeZoneInformation(&tziCurrent) == TIME_ZONE_ID_INVALID)
{
ASSERT(FALSE);
return NULL;
}
return CXTPCalendarTimeZone::GetTimeZoneInfo(&tziCurrent);
}
CXTPCalendarTimeZonePtr CXTPCalendarDayView::GetScale2TimeZoneInfo() const
{
return CXTPCalendarTimeZone::GetTimeZoneInfo(&GetScale2TimeZone());
}
void CXTPCalendarDayView::ScrollToWorkDayBegin()
{
if (!m_pControl || !m_pControl->GetCalendarOptions())
{
ASSERT(FALSE);
return;
}
COleDateTime dtStartDate = GetViewDayDate(0);
COleDateTime dtSelBegin = CXTPCalendarUtils::UpdateTime(dtStartDate, m_pControl->GetCalendarOptions()->dtWorkDayStartTime);
COleDateTime dtSelEnd = dtSelBegin + GetCellDuration();
SetSelection(dtSelBegin, dtSelEnd, FALSE);
int nWDStartCell = GetCellNumber(m_pControl->GetCalendarOptions()->dtWorkDayStartTime, FALSE);
_ScrollV(nWDStartCell, nWDStartCell);
}
int CXTPCalendarDayView::_GetTimeScaleWith() const
{
if (m_bShowAllDayEventsOnly)
return 0;
int nWidth = XTP_SAFE_GET1(GetTimeScale(), GetWidth(), 0);
if (IsScale2Visible())
nWidth += XTP_SAFE_GET1(GetTimeScale(2), GetWidth(), 0);
return nWidth;
}
CRect CXTPCalendarDayView::_GetScrollRectClient() const
{
CXTPClientRect rcClient(GetCalendarControl());
rcClient.left += _GetTimeScaleWith();
rcClient.left = min(rcClient.left, rcClient.right);
return rcClient;
}
void CXTPCalendarDayView::ScrollToColumn(long lColumn)
{
ScrollToWorkDayBegin();
int iPos = lColumn;
int iStP = RecalcMinColumnWidth();
int iResCnt = 0;
if (GetResources())
iResCnt = GetResources()->GetCount();
SCROLLINFO si;
int nScrollStep = 1;
if (GetScrollBarInfoH(&si, &nScrollStep))
{
if (iStP > 0 && iResCnt > 1) //control horizontal scrolling for multi-schedules case
{
int nLimit = m_pControl->GetScrollLimit(SB_HORZ);
int nCurPos = min(iStP * (iPos - 1), nLimit);
ScrollH(nCurPos, nCurPos);
m_pControl->SetScrollPos(SB_HORZ, nCurPos, TRUE);
m_pControl->AdjustScrollBar();
}
}
}
/////////////////////////////////////////////////////////////////////////////