// XTPCalendarDayView.cpp: implementation of the CXTPCalendarDayView class. // // This file is a part of the XTREME CALENDAR MFC class library. // (c)1998-2008 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 "XTPCalendarData.h" #include "XTPCalendarDayView.h" #include "XTPCalendarDayViewTimeScale.h" #include "XTPCalendarUtils.h" #include "XTPCalendarPaintManager.h" #include "XTPCalendarTheme.h" #include "XTPCalendarThemeOffice2007.h" #include "XTPCalendarControl.h" #include "XTPCalendarRecurrencePattern.h" #include "XTPCalendarNotifications.h" #include "Common/XTPDrawHelpers.h" #include "Common/XTPVC50Helpers.h" #include #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_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_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_bMouseOutOfDragArea = FALSE; m_dtDraggingStartPoint = COleDateTime(0, 0, 0, 0, 0, 0); m_dwRedrawNowLineTimerID = 0; m_dtLastRedrawTime = CXTPCalendarUtils::GetCurrentTime(); m_ptLBtnDownMousePos = CPoint(0,0); } CXTPCalendarDayView::~CXTPCalendarDayView() { CMDTARGET_RELEASE(m_pTimeScaleHeader); CMDTARGET_RELEASE(m_pTimeScaleHeader2); ClearDays(); } XTPCalendarViewType CXTPCalendarDayView::GetViewType() { int nWWMask = m_pControl ? m_pControl->GetWorkWeekMask() : xtpCalendarDayMo_Fr; int nDaysCount = GetViewDayCount(); int nWWCount = CXTPCalendarUtils::GetDayOfWeekCount(nWWMask); if (nDaysCount != nWWCount && nDaysCount != 7) { return xtpCalendarDayView; } int nFirstDayOfWeek = m_pControl ? m_pControl->GetFirstDayOfWeek() : xtpCalendarDayMonday; int nNextWWeekIdx = CXTPCalendarUtils::GetDayOfWeekIndex(nFirstDayOfWeek); 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(); return (DATE)dblTime; } COleDateTimeSpan CXTPCalendarDayView::GetCellDuration() const { return m_pTimeScaleHeader ? m_pTimeScaleHeader->GetScaleInterval() : (double)0; } int CXTPCalendarDayView::GetCellNumber(COleDateTime dtTime, BOOL bForEndTime) const { double dblTime = (double)CXTPCalendarUtils::ResetDate(dtTime); double dblEpsilon = XTP_HALF_SECOND * (bForEndTime ? -1 : 1); double dblCellDur = (double)GetCellDuration(); if (dblCellDur <= XTP_HALF_SECOND) { dblCellDur = XTP_HALF_SECOND * 2 * 60 * 30; } int nCell = int(dblTime / dblCellDur + dblEpsilon); 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 (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 (nPos_raw < 0) { ScrollDaysToPrev(); } else if (nPos_raw > nXmax) { ScrollDaysToNext(); } } } BOOL CXTPCalendarDayView::GetScrollBarInfoV(SCROLLINFO* pSI) { ASSERT(pSI); if (!pSI || m_bScrollV_Disabled) { return FALSE; } 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) { ASSERT(pSI); if (!pSI) return FALSE; int nMinColumnWidth = RecalcMinColumnWidth(); if (nMinColumnWidth <= 0) return FALSE; int nColumnsCount = GetTotalGroupsCount(); CRect rcClient = _GetScrollRectClient(); int nFullWidth = nColumnsCount * nMinColumnWidth; if (nFullWidth <= rcClient.Width()) return FALSE; pSI->nPos = min(m_nScrollOffsetX, nFullWidth); pSI->nMin = 0; pSI->nMax = nFullWidth-1; pSI->nPage = rcClient.Width(); if (pnScrollStep) *pnScrollStep = 15; return TRUE; } int CXTPCalendarDayView::GetTotalGroupsCount() { 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() { 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) / 6; else nMinColumnWidth = abs(nMinColumnWidth); } return nMinColumnWidth; } int CXTPCalendarDayView::GetAllDayEventsMaxCount() { 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() { 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_pTimeScaleHeader2, SetCaption(GetScale2Text()) ); XTP_SAFE_CALL1(m_pTimeScaleHeader2, SetVisible(IsScale2Visible()) ); TBase::AdjustLayout(pDC, rcView, FALSE); COleDateTimeSpan spDay(1, 0, 0, 0); double dRows = spDay / max((double)m_pTimeScaleHeader->GetScaleInterval(), XTP_HALF_SECOND * 2); m_LayoutX.m_nRowCount = (int)(dRows + XTP_HALF_SECOND); // to prevent loosing 1 : (int)(47.99999999999) = 47; // need 48 ! //CString str; str.Format(_T("RowsCount[%d] = %.15e (%.15e)"), m_nRowCount, dRows, (dRows + XTP_HALF_SECOND)); //AfxMessageBox(str); 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 (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); 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 nWidth = (rcView2.Width() / (nColumnsCount - nCols)) * pDay->GetViewGroupsCount(); 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 = CXTPCalendarUtils::ResetTime(m_selectedBlock.dtBegin); COleDateTime dtSelEndDay = CXTPCalendarUtils::ResetTime(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(); } } /* AdjustLayout2 Theme->AdjustLayout <- OnPostAdjustLayout2 Theme->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_pTimeScaleHeader2, SetCaption(GetScale2Text()) ); XTP_SAFE_CALL1(m_pTimeScaleHeader2, SetVisible(IsScale2Visible()) ); if (IsScale2Visible()) { AdjustScale2TimeZone(); } COleDateTimeSpan spDay(1, 0, 0, 0); double dRows = spDay / max((double)m_pTimeScaleHeader->GetScaleInterval(), XTP_HALF_SECOND * 2); m_LayoutX.m_nRowCount = (int)(dRows + XTP_HALF_SECOND); // 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 = CXTPCalendarUtils::ResetTime(m_selectedBlock.dtBegin); COleDateTime dtSelEndDay = CXTPCalendarUtils::ResetTime(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; } //=================================== CRect rcView = GetViewRect(); CDC memDC; CBitmap bmpCache; memDC.CreateCompatibleDC(pDC); VERIFY( bmpCache.CreateCompatibleBitmap(pDC, rcView.Width(), rcView.Height()) ); CXTPBitmapDC autoDCbmp(&memDC, &bmpCache); memDC.FillSolidRect(rcView, 0xFF); memDC.SetViewportOrg(m_nScrollOffsetX, 0); //------------------------------------------------ if (m_pTimeScaleHeader) m_pTimeScaleHeader->MoveTo(m_nScrollOffsetX); if (m_pTimeScaleHeader2 && IsScale2Visible()) m_pTimeScaleHeader2->MoveTo(m_nScrollOffsetX); //************************************************ TBase::OnDraw(&memDC); //************************************************ //int nTSWidth = _GetTimeScaleWith(); CXTPClientRect rcClient(GetCalendarControl()); pDC->BitBlt(rcClient.left, rcClient.top, rcClient.Width(), rcClient.Height(), &memDC, 0, 0, SRCCOPY); } void CXTPCalendarDayView::Draw(CDC* pDC) { pDC->SetBkMode(TRANSPARENT); // days int nCount = GetViewDayCount(); for (int i = nCount - 1; i >= 0; i--) { XTP_SAFE_CALL1(GetViewDay(i), Draw(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_DAY_VIEW* pHitTest) { 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()); int nHit = XTP_SAFE_GET2(pThemeX, GetPrevNextEventControllerPartX(), HitTest(&pt), 0); if (nHit) { XTP_CALENDAR_HITTESTINFO_DAY_VIEW emptyData; *pHitTest = emptyData; pHitTest->uHitCode = nHit; return TRUE; } //---------------------------------------------------- return TBase::HitTestEx(pt, pHitTest); } BOOL CXTPCalendarDayView::IsUseCellAlignedDraggingInTimeArea() { 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 (double(m_spDraggingStartOffset) != 0.0 && 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; } TRACE_DRAGGING(_T("OnDragging - [CXTPCalendarDayView] (point.x =%d, point.y =%d) \n"), point.x, point.y); XTP_CALENDAR_HITTESTINFO hitInfo2 = *pHitTest; XTP_CALENDAR_HITTESTINFO* pHitTest2 = &hitInfo2; BOOL bChanged = FALSE; XTP_CALENDAR_HITTESTINFO_DAY_VIEW hitTestInfo; // TODO: //if (IsOutOfDraggingRect(point, &hitTestInfo)) //{ // return FALSE; //} if (!HitTestEx(point, &hitTestInfo)) { return FALSE; } //======================================================================== BOOL bScrolled = FALSE; XTPCalendarDayViewScrollDirection scrollDir = GetNeededScrollDirection(point); if (scrollDir != xtpCalendarDayViewScrollNotNeeded) { if (scrollDir == xtpCalendarDayViewScrollUp) { TRACE_DRAGGING(_T("OnDragging::ScrollV up\n")); bScrolled = VertEventScroll(TRUE);//scroll up SetMouseOutOfDragArea(FALSE); if (bScrolled) { if (HitTestEx(point, &hitTestInfo)) { pHitTest2->dt = hitTestInfo.dt; } } } else if (scrollDir == xtpCalendarDayViewScrollDown) { TRACE_DRAGGING(_T("OnDragging::ScrollV down\n")); bScrolled = VertEventScroll(FALSE);//scroll down SetMouseOutOfDragArea(FALSE); if (bScrolled) { if (HitTestEx(point, &hitTestInfo)) { pHitTest2->dt = hitTestInfo.dt; } } } } if (IsOutOfClientRect(point, &hitTestInfo)) { TRACE_DRAGGING(_T("OnDragging::OutOfDragArea\n")); SetMouseOutOfDragArea(TRUE); StopVertEventScroll(); bScrolled = TRUE; return TRUE; } if (!bScrolled) { TRACE_DRAGGING(_T("OnDragging::In DragArea\n")); SetMouseOutOfDragArea(FALSE); StopVertEventScroll(); } // check drag on TimeScale: TRACE_DRAGGING(_T("OnDragging - [CXTPCalendarDayView] (hour =%d, minute =%d) \n"), pHitTest->dt.GetHour(), pHitTest->dt.GetMinute()); 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; if (bChanged) { if (!bAllDayEventArea && bAllMultiDayEventOrig && _IsDragModeCopyMove(m_eDraggingMode)) { m_ptrDraggingEventNew->SetDuration(GetCellDuration()); } else if (bAllDayEventArea && !bAllMultiDayEventOrig && _IsDragModeCopyMove(m_eDraggingMode)) { m_ptrDraggingEventNew->SetStartTime(CXTPCalendarUtils::ResetTime(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; } } } //------------------------------------------------------------------------ //COleDateTimeSpan spDurationNew = m_ptrDraggingEventNew->GetEndTime() - // m_ptrDraggingEventNew->GetStartTime(); // TRACE(_T("bAllDayEventArea =%d, Orig->IsAllDayEvent =%d, bAllMultiDayEventOrig =%d, New->GetDurationMinutes=%d [%s - %s]\n"), // bAllDayEventArea, m_ptrDraggingEventOrig->IsAllDayEvent(), //bAllMultiDayEventOrig, (int)spDurationNew.GetTotalMinutes(), //m_ptrDraggingEventNew->GetStartTime().Format(), //m_ptrDraggingEventNew->GetEndTime().Format()); 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) { static const int nVScrollZone = 20; CRect rcCtrl; if (!m_pControl) { return xtpCalendarDayViewScrollNotNeeded; } m_pControl->GetWindowRect(rcCtrl); CRect rcAllDayEvents = GetAllDayEventsRectangle(); SCROLLINFO si; GetScrollBarInfoV(&si); int nCurPos = si.nPos; int nLimit = m_pControl->GetScrollLimit(SB_VERT); BOOL bWidtdhOK = (rcAllDayEvents.left <= pnt.x && rcAllDayEvents.right >= pnt.x); if (!bWidtdhOK) return xtpCalendarDayViewScrollNotNeeded; if ((pnt.y >= rcAllDayEvents.bottom) && (pnt.y - rcAllDayEvents.bottom <= nVScrollZone) && nCurPos > 0 && m_ptLBtnDownMousePos.y - pnt.y > 2) { // Scroll up return xtpCalendarDayViewScrollUp; } if ((pnt.y + 3 < rcCtrl.Height()) && (rcCtrl.Height() - (pnt.y + 3) <= nVScrollZone) && nCurPos < nLimit && pnt.y - m_ptLBtnDownMousePos.y > 2) { return xtpCalendarDayViewScrollDown; } return xtpCalendarDayViewScrollNotNeeded; } BOOL CXTPCalendarDayView::IsOutOfClientRect(CPoint pnt, XTP_CALENDAR_HITTESTINFO_DAY_VIEW* 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::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; TRACE_DRAGGING(_T("SetMouseOutOfDragArea OUT\n")); bNeedUpd = TRUE; } } if (bChanged && !m_bMouseOutOfDragArea) { TRACE_DRAGGING(_T("SetMouseOutOfDragArea IN\n")); 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) { //Start timer m_dwScrollingEventTimerID = SetTimer(XTP_SCROLL_TIMER_RESOLUTION_MS); DBG_TRACE_TIMER(_T("SET Timer: ID =%d, m_dwScrollingEventTimerID, CXTPCalendarDayView::VertEventScroll() \n"), m_dwScrollingEventTimerID); } 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; //TRACE(_T("DayView: Auto redraw timer was KILLED. \n")); } if (m_dwScrollingEventTimerID) { KillTimer(m_dwScrollingEventTimerID); m_dwScrollingEventTimerID = 0; } } if (bActivate && m_dwRedrawNowLineTimerID == 0) { m_dwRedrawNowLineTimerID = SetTimer(XTP_REDRAW_TIMER_RESOLUTION_MS); DBG_TRACE_TIMER(_T("SET Timer: ID =%d, m_dwRedrawNowLineTimerID, CXTPCalendarDayView::OnActivateView() \n"), m_dwRedrawNowLineTimerID); //TRACE(_T("DayView: Auto redraw timer was SET. \n")); } } 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(); //COleDateTimeSpan spDiff = dtNow - m_dtLastRedrawTime; //if ((spDiff.GetTotalSeconds() >= 15 || dtNow.GetSecond()%15 == 0) && // dtNow.GetSecond() != m_dtLastRedrawTime.GetSecond()) if (dtNow.GetMinute() != m_dtLastRedrawTime.GetMinute()) { CXTPCalendarControl::CUpdateContext updateContext(m_pControl, xtpCalendarUpdateRedraw); //TRACE(_T("DayView: Auto REDRAW (%d:%d:%d). \n"), (int)dtNow.GetHour(), // (int)dtNow.GetMinute(), (int)dtNow.GetSecond()); } return TRUE; } return TBase::OnTimer(uTimerID); } BOOL CXTPCalendarDayView::OnEndDragging(CPoint point, XTP_CALENDAR_HITTESTINFO* pHitInfo) { 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 = CXTPCalendarUtils::ResetDate(dtS); COleDateTime dtE0 = CXTPCalendarUtils::ResetDate(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) { m_ptLBtnDownMousePos = CPoint(0, 0); return TBase::OnLButtonUp(nFlags, point); } BOOL CXTPCalendarDayView::OnLButtonDown(UINT nFlags, CPoint point) { CSelectionChangedContext selChanged(this); TBase::OnLButtonDown(nFlags, point); m_ptLBtnDownMousePos = point; if (m_eDraggingMode != xtpCalendaDragModeUnknown) { return FALSE; } XTP_CALENDAR_HITTESTINFO_DAY_VIEW hitTestInfo; if (HitTestEx(point, &hitTestInfo)) { 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) { return; } // process selection mode if ((nFlags & MK_LBUTTON) == 0) { return; } else if (!m_bStartedClickInside) { return; } XTP_CALENDAR_HITTESTINFO_DAY_VIEW hitTestInfo; if (HitTestEx(point, &hitTestInfo)) { COleDateTime dtEnd = m_selectedBlock.dtEnd; BOOL bAllDayEvent = m_selectedBlock.bAllDayEvent; BOOL bScrolled = FALSE; XTPCalendarDayViewScrollDirection direction = GetNeededScrollDirection(point); 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 = CXTPCalendarUtils::ResetTime(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) { if (!m_selectedBlock.IsValid()) return FALSE; COleDateTime dtBegin = m_selectedBlock.dtBegin, 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) { CXTPCalendarDayViewDay* 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); 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 = CXTPCalendarUtils::ResetTime(dtEnd) - CXTPCalendarUtils::ResetTime(dtBegin); int nDays = GETTOTAL_DAYS_DTS(spDaysRange) + 1; COleDateTime dtDay = CXTPCalendarUtils::ResetTime(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(CXTPCalendarUtils::ResetTime(COleDateTime::GetCurrentTime())); } } COleDateTimeSpan CXTPCalendarDayView::GetScaleInterval() const { int nSI_min = XTP_SAFE_GET2(m_pControl, GetCalendarOptions(), nDayView_ScaleInterval, 30); return COleDateTimeSpan(0, 0, nSI_min, 0); } void CXTPCalendarDayView::SetScaleInterval(const COleDateTimeSpan spScaleInterval) { BOOL bValidSVal = GETTOTAL_MINUTES_DTS(spScaleInterval) >= 1; ASSERT(bValidSVal); if (m_pTimeScaleHeader && bValidSVal) { int nOldScaleInterval = XTP_SAFE_GET2(m_pControl, GetCalendarOptions(), nDayView_ScaleInterval, 30); int nScaleInterval = (int)GETTOTAL_MINUTES_DTS(spScaleInterval); if (nScaleInterval != nOldScaleInterval) { XTP_SAFE_SET2(m_pControl, GetCalendarOptions(), nDayView_ScaleInterval, nScaleInterval); CXTPCalendarControl::CUpdateContext updateContext(m_pControl, xtpCalendarUpdateAll); SendNotification(XTP_NC_CALENDAROPTIONSWASCHANGED, xtpCalendarDayView, 0); SendNotification(XTP_NC_CALENDARVIEWTIMESCALEWASCHANGED, 0, 0); } } } void CXTPCalendarDayView::SetScaleText(LPCTSTR strText) { XTP_SAFE_CALL1(m_pTimeScaleHeader, SetCaption(strText)); XTP_SAFE_SET2(m_pControl, GetCalendarOptions(), strDayView_ScaleLabel, strText); SendNotification(XTP_NC_CALENDAROPTIONSWASCHANGED, xtpCalendarDayView, 0); SendNotification(XTP_NC_CALENDARVIEWTIMESCALEWASCHANGED, 0, 0); } CString CXTPCalendarDayView::GetScaleText() { return XTP_SAFE_GET2(m_pControl, GetCalendarOptions(), strDayView_ScaleLabel, _T("")); } void CXTPCalendarDayView::SetScale2Text(LPCTSTR strText) { XTP_SAFE_CALL1(m_pTimeScaleHeader2, SetCaption(strText)); XTP_SAFE_SET2(m_pControl, GetCalendarOptions(), strDayView_Scale2Label, strText); SendNotification(XTP_NC_CALENDAROPTIONSWASCHANGED, xtpCalendarDayView, 0); SendNotification(XTP_NC_CALENDARVIEWTIMESCALEWASCHANGED, 0, 0); } CString CXTPCalendarDayView::GetScale2Text() { 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((GETTOTAL_SECONDS_DTS(spScale2Offset) % 60) == 0); int nTimeShift2_min = GETTOTAL_MINUTES_DTS(spScale2Offset); XTP_SAFE_CALL1(m_pTimeScaleHeader2, SetTimeshift(nTimeShift2_min)); } const TIME_ZONE_INFORMATION& CXTPCalendarDayView::GetScale2TimeZone() { 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() { return XTP_SAFE_GET2(m_pControl, GetCalendarOptions(), bDayView_Scale2Visible, FALSE); } COleDateTime CXTPCalendarDayView::GetViewDayDate(int nIndex) { CXTPCalendarDayViewDay* pViewDay = GetViewDay(nIndex); ASSERT(pViewDay); return pViewDay ? pViewDay->m_dtDate : CXTPCalendarUtils::ResetTime(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) { 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() { 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() { 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 = CXTPCalendarUtils::ResetTime(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) { CXTPCalendarControl::CUpdateContext updateContext(m_pControl, xtpCalendarUpdateRedraw); UnselectAllEvents(); BOOL bVKShift = !!(GetKeyState(VK_SHIFT) & 0x8000); 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(CXTPCalendarUtils::ResetDate(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); if (nChar == VK_LEFT) { if (!m_bScrollH_Disabled || CXTPCalendarUtils::ResetTime(dtNewSelEnd) > dtFirstDay) { if (!bVKShift && m_selectedBlock.nGroupIndex > 0) { m_selectedBlock.nGroupIndex--; } else { dtNewSelEnd -= spDay; CXTPCalendarDayViewDay* pDay = GetDay(dtNewSelEnd); if (!bVKShift && pDay) { m_selectedBlock.nGroupIndex = pDay->GetViewGroupsCount() - 1; } } } } else if (nChar == VK_RIGHT) { if (!m_bScrollH_Disabled || CXTPCalendarUtils::ResetTime(dtNewSelEnd) < dtLastDay) { CXTPCalendarDayViewDay* pDay = GetDay(dtNewSelEnd); if (!bVKShift && pDay && m_selectedBlock.nGroupIndex < pDay->GetViewGroupsCount() - 1) { 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); } } 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 = CXTPCalendarUtils::ResetTime(rdtSel1); COleDateTime dtSelDay2 = CXTPCalendarUtils::ResetTime(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(CXTPCalendarUtils::ResetDate(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 (_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(CXTPCalendarUtils::ResetTime(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()) { //return pViewEvent->IsVisible(); return FALSE; } //--------------------------------------------------------------------------- COleDateTime dtDay = XTP_SAFE_GET3(pViewEvent, GetViewGroup_(), GetViewDay_(), GetDayDate(), (DATE)0); dtDay = CXTPCalendarUtils::ResetTime(dtDay); COleDateTime dtStart = pViewEvent->GetEvent()->GetStartTime(); COleDateTime dtEnd = pViewEvent->GetEvent()->GetEndTime(); COleDateTime stSTime = CXTPCalendarUtils::ResetDate(dtStart); COleDateTime stETime = CXTPCalendarUtils::ResetDate(dtEnd); if (CXTPCalendarUtils::IsZeroTime(stETime)) stETime = CXTPCalendarUtils::SetTime_235959(stETime); int nSCell = 0; int nECell = max(0, GetRowCount() - 1); if (CXTPCalendarUtils::ResetTime(dtStart) == dtDay) nSCell = GetCellNumber(stSTime, FALSE); if (CXTPCalendarUtils::ResetTime(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() { COleDateTime dtSel1 = min(m_selectedBlock.dtBegin, m_selectedBlock.dtEnd); COleDateTime dtSel2 = max(m_selectedBlock.dtBegin, m_selectedBlock.dtEnd); COleDateTime dtSel1Day = CXTPCalendarUtils::ResetTime(dtSel1); COleDateTime dtSel2Day = CXTPCalendarUtils::ResetTime(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 = CXTPCalendarUtils::ResetTime(dtNext); COleDateTime dtCurrDay = CXTPCalendarUtils::ResetTime(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() { 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() { 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() { int nWidth = XTP_SAFE_GET1(GetTimeScale(), GetWidth(), 0); if (IsScale2Visible()) nWidth += XTP_SAFE_GET1(GetTimeScale(2), GetWidth(), 0); return nWidth; } CRect CXTPCalendarDayView::_GetScrollRectClient() { CXTPClientRect rcClient(GetCalendarControl()); rcClient.left += _GetTimeScaleWith(); rcClient.left = min(rcClient.left, rcClient.right); return rcClient; } /////////////////////////////////////////////////////////////////////////////