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.

4044 lines
104 KiB
C++

// XTPCalendarView.cpp : implementation file
//
// 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/XTPPropExchange.h"
#include "Common/XTPDrawHelpers.h"
#include "Common/XTPSmartPtrInternalT.h"
#include "Common/XTPNotifyConnection.h"
#include "Common/XTPColorManager.h"
#include "XTPCalendarDefines.h"
#include "XTPCalendarUtils.h"
#include "XTPCalendarPtrCollectionT.h"
#include "XTPCalendarNotifications.h"
#include "XTPCalendarOptions.h"
#include "XTPCalendarTimeZoneHelper.h"
#include "XTPCalendarResource.h"
#include "XTPCalendarEvent.h"
#include "XTPCalendarEvents.h"
#include "XTPCalendarView.h"
#include "XTPCalendarViewEvent.h"
#include "XTPCalendarViewDay.h"
#include "XTPCalendarTimeLineView.h"
#include "XTPCalendarViewPart.h"
#include "XTPCalendarControl.h"
#include "XTPCalendarData.h"
#include "XTPCalendarPaintManager.h"
#include "XTPCalendarTheme.h"
#include "XTPCalendarThemeOffice2007.h"
#include <math.h>
#pragma warning(disable: 4571) // warning C4571: catch(...) blocks compiled with /EHs do not catch or re-throw Structured Exceptions
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
#define XTP_CLIPBOARD_EVENTS_DATA_VER 2
class CXTPCalendarView::CUndoBuffer
{
public:
//-----------------------------------------------------------------------
// Summary:
// Default class constructor.
//-----------------------------------------------------------------------
CUndoBuffer() {};
//-----------------------------------------------------------------------
// Summary:
// Default class destructor.
//-----------------------------------------------------------------------
virtual ~CUndoBuffer()
{
RemoveAll();
};
//-----------------------------------------------------------------------
// Summary:
// This member function is used to add an Undo action to the buffer.
// Parameters:
// pPrev - A CXTPCalendarEvent object that contains the instance
// before the edit action.
// pNew - A CXTPCalendarEvent that contains the instance after
// the edit action.
//-----------------------------------------------------------------------
void AddUndoAction(CXTPCalendarEvent* pPrev, CXTPCalendarEvent* pNew)
{
CXTPCalendarEventPtr ptrPrevCopy = pPrev ? pPrev->CloneEvent() : NULL;
CXTPCalendarEventPtr ptrNewCopy = pNew ? pNew->CloneEvent() : NULL;
m_arUndoActions.Add(SUndoAction(ptrPrevCopy, ptrNewCopy));
}
//-----------------------------------------------------------------------
// Summary:
// Call this member function to clear the Undo buffer.
//-----------------------------------------------------------------------
void RemoveAll()
{
m_arUndoActions.RemoveAll();
}
//-----------------------------------------------------------------------
// Summary:
// This member function is used to search for an undo action for a
// specified event in the buffer.
// Parameters:
// pEvent - A CXTPCalendarEvent object to search for in the buffer.
// Returns:
// A BOOL. TRUE if undo action for a specified event exists in the
// buffer. FALSE otherwise.
//-----------------------------------------------------------------------
BOOL IsInUndoBuffer(CXTPCalendarEvent* pEvent)
{
int nCount = (int)m_arUndoActions.GetSize();
for (int i = nCount-1; i >= 0; i--)
{
SUndoAction& rAction = m_arUndoActions.ElementAt(i);
if (rAction.ptrPrev && rAction.ptrPrev->IsEqualIDs(pEvent) ||
rAction.ptrNew && rAction.ptrNew->IsEqualIDs(pEvent))
{
return TRUE;
}
}
return FALSE;
}
//-----------------------------------------------------------------------
// Summary:
// Call this member function to obtain the number of undo actions.
// Returns:
// An int that contains the number of Undo actions.
//-----------------------------------------------------------------------
int GetCount() const
{
return (int)m_arUndoActions.GetSize();
}
//-----------------------------------------------------------------------
// Summary:
// Call this member function to obtain the first undo event.
// Returns:
// A CXTPCalendarEvent object that contains the first undo event
// or NULL if there are no undo events.
//-----------------------------------------------------------------------
CXTPCalendarEventPtr GetFirstUndoEvent()
{
int nCount = (int)m_arUndoActions.GetSize();
if (nCount > 0)
{
SUndoAction& rAction = m_arUndoActions.ElementAt(0);
if (rAction.ptrPrev)
{
return rAction.ptrPrev;
}
else if (rAction.ptrNew)
{
return rAction.ptrNew;
}
}
return NULL;
}
//-----------------------------------------------------------------------
// Summary:
// This member function is used to search for the first action for
// a specified event in the buffer.
// Parameters:
// pEvent - A CXTPCalendarEvent object that contains the event to
// search for in the buffer.
// Returns:
// A CXTPCalendarEvent that contains the oldest event object from
// all of the editing actions or NULL if there are no events.
//-----------------------------------------------------------------------
CXTPCalendarEventPtr UndoAllForEvent(CXTPCalendarEvent* pEvent)
{
int nCount = (int)m_arUndoActions.GetSize();
for (int i = 0; i < nCount; i++)
{
SUndoAction& rAction = m_arUndoActions.ElementAt(i);
if (rAction.ptrPrev && rAction.ptrPrev->IsEqualIDs(pEvent) ||
rAction.ptrNew && rAction.ptrNew->IsEqualIDs(pEvent))
{
return rAction.ptrPrev;
}
}
return NULL;
}
//-----------------------------------------------------------------------
// Summary:
// This member function is used to search for last action for a
// specified event in the buffer.
// Parameters:
// pEvent - A CXTPCalendarEvent object that contains the event
// to search for in the buffer.
// Returns:
// A CXTPCalendarEvent that contains the latest event object from
// all of the editing actions or NULL if there are no events.
//-----------------------------------------------------------------------
CXTPCalendarEventPtr RedoAllForEvent(CXTPCalendarEvent* pEvent)
{
CXTPCalendarEventPtr ptrResult;
int nCount = (int)m_arUndoActions.GetSize();
for (int i = nCount-1; i >= 0; i--)
{
SUndoAction& rAction = m_arUndoActions.ElementAt(i);
if (rAction.ptrPrev && rAction.ptrPrev->IsEqualIDs(pEvent) ||
rAction.ptrNew && rAction.ptrNew->IsEqualIDs(pEvent))
{
return rAction.ptrNew;
}
}
return NULL;
}
//-----------------------------------------------------------------------
// Summary:
// This member function is used to clear the current buffer of all
// undo actions and then add new undo actions to the buffer from
// the source object.
// Parameters:
// rSrc - A CUndoBuffer object that contains the new undo actions
// to add to the undo buffer object.
//-----------------------------------------------------------------------
void Set(CUndoBuffer& rSrc)
{
m_arUndoActions.RemoveAll();
m_arUndoActions.Append(rSrc.m_arUndoActions);
}
protected:
//-----------------------------------------------------------------------
// Remarks:
// Helper structure to store editing/undo actions.
//-----------------------------------------------------------------------
struct SUndoAction
{
CXTPCalendarEventPtr ptrPrev; // Event instance before edit action.
CXTPCalendarEventPtr ptrNew; // Event instance after edit action.
//-----------------------------------------------------------------------
// Summary:
// Default class constructor.
// Parameters:
// pPrev - A CXTPCalendarEvent object that contains the instance
// before the edit action.
// pNew - A CXTPCalendarEvent object that contains the instance
// after the edit action.
//-----------------------------------------------------------------------
SUndoAction(CXTPCalendarEvent* pPrev = NULL, CXTPCalendarEvent* pNew = NULL) :
ptrPrev(pPrev, TRUE), ptrNew(pNew, TRUE) {};
//-----------------------------------------------------------------------
// Parameters:
// src - A SUndoAction object that contains the source object.
// Summary:
// Copy class constructor.
//-----------------------------------------------------------------------
SUndoAction(const SUndoAction& src)
{
*this = src;
}
//-----------------------------------------------------------------------
// Summary:
// Default class destructor.
//-----------------------------------------------------------------------
virtual ~SUndoAction() {}
//-----------------------------------------------------------------------
// Summary:
// This is the overloaded assignment operator.
// Parameters:
// src - Source object.
// Returns:
// A reference to the current object.
// Remarks:
// Copy class operator.
//-----------------------------------------------------------------------
const SUndoAction& operator=(const SUndoAction& src)
{
ptrPrev = src.ptrPrev;
ptrNew = src.ptrNew;
return *this;
}
};
CArray<SUndoAction, const SUndoAction&> m_arUndoActions; // Array of editing/undo actions.
};
//===========================================================================
IMPLEMENT_DYNAMIC(CXTPCalendarWMHandler, CCmdTarget)
IMPLEMENT_DYNAMIC(CXTPCalendarView, CXTPCalendarWMHandler)
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
// CXTPCalendarView
CXTPCalendarView::CXTPCalendarView(CXTPCalendarControl* pCalendarControl) :
m_pControl(pCalendarControl)
{
//m_strDayHeaderFormatLong = _T("d MMMM");
//m_strDayHeaderFormatMiddle = _T("d MMM");
//m_strDayHeaderFormatShort = _T("d");
//m_strDayHeaderFormatShortest = _T("d");
m_rcView.SetRectEmpty();
m_rcTooltip.SetRectEmpty();
m_Layout.m_nRowHeight = 18;
m_eDraggingMode = xtpCalendaDragModeUnknown;
m_ptStartDragging.x = m_ptStartDragging.y = LONG_MAX;
m_bStartedClickInside = FALSE;
m_nTimerID_StartEditSubject = 0;
m_nTimerID_ShowToolTip = 0;
m_eUndoMode = xtpCalendarUndoModeUnknown;
m_bResetUndoBuffer = FALSE;
m_nKeyStateTimerID = 0;
m_pSelectedEvents = new CXTPCalendarViewEvents();
m_pResources = NULL;
m_pUndoBuffer = new CUndoBuffer();
m_pPrevUndoBuffer = new CUndoBuffer();
_CalculateEventTimeFormat();
m_bScrollV_Disabled = FALSE;
m_bScrollH_Disabled = FALSE;
ClearDiscreteSelection();
m_ptLBtnDownMousePos = CPoint(0,0);
m_ptLBtnUpMousePos = CPoint(0,0);
}
CXTPCalendarView::~CXTPCalendarView()
{
CMDTARGET_RELEASE(m_pSelectedEvents);
CMDTARGET_RELEASE(m_pResources);
ASSERT(m_nTimerID_StartEditSubject == 0);
ASSERT(m_nTimerID_ShowToolTip == 0);
ClearDiscreteSelection();
SAFE_DELETE(m_pUndoBuffer);
SAFE_DELETE(m_pPrevUndoBuffer);
}
void CXTPCalendarView::OnBeforeDestroy()
{
// --- Kill Subject editor
if (IsEditingSubject())
EndEditSubject(xtpCalendarEditSubjectCommit, FALSE);
if (m_ptrDraggingEventNew)
CommitDraggingEvent();
// --- Kill tooltip (and timer inside)
ShowToolTip(FALSE);
// --- Clear selected events collection
if (m_pSelectedEvents)
m_pSelectedEvents->RemoveAll();
// === Call base cleanup code
TBase::OnBeforeDestroy();
}
void CXTPCalendarView::OnActivateView(BOOL bActivate,
CXTPCalendarView* pActivateView,
CXTPCalendarView* pInactiveView)
{
UNREFERENCED_PARAMETER(pActivateView);
UNREFERENCED_PARAMETER(pInactiveView);
if (!bActivate && IsEditingSubject())
EndEditSubject(xtpCalendarEditSubjectCommit, FALSE);
}
void CXTPCalendarView::RedrawControl()
{
ASSERT(m_pControl);
if (m_pControl)
{
m_pControl->RedrawControl();
}
}
void CXTPCalendarView::Populate()
{
if (IsEditingSubject())
{
EndEditSubject(xtpCalendarEditSubjectCommit);
}
int nCount = GetViewDayCount();
for (int i = 0; i < nCount; i++)
{
CXTPCalendarViewDay* pViewDay = GetViewDay_(i);
COleDateTime dtDay = GetViewDayDate(i);
//ASSERT(pViewDay);
if (pViewDay)
pViewDay->Populate(dtDay);
}
_ReSelectSelectEvents();
}
BOOL CXTPCalendarView::OnLButtonDown(UINT nFlags, CPoint point)
{
m_ptLBtnDownMousePos = point;
CXTPCalendarControl::CUpdateContext updateContext(m_pControl, xtpCalendarUpdateRedrawIfNeed);
CSelectionChangedContext selChanged(this);
if (!m_pControl->IsReadonlyMode())
m_bStartedClickInside = TRUE;
//---------------------------------------------------------------------------
TBase::OnLButtonDown(nFlags, point);
//= kill timeout request to edit subject=====================================
if (m_nTimerID_StartEditSubject)
{
KillTimer(m_nTimerID_StartEditSubject);
m_nTimerID_StartEditSubject = 0;
m_ptrEditingViewEvent = NULL;
}
//---------------------------------------------------------------------------
XTP_CALENDAR_HITTESTINFO hitInfo;
if (HitTest(point, &hitInfo))
{
if (hitInfo.uHitCode & xtpCalendarHitTestDay_Mask)
{
CXTPCalendarControl::CUpdateContext updateContext1(m_pControl, xtpCalendarUpdateRedraw);
ProcessDaySelection(&hitInfo, nFlags);
}
else if (hitInfo.uHitCode & xtpCalendarHitTestEvent_Mask && !m_pControl->IsReadonlyMode())
{
CXTPCalendarControl::CUpdateContext updateContext1(m_pControl, xtpCalendarUpdateRedraw);
ProcessEventSelection(&hitInfo, nFlags);
// set request to start dragging when OnMouseMove()
m_ptStartDragging = point;
}
}
//---------------------------------------------------------------------------
BOOL bResetUndoLocal = TRUE;
if (IsEditingSubject() && !m_pControl->IsReadonlyMode())
{
if (!GetSubjectEditorRect().PtInRect(point))
{
bResetUndoLocal = m_eDraggingMode != xtpCalendaDragModeEditSubject;
EndEditSubject(xtpCalendarEditSubjectCommit);
}
}
m_bResetUndoBuffer = bResetUndoLocal;
//---------------------------------------------------------------------------
CXTPCalendarThemeOffice2007* pThemeX = DYNAMIC_DOWNCAST(CXTPCalendarThemeOffice2007, GetTheme());
if (pThemeX)
{
XTP_SAFE_CALL1(pThemeX->GetPrevNextEventButtonsPartX(), OnLButtonDown(this, nFlags, point));
}
return TRUE;
}
BOOL CXTPCalendarView::OnLButtonUp(UINT nFlags, CPoint point)
{
m_ptLBtnUpMousePos = m_ptLBtnDownMousePos;
m_ptLBtnDownMousePos = CPoint(0, 0);
// way to support discrete selection - pick all days while ALT key hold
XTP_CALENDAR_HITTESTINFO hitAltInfo;
BOOL bAltHitTest = HitTest(point, &hitAltInfo);
BOOL bVKAlt = (GetKeyState(VK_MENU) < 0);
if (bAltHitTest && bVKAlt && nFlags == 0 && m_bStartedClickInside)
{
if (hitAltInfo.dt != NULL)
{
UINT uDay = (UINT) hitAltInfo.dt;
AddToDiscreteSelection(uDay);
return TRUE;
}
}
else
{
ClearDiscreteSelection();
}
CXTPCalendarControl::CUpdateContext updateContext(m_pControl, xtpCalendarUpdateRedrawIfNeed);
CSelectionChangedContext selChanged(this);
const BOOL bHandled = TBase::OnLButtonUp(nFlags, point);
//---------------------------------------------------------------------------
m_ptStartDragging.x = m_ptStartDragging.y = LONG_MAX;
XTP_CALENDAR_HITTESTINFO hitInfo;
BOOL bHitTest = HitTest(point, &hitInfo);
if (GetViewType() == xtpCalendarTimeLineView)
{
CXTPCalendarTimeLineView* pView = (CXTPCalendarTimeLineView* ) GetCalendarControl()->GetActiveView();
if (pView)
pView->ShowCalendarPopup(hitInfo.dt, point);
}
int nDragMode = m_eDraggingMode;
if (!OnEndDragging(point, &hitInfo) && !m_pControl->IsReadonlyMode())
{
if (!bHandled && bHitTest)
{
UINT uESmask = xtpCalendarHitTestEventTextArea | xtpCalendarHitTestEventResizeArea_Mask;
if ((hitInfo.uHitCode & uESmask) && !IsEditingSubject() &&
hitInfo.pViewEvent && hitInfo.pViewEvent->IsSelected())
{
BOOL bEnabled = XTP_SAFE_GET1(GetCalendarOptions(), bEnableInPlaceEditEventSubject_ByMouseClick, FALSE);
bEnabled = bEnabled && IsSingleEventSelected();
if (bEnabled)
bEnabled = !OnBeforeEditOperationNotify(xtpCalendarEO_EditSubject_ByMouseClick, hitInfo.pViewEvent);
if (bEnabled)
{
ASSERT(!m_ptrEditingViewEvent);
m_ptrEditingViewEvent = hitInfo.pViewEvent;
m_ptrEditingViewEvent->InternalAddRef();
if (m_nTimerID_StartEditSubject == 0)
{
UINT uTimeOut_ms = GetStartEditSubjectTimeOut();
m_nTimerID_StartEditSubject = SetTimer(uTimeOut_ms);
}
}
}
}
}
//---------------------------------------------------------------------------
if (_IsDragModeCopyMove(nDragMode) && bHitTest && hitInfo.pViewDay)
{
UnselectAllEvents();
SelectDay(hitInfo.pViewDay, hitInfo.nGroup);
}
if (GetCalendarControl())
GetCalendarControl()->m_mouseMode = xtpCalendarMouseNothing;
m_bStartedClickInside = FALSE;
OnMouseMove(nFlags, point);
return TRUE;
}
void CXTPCalendarView::OnMouseMove(UINT nFlags, CPoint point)
{
CXTPCalendarControl::CUpdateContext updateContext(m_pControl, xtpCalendarUpdateRedrawIfNeed);
CSelectionChangedContext selChanged(this);
CXTPCalendarThemeOffice2007* pThemeX = DYNAMIC_DOWNCAST(CXTPCalendarThemeOffice2007, GetTheme());
if (pThemeX)
XTP_SAFE_CALL1(pThemeX->GetPrevNextEventButtonsPartX(), OnMouseMove(this, nFlags, point));
TBase::OnMouseMove(nFlags, point);
XTP_CALENDAR_HITTESTINFO hitInfo;
BOOL bHitTest = HitTest(point, &hitInfo);
if (bHitTest && hitInfo != m_LastHitInfo)
{
m_LastHitInfo = hitInfo;
BOOL bVKAlt = (GetKeyState(VK_MENU) < 0);
if (bVKAlt && (nFlags & MK_LBUTTON && m_bStartedClickInside))
{
//Preventing continues selection if ALT key hold
if (m_LastHitInfo.dt != NULL)
{
UINT uDay = (UINT) m_LastHitInfo.dt;
AddToDiscreteSelection(uDay);
}
}
else if (nFlags & MK_LBUTTON && m_bStartedClickInside)
{
const int cEpsilon = 2;
if (m_ptStartDragging.x == LONG_MAX || m_ptStartDragging.y == LONG_MAX ||
abs(point.x - m_ptStartDragging.x) >= cEpsilon ||
abs(point.y - m_ptStartDragging.y) >= cEpsilon)
{
if (!m_ptrDraggingEventNew && !m_ptrDraggingEventOrig &&
m_eDraggingMode == xtpCalendaDragModeUnknown)
{
XTP_CALENDAR_HITTESTINFO hitInfoSD;
if (HitTest(m_ptStartDragging, &hitInfoSD))
{
if (hitInfoSD.uHitCode & xtpCalendarHitTestEvent_Mask)
{
int eDragMode = _GetDraggingMode(&hitInfoSD);
if (!IsEditOperationDisabledNotify(_DragMod2Operation(eDragMode), hitInfoSD.pViewEvent))
OnStartDragging(m_ptStartDragging, &hitInfoSD);
}
}
}
m_ptStartDragging.x = m_ptStartDragging.y = LONG_MAX;
BOOL bDragging = m_ptrDraggingEventNew && m_eDraggingMode != xtpCalendaDragModeEditSubject;
if (bDragging)
{
CXTPCalendarEventPtr ptrDragEventPrev = m_ptrDraggingEventNew->CloneEvent();
BOOL bDragged = OnDragging(point, &hitInfo);
if (bDragged)
{
XTP_EVENT_DRAG_OPERATION_PARAMS opParamsDrag;
::ZeroMemory(&opParamsDrag, sizeof(opParamsDrag));
opParamsDrag.eOperation = _DragMod2Operation(m_eDraggingMode);
opParamsDrag.pDraggingEventOriginal = m_ptrDraggingEventOrig;
opParamsDrag.pDraggingEvent = ptrDragEventPrev;
opParamsDrag.pDraggingEventNew = m_ptrDraggingEventNew;
BOOL bHandled = FALSE;
if (m_pControl)
m_pControl->SendNotification(XTP_NC_CALENDAR_BEFORE_EVENT_EDIT_OPERATION,
(WPARAM)&opParamsDrag, (LPARAM)&bHandled);
if (bHandled) //rollback
m_ptrDraggingEventNew = ptrDragEventPrev;
XTP_SAFE_CALL1(GetCalendarControl(), Populate());
CXTPCalendarControl::CUpdateContext updateContext1(m_pControl, xtpCalendarUpdateLayout | xtpCalendarUpdateRedraw);
if (m_ptrDraggingEventNew
&& m_ptrDraggingEventOrig
&& (!m_ptrDraggingEventNew->IsEqualStartEnd(m_ptrDraggingEventOrig) ||
m_ptrDraggingEventNew->GetScheduleID() != m_ptrDraggingEventOrig->GetScheduleID()))
SelectEvent(m_ptrDraggingEventNew);
}
}
}
if (m_eDraggingMode == xtpCalendaDragModeUnknown &&
hitInfo.uHitCode & (xtpCalendarHitTestDay_Mask | xtpCalendarHitTestEvent_Mask))
{
if ((hitInfo.uHitCode & xtpCalendarHitTestEvent_Mask) &&
hitInfo.pViewEvent && hitInfo.pViewEvent->IsSelected())
{}
else
{
CXTPCalendarControl::CUpdateContext updateContext1(m_pControl, xtpCalendarUpdateRedraw);
ProcessDaySelection(&hitInfo, nFlags | MK_SHIFT);
}
}
}
// process tooltip events (only when no buttons pressed)
if (0 == nFlags)
{
CRect rcTooltip(GetTooltipRect(point, hitInfo));
if (m_rcTooltip != rcTooltip)
{
// -- kill waiting and hide a tooltip because we switched to another cell
ShowToolTip(FALSE);
// -- start waiting for mouse under regular empty cell
// (to show later "click to add appointment" button)
UINT uTimeOut_ms = GetShowToolTipTimeOut();
m_nTimerID_ShowToolTip = SetTimer(uTimeOut_ms);
m_rcTooltip = rcTooltip;
ASSERT(m_nTimerID_ShowToolTip);
}
}
}
else if (!bHitTest)
{
XTP_CALENDAR_HITTESTINFO hitInfoEmpty;
m_LastHitInfo = hitInfoEmpty;
}
//===========================================================================
if (GetCalendarControl())
{
if (_IsDragModeCopyMove(m_eDraggingMode)
&& GetCalendarControl()->m_mouseMode != xtpCalendarMouseEventDraggingOut)
{
GetCalendarControl()->m_mouseMode = m_eDraggingMode == xtpCalendaDragModeCopy ?
xtpCalendarMouseEventDragCopy : xtpCalendarMouseEventDragMove;
GetCalendarControl()->UpdateMouseCursor();
}
}
}
void CXTPCalendarView::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags)
{
CXTPCalendarControl::CUpdateContext updateContext(m_pControl, xtpCalendarUpdateRedrawIfNeed);
CSelectionChangedContext selChanged(this);
TBase::OnChar(nChar, nRepCnt, nFlags);
BOOL bEnable = XTP_SAFE_GET1(GetCalendarOptions(), bEnableInPlaceCreateEvent, FALSE);
if (nChar >= _T(' ') && bEnable && !m_pControl->IsReadonlyMode())
{
CString strInitialSubj((TCHAR)nChar);
if (!OnInPlaceCreateEvent(strInitialSubj))
StartEditNewEventInplace(strInitialSubj);
}
}
void CXTPCalendarView::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
{
CXTPCalendarControl::CUpdateContext updateContext(m_pControl, xtpCalendarUpdateRedrawIfNeed);
CSelectionChangedContext selChanged(this);
TBase::OnKeyDown(nChar, nRepCnt, nFlags);
if (nChar == VK_RETURN || nChar == VK_ESCAPE)
{
if (IsEditingSubject())
{
CXTPCalendarEventPtr ptrEditingEvent(m_ptrDraggingEventOrig, TRUE);
EndEditSubject((nChar == VK_RETURN) ? xtpCalendarEditSubjectCommit : xtpCalendarEditSubjectCancel);
if (nChar == VK_ESCAPE && ptrEditingEvent)
{
_Undo(ptrEditingEvent);
m_pUndoBuffer->Set(*m_pPrevUndoBuffer);
}
}
if (nChar == VK_ESCAPE && m_ptrDraggingEventNew)
{
CXTPCalendarEventPtr ptrEditingEvent(m_ptrDraggingEventOrig, TRUE);
CancelDraggingEvent();
BOOL bControlUpdated = FALSE;
if (ptrEditingEvent && !m_bResetUndoBuffer)
{
bControlUpdated = _Undo(ptrEditingEvent);
m_pUndoBuffer->Set(*m_pPrevUndoBuffer);
}
if (!bControlUpdated && GetCalendarControl())
{
CXTPCalendarControl::CUpdateContext updateContext1(GetCalendarControl(), xtpCalendarUpdateLayout | xtpCalendarUpdateRedraw);
GetCalendarControl()->Populate();
}
}
}
else if (nChar == VK_F2)
{
if (IsEditingSubject())
{
return;
}
CXTPCalendarViewEvent* pViewEvent = GetLastSelectedViewEvent();
if (GetViewType() == xtpCalendarDayView || GetViewType() == xtpCalendarWorkWeekView || GetViewType() == xtpCalendarFullWeekView)
{
CPoint point = m_ptLBtnUpMousePos;
XTP_CALENDAR_HITTESTINFO hitInfo;
if (HitTest(point, &hitInfo))
{
if (pViewEvent)
{
CXTPCalendarEvent* pEvent = pViewEvent->GetEvent();
if (pEvent)
pViewEvent = FindViewEventByGroup(pEvent, pEvent->GetStartTime(), hitInfo.nGroup);
}
}
}
BOOL bEnabled = XTP_SAFE_GET1(GetCalendarOptions(), bEnableInPlaceEditEventSubject_ByF2, FALSE);
bEnabled = bEnabled && m_eDraggingMode == xtpCalendaDragModeUnknown && pViewEvent;
if (bEnabled)
bEnabled = !OnBeforeEditOperationNotify(xtpCalendarEO_EditSubject_ByF2, pViewEvent);
if (bEnabled)
{
ASSERT(!m_ptrDraggingEventOrig && !m_ptrDraggingEventNew && !m_ptrEditingViewEvent);
if (pViewEvent)
{
CXTPCalendarControl::CUpdateContext updateContext1(m_pControl, xtpCalendarUpdateRedraw);
EmptyUndoBuffer();
StartEditSubject(pViewEvent);
}
}
}
else if (nChar == VK_DELETE)
{
if (m_eDraggingMode == xtpCalendaDragModeUnknown && !m_ptrEditingViewEvent)
{
ASSERT(!m_ptrDraggingEventOrig && !m_ptrDraggingEventNew && !m_ptrEditingViewEvent);
CXTPCalendarViewEvent* pViewEvent = GetLastSelectedViewEvent();
if (m_selectedBlock.dtEnd.GetStatus() == COleDateTime::valid &&
GetCalendarControl() && pViewEvent && pViewEvent->IsSelected())
{
CXTPCalendarControl::CUpdateContext updateContext1(GetCalendarControl(), xtpCalendarUpdateRedraw | xtpCalendarUpdateLayout);
VERIFY(GetCalendarControl()->DoDeleteSelectedEvents(pViewEvent));
GetCalendarControl()->Populate();
}
}
}
else if (nChar == VK_TAB)
{
if (m_eDraggingMode == xtpCalendaDragModeUnknown ||
m_eDraggingMode == xtpCalendaDragModeEditSubject)
{
BOOL bShift = (GetKeyState(VK_SHIFT) < 0);
CXTPCalendarControl::CUpdateContext updateContext1(m_pControl, xtpCalendarUpdateRedraw);
if (IsEditingSubject())
{
EndEditSubject(xtpCalendarEditSubjectCommit);
}
COleDateTime dtMinStart = GetNextTimeEditByTAB();
CXTPCalendarViewEvent* pViewEvent = GetLastSelectedViewEvent();
CXTPCalendarEvent* pLastEvent = pViewEvent ? pViewEvent->GetEvent() : NULL;
const int cLoopMax = 5000;
int i;
for (i = 0; i < cLoopMax; i++) // to prevent infinite looping
{
pViewEvent = FindEventToEditByTAB(dtMinStart, bShift, pLastEvent);
pLastEvent = pViewEvent ? pViewEvent->GetEvent() : NULL;
if (!pViewEvent || pViewEvent && pViewEvent->IsVisible())
{
break;
}
}
ASSERT(i < cLoopMax); // probably infinite looping ???
UnselectAllEvents();
if (pViewEvent && pViewEvent->IsVisible() && pViewEvent->GetEvent())
{
dtMinStart = pViewEvent->GetEvent()->GetStartTime();
UpdateNextTimeEditByTAB(dtMinStart, bShift);
EmptyUndoBuffer();
BOOL bEnabled = XTP_SAFE_GET1(GetCalendarOptions(), bEnableInPlaceEditEventSubject_ByTab, FALSE);
if (bEnabled)
{
bEnabled = !OnBeforeEditOperationNotify(xtpCalendarEO_EditSubject_ByTab, pViewEvent);
}
if (bEnabled)
{
StartEditSubject(pViewEvent);
}
else
{
SelectEvent(pViewEvent->GetEvent());
}
SelectDay(XTP_SAFE_GET2(pViewEvent, GetViewGroup_(), GetViewDay_(), NULL),
XTP_SAFE_GET2(pViewEvent, GetViewGroup_(), GetGroupIndex(), -1));
}
else
{
dtMinStart = GetViewDayDate(bShift ? GetViewDayCount()-1 : 0);
UpdateNextTimeEditByTAB(dtMinStart, bShift, TRUE);
}
}
}
}
BOOL CXTPCalendarView::OnSysKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
{
CXTPCalendarControl::CUpdateContext updateContext(m_pControl, xtpCalendarUpdateRedrawIfNeed);
CSelectionChangedContext selChanged(this);
BOOL bHandled = TBase::OnSysKeyDown(nChar, nRepCnt, nFlags);
UINT uAltBit = (((UINT)1) << 13);
if (nChar == VK_BACK && (nFlags & uAltBit))
{
bHandled = TRUE;
if (CanUndo())
Undo();
else if (CanRedo())
Redo();
}
return bHandled;
}
BOOL CXTPCalendarView::SetDraggingEvent(CXTPCalendarEvent* pEventOrig)
{
if (m_ptrDraggingEventOrig || m_ptrDraggingEventNew || !pEventOrig)
return FALSE;
// Dragging Event already set or CommitDraggingEvent() was not called or invalid parameter
pEventOrig->InternalAddRef();
m_ptrDraggingEventOrig = pEventOrig;
m_ptrDraggingEventNew = pEventOrig->CloneEvent();
if (m_ptrDraggingEventNew
&& m_ptrDraggingEventNew->GetRecurrenceState() == xtpCalendarRecurrenceOccurrence)
{
VERIFY(m_ptrDraggingEventNew->MakeAsRException());
}
return TRUE;
}
CXTPCalendarEvent* CXTPCalendarView::GetDraggingEventOrig() const
{
return m_ptrDraggingEventOrig;
}
CXTPCalendarEvent* CXTPCalendarView::GetDraggingEventNew() const
{
return m_ptrDraggingEventNew;
}
BOOL CXTPCalendarView::CommitDraggingEvent()
{
ASSERT(m_ptrDraggingEventNew);
if (!GetCalendarControl())
{
return FALSE;
}
CXTPAutoResetValue<BOOL> autoSet_UpdateCtrlNf(GetCalendarControl()->m_bUpdateWhenEventChangedNotify);
autoSet_UpdateCtrlNf = FALSE;
if (m_ptrDraggingEventNew && m_ptrDraggingEventOrig)
{
BOOL bDPdiff = m_ptrDraggingEventNew->GetDataProvider() != m_ptrDraggingEventOrig->GetDataProvider();
BOOL bChanged = !m_ptrDraggingEventNew->IsEqualStartEnd(m_ptrDraggingEventOrig);
bChanged = bChanged || m_ptrDraggingEventNew->GetSubject() != m_ptrDraggingEventOrig->GetSubject();
bChanged = bChanged || m_ptrDraggingEventNew->IsAllDayEvent() != m_ptrDraggingEventOrig->IsAllDayEvent();
bChanged = bChanged || m_ptrDraggingEventNew->GetScheduleID() != m_ptrDraggingEventOrig->GetScheduleID();
bChanged = bChanged || bDPdiff;
if (bChanged || m_eDraggingMode == xtpCalendaDragModeCopy)
{
if (!m_pUndoBuffer->IsInUndoBuffer(m_ptrDraggingEventOrig) || m_bResetUndoBuffer)
{
m_pPrevUndoBuffer->Set(*m_pUndoBuffer);
EmptyUndoBuffer();
}
CXTPCalendarData* pDataNew = m_ptrDraggingEventNew->GetDataProvider(); // _GetDataProviderForDraggingEvent(m_ptrDraggingEventNew);
CXTPCalendarData* pDataOrig = m_ptrDraggingEventOrig->GetDataProvider();
if (m_eDraggingMode == xtpCalendaDragModeCopy)
{
if (m_ptrDraggingEventNew->GetRecurrenceState() != xtpCalendarRecurrenceNotRecurring)
{
VERIFY(m_ptrDraggingEventNew->RemoveRecurrence() );
}
if (pDataNew)
{
DBG_DATA_VERIFY(pDataNew->AddEvent(m_ptrDraggingEventNew) );
}
}
else
{
m_pUndoBuffer->AddUndoAction(m_ptrDraggingEventOrig, m_ptrDraggingEventNew);
m_eUndoMode = xtpCalendarUndoModeUndo;
m_bResetUndoBuffer = FALSE;
if (pDataNew)
{
if (!bDPdiff)
{
// restore event ID for case when m_ptrDraggingEventNew was recreated
// during dragging between providers
m_ptrDraggingEventNew->SetEventID(m_ptrDraggingEventOrig->GetEventID());
DBG_DATA_VERIFY(pDataNew->ChangeEvent(m_ptrDraggingEventNew) );
}
else
{
if (m_ptrDraggingEventNew->GetRecurrenceState() != xtpCalendarRecurrenceNotRecurring)
{
VERIFY(m_ptrDraggingEventNew->RemoveRecurrence() );
}
if (pDataOrig)
{
DBG_DATA_VERIFY(pDataOrig->DeleteEvent(m_ptrDraggingEventOrig) );
}
DBG_DATA_VERIFY(pDataNew->AddEvent(m_ptrDraggingEventNew));
}
}
}
}
m_ptrDraggingEventOrig = NULL;
m_ptrDraggingEventNew = NULL;
return bChanged;
}
else if (m_ptrDraggingEventNew)
{
if (!m_pUndoBuffer->IsInUndoBuffer(m_ptrDraggingEventNew) || m_bResetUndoBuffer)
{
m_pPrevUndoBuffer->Set(*m_pUndoBuffer);
EmptyUndoBuffer();
}
CXTPCalendarData* pData = m_ptrDraggingEventNew->GetDataProvider(); //_GetDataProviderForDraggingEvent(m_ptrDraggingEventNew);
ASSERT(m_ptrDraggingEventNew->GetRecurrenceState() == xtpCalendarRecurrenceNotRecurring);
if (pData)
{
DBG_DATA_VERIFY( pData->AddEvent(m_ptrDraggingEventNew) );
}
m_pUndoBuffer->AddUndoAction(NULL, m_ptrDraggingEventNew);
m_eUndoMode = xtpCalendarUndoModeUndo;
m_bResetUndoBuffer = FALSE;
m_ptrDraggingEventOrig = NULL;
m_ptrDraggingEventNew = NULL;
return TRUE;
}
return FALSE;
}
void CXTPCalendarView::CancelDraggingEvent()
{
ASSERT(m_ptrDraggingEventNew);
m_eDraggingMode = xtpCalendaDragModeUnknown;
if (GetCalendarControl())
{
GetCalendarControl()->m_mouseMode = xtpCalendarMouseNothing;
GetCalendarControl()->UpdateMouseCursor();
}
m_ptrDraggingEventOrig = NULL;
m_ptrDraggingEventNew = NULL;
m_ptStartDragging.x = m_ptStartDragging.y = LONG_MAX;
m_bStartedClickInside = FALSE;
}
CXTPCalendarEventsPtr CXTPCalendarView::RetrieveDayEvents(CXTPCalendarResource* pRC,
COleDateTime dtDay)
{
ASSERT(pRC);
dtDay = CXTPCalendarUtils::ResetTime(dtDay);
CXTPCalendarEventsPtr ptrEvents = pRC ? pRC->RetrieveDayEvents(dtDay) : new CXTPCalendarEvents();
if (!m_ptrDraggingEventNew || !ptrEvents || !pRC)
{
return ptrEvents;
}
BOOL bIsDragCopy = m_eDraggingMode == xtpCalendaDragModeCopy;
COleDateTime dtDay1 = GetDateTimeDay(m_ptrDraggingEventNew->GetStartTime(), m_ptrDraggingEventNew->IsAllDayEvent());
COleDateTime dtDay2 = GetDateTimeDay(m_ptrDraggingEventNew->GetEndTime(), m_ptrDraggingEventNew->IsAllDayEvent());
UINT uSchID = m_ptrDraggingEventNew->GetScheduleID();
BOOL bNewEventScheduleVisible =
m_ptrDraggingEventNew->GetDataProvider() == pRC->GetDataProvider() &&
pRC->ExistsScheduleID(uSchID);
if (!bIsDragCopy)
{
int nCount = ptrEvents->GetCount();
for (int i = nCount-1; i >= 0; i--)
{
CXTPCalendarEvent* pEvent = ptrEvents->GetAt(i, FALSE);
if (!pEvent)
{
continue;
}
if (m_ptrDraggingEventOrig &&
m_ptrDraggingEventOrig->GetDataProvider() == pEvent->GetDataProvider() &&
m_ptrDraggingEventOrig->IsEqualIDs(pEvent) &&
m_ptrDraggingEventOrig->GetScheduleID() == pEvent->GetScheduleID())
{
ptrEvents->RemoveAt(i);
//break;
}
}
}
if (dtDay >= dtDay1 && dtDay <= dtDay2 && bNewEventScheduleVisible)
{
ptrEvents->Add(m_ptrDraggingEventNew);
}
return ptrEvents;
}
XTPCalendarDraggingMode CXTPCalendarView::_GetDraggingMode(XTP_CALENDAR_HITTESTINFO* pHitTest) const
{
if (!pHitTest)
{
ASSERT(FALSE);
return xtpCalendaDragModeUnknown;
}
if (pHitTest->uHitCode & xtpCalendarHitTestEventResizeArea_Mask)
{
if (pHitTest->uHitCode & xtpCalendarHitTestEventResizeBegin)
{
return xtpCalendaDragModeResizeBegin;
}
else if (pHitTest->uHitCode & xtpCalendarHitTestEventResizeEnd)
{
return xtpCalendaDragModeResizeEnd;
}
}
else
{
BOOL bIsCtrl = (GetKeyState(VK_CONTROL) < 0);
return bIsCtrl ? xtpCalendaDragModeCopy : xtpCalendaDragModeMove;
}
return xtpCalendaDragModeUnknown;
}
void CXTPCalendarView::OnStartDragging(CPoint /*point*/, XTP_CALENDAR_HITTESTINFO* pHitTest)
{
if (!pHitTest)
return;
if ((pHitTest->uHitCode & xtpCalendarHitTestEvent_Mask) == 0)
return;
if (IsEditingSubject())
EndEditSubject(xtpCalendarEditSubjectCommit, FALSE);
m_spDraggingStartOffset.SetStatus(COleDateTimeSpan::null);
m_eDraggingMode = xtpCalendaDragModeUnknown;
if (!pHitTest->pViewEvent || !pHitTest->pViewEvent->GetEvent())
return;
m_eDraggingMode = _GetDraggingMode(pHitTest);
ASSERT(m_eDraggingMode != xtpCalendaDragModeUnknown);
if (_IsDragModeCopyMove(m_eDraggingMode))
{
if (pHitTest->bTimePartValid)
{
m_spDraggingStartOffset = pHitTest->dt - pHitTest->pViewEvent->GetEvent()->GetStartTime();
}
else
{
m_spDraggingStartOffset = CXTPCalendarUtils::ResetTime(pHitTest->dt) -
CXTPCalendarUtils::ResetTime(pHitTest->pViewEvent->GetEvent()->GetStartTime());
}
if (!m_nKeyStateTimerID)
m_nKeyStateTimerID = SetTimer(50);
}
//---------------------------------------------------------------------------
VERIFY(SetDraggingEvent(pHitTest->pViewEvent->GetEvent()));
}
BOOL CXTPCalendarView::OnEndDragging(CPoint point, XTP_CALENDAR_HITTESTINFO* /*phitInfo*/)
{
if (!m_ptrDraggingEventNew || !m_ptrDraggingEventOrig ||
m_eDraggingMode == xtpCalendaDragModeEditSubject)
{
return FALSE;
}
CXTPCalendarEventPtr ptrEventToSelect = m_ptrDraggingEventNew;
BOOL bChanged = CommitDraggingEvent();
int nDragMode = m_eDraggingMode;
m_eDraggingMode = xtpCalendaDragModeUnknown;
if (bChanged && GetCalendarControl())
GetCalendarControl()->Populate();
UnselectAllEvents();
if (_IsDragModeCopyMove(nDragMode))
EmptyUndoBuffer();
if (ptrEventToSelect && (nDragMode == xtpCalendaDragModeResizeBegin || nDragMode == xtpCalendaDragModeResizeEnd))
{
CXTPCalendarControl::CUpdateContext updateContext(m_pControl, xtpCalendarUpdateRedraw);
COleDateTime dtFVDate = GetDateTimeDay(ptrEventToSelect->GetStartTime(), ptrEventToSelect->IsAllDayEvent());
if (nDragMode == xtpCalendaDragModeResizeEnd)
dtFVDate = CXTPCalendarUtils::RetriveEventEndDate(ptrEventToSelect);
CXTPCalendarViewEvent* pViewEvent = FindViewEvent(ptrEventToSelect, dtFVDate);
if (pViewEvent && pViewEvent->GetEvent())
{
SelectDay(XTP_SAFE_GET2(pViewEvent, GetViewGroup_(), GetViewDay_(), NULL),
XTP_SAFE_GET2(pViewEvent, GetViewGroup_(), GetGroupIndex(), -1));
BOOL bEnabled = XTP_SAFE_GET1(GetCalendarOptions(), bEnableInPlaceEditEventSubject_AfterEventResize, FALSE);
if (bEnabled)
bEnabled = !OnBeforeEditOperationNotify(xtpCalendarEO_EditSubject_AfterEventResize, pViewEvent);
BOOL bNo = pViewEvent->GetEvent()->GetDurationMinutes() < 1440;
if (bEnabled && bNo)
StartEditSubject(pViewEvent);
else
SelectEvent(pViewEvent->GetEvent());
}
}
SelectEvent(ptrEventToSelect);
return TRUE;
}
CXTPCalendarViewEvent* CXTPCalendarView::FindViewEvent(CXTPCalendarEvent* pEvent, COleDateTime dtDay) const
{
if (!pEvent)
{
ASSERT(FALSE);
return NULL;
}
dtDay = CXTPCalendarUtils::ResetTime(dtDay);
CXTPCalendarViewEvent* pFEView = NULL;
BOOL bFDayProceessed = FALSE;
int nCount = GetViewDayCount();
for (int i = 0; i < nCount; i++)
{
CXTPCalendarViewDay* pViewDay = GetViewDay_(i);
if (!pViewDay)
{
ASSERT(FALSE);
continue;
}
COleDateTime dtDayDate = pViewDay->GetDayDate();
int nGroupsCount = pViewDay->GetViewGroupsCount();
for (int g = 0; g < nGroupsCount; g++)
{
CXTPCalendarViewGroup* pViewGroup = pViewDay->GetViewGroup_(g);
ASSERT(pViewGroup);
if (!pViewGroup)
{
continue;
}
int nECount = pViewGroup->GetViewEventsCount();
for (int j = 0; j < nECount; j++)
{
CXTPCalendarViewEvent* pViewEvent = pViewGroup->GetViewEvent_(j);
CXTPCalendarEvent* pEv = pViewEvent ? pViewEvent->GetEvent() : NULL;
if (!pEv)
{
ASSERT(FALSE);
continue;
}
if (pEvent->IsEqualIDs(pEv) && pEvent->IsEqualStartEnd(pEv))
{
if (pViewEvent->IsVisible())
{
pFEView = pViewEvent;
}
if (CXTPCalendarUtils::IsEqual(dtDay, dtDayDate))
{
bFDayProceessed = TRUE;
}
if (pFEView && bFDayProceessed)
{
return pFEView;
}
}
}
}
}
return NULL;
}
CXTPCalendarViewEvent* CXTPCalendarView::FindViewEventByGroup(CXTPCalendarEvent* pEvent,
COleDateTime dtDay, int nScheduleID) const
{
if (!pEvent)
{
ASSERT(FALSE);
return NULL;
}
dtDay = CXTPCalendarUtils::ResetTime(dtDay);
CXTPCalendarViewEvent* pFEView = NULL;
BOOL bFDayProceessed = FALSE;
int nCount = GetViewDayCount();
for (int i = 0; i < nCount; i++)
{
CXTPCalendarViewDay* pViewDay = GetViewDay_(i);
if (!pViewDay)
{
ASSERT(FALSE);
continue;
}
COleDateTime dtDayDate = pViewDay->GetDayDate();
int nGroupsCount = pViewDay->GetViewGroupsCount();
if (nScheduleID < nGroupsCount)
{
CXTPCalendarViewGroup* pViewGroup = pViewDay->GetViewGroup_(nScheduleID);
ASSERT(pViewGroup);
if (!pViewGroup)
{
continue;
}
int nECount = pViewGroup->GetViewEventsCount();
for (int j = 0; j < nECount; j++)
{
CXTPCalendarViewEvent* pViewEvent = pViewGroup->GetViewEvent_(j);
CXTPCalendarEvent* pEv = pViewEvent ? pViewEvent->GetEvent() : NULL;
if (!pEv)
{
ASSERT(FALSE);
continue;
}
if (pEvent->IsEqualIDs(pEv) && pEvent->IsEqualStartEnd(pEv))
{
if (pViewEvent->IsVisible())
{
pFEView = pViewEvent;
}
if (CXTPCalendarUtils::IsEqual(dtDay, dtDayDate))
{
bFDayProceessed = TRUE;
}
if (pFEView && bFDayProceessed)
{
return pFEView;
}
}
}
}
}
return NULL;
}
BOOL CXTPCalendarView::HasSelectedViewEvent() const
{
if (!m_pSelectedEvents)
{
return FALSE;
}
return m_pSelectedEvents->GetCount() > 0;
}
CXTPCalendarViewEvents* CXTPCalendarView::GetSelectedViewEvents() const
{
return m_pSelectedEvents;
}
BOOL CXTPCalendarView::IsSingleEventSelected() const
{
int nCount = m_pSelectedEvents ? m_pSelectedEvents->GetCount() : 0;
if (nCount == 0)
return FALSE;
if (nCount == 1)
return TRUE;
CXTPCalendarEvent* pEvent = m_pSelectedEvents->GetAt(0)->GetEvent();
for (int i = 0; i < nCount; i++)
{
CXTPCalendarViewEvent* pViewEvent = m_pSelectedEvents->GetAt(i);
ASSERT(pViewEvent);
if (pViewEvent && !pViewEvent->GetEvent()->IsEqualIDs(pEvent))
return FALSE;
}
return TRUE;
}
CXTPCalendarViewEventsPtr CXTPCalendarView::GetSelectedEvents() const
{
CXTPCalendarViewEventsPtr ptrEventsWithViews = new CXTPCalendarViewEvents();
CXTPCalendarEvents arEvents;
ASSERT(m_pSelectedEvents);
if (!ptrEventsWithViews || !m_pSelectedEvents)
{
return NULL;
}
int nCount = m_pSelectedEvents->GetCount();
for (int i = 0; i < nCount; i++)
{
CXTPCalendarViewEvent* pViewEvent = m_pSelectedEvents->GetAt(i);
CXTPCalendarEvent* pEvent = pViewEvent ? pViewEvent->GetEvent() : NULL;
if (pEvent && arEvents.Find(pEvent) < 0)
{
arEvents.Add(pEvent, TRUE);
ptrEventsWithViews->Add(pViewEvent, TRUE);
}
}
return ptrEventsWithViews;
}
BOOL CXTPCalendarView::GetSelection(COleDateTime* pBegin, COleDateTime* pEnd,
BOOL* pbAllDayEvent, int* pnGroupIndex,
COleDateTimeSpan* pspSelectionResolution) const
{
if (!m_selectedBlock.IsValid())
{
return FALSE;
}
if (pspSelectionResolution)
{
*pspSelectionResolution = COleDateTimeSpan(1, 0, 0, 0);
}
if (pbAllDayEvent)
{
*pbAllDayEvent = TRUE;
}
if (pnGroupIndex)
{
*pnGroupIndex = m_selectedBlock.nGroupIndex;
}
//---------------------------------------------------------------------------
if (pBegin)
{
*pBegin = min(m_selectedBlock.dtBegin, m_selectedBlock.dtEnd);
}
if (pEnd)
{
*pEnd = max(m_selectedBlock.dtBegin, m_selectedBlock.dtEnd) + COleDateTimeSpan(1, 0, 0, 0);
}
return TRUE;
}
void CXTPCalendarView::SetSelection(const COleDateTime& dtBegin, const COleDateTime& dtEnd,
BOOL bAllDayEvent, int nGroupIndex)
{
m_selectedBlock.dtBegin = dtBegin;
m_selectedBlock.dtEnd = dtEnd;
m_selectedBlock.bAllDayEvent = bAllDayEvent;
m_selectedBlock.nGroupIndex = nGroupIndex;
CSelectionChangedContext selChanged(this, xtpCalendarSelectionDays);
}
void CXTPCalendarView::ResetSelection()
{
if (IsEditingSubject())
{
CXTPCalendarEventPtr ptrEditingEvent(m_ptrDraggingEventOrig, TRUE);
EndEditSubject(xtpCalendarEditSubjectCancel);
}
m_selectedBlock.dtBegin.SetStatus(COleDateTime::null);
m_selectedBlock.dtEnd.SetStatus(COleDateTime::null);
m_selectedBlock.bAllDayEvent = FALSE;
m_selectedBlock.nGroupIndex = -1;
CSelectionChangedContext selChanged(this, xtpCalendarSelectionDays);
}
BOOL CXTPCalendarView::SelectionContains(COleDateTime date, int nGroupIndex, BOOL* pbAllDaySelection)
{
COleDateTime dtBegin;
COleDateTime dtEnd;
int nSelGroupIndex;
if (GetSelection(&dtBegin, &dtEnd, pbAllDaySelection, &nSelGroupIndex))
{
if (nGroupIndex < 0 || nGroupIndex == nSelGroupIndex)
{
return (dtBegin <= date && (double)date <= (double)dtEnd - XTP_HALF_SECOND);
}
}
return FALSE;
}
COleDateTime CXTPCalendarView::GetNextTimeEditByTAB() const
{
ASSERT(GetViewDayCount() != 0);
COleDateTime dtDay;
if (m_selectedBlock.dtEnd.GetStatus() == COleDateTime::valid)
{
dtDay = m_selectedBlock.dtEnd;
}
else
{
dtDay = GetViewDayDate(0);
}
dtDay = CXTPCalendarUtils::ResetTime(dtDay);
return dtDay;
}
void CXTPCalendarView::UpdateNextTimeEditByTAB(COleDateTime dtNext, BOOL /*bReverse*/, BOOL /*bReset*/)
{
COleDateTime dtNextDay = CXTPCalendarUtils::ResetTime(dtNext);
COleDateTime dtCurrDay = CXTPCalendarUtils::ResetTime(GetNextTimeEditByTAB());
if (dtNextDay != dtCurrDay)
{
SelectDay(dtNextDay);
}
}
CXTPCalendarViewEvent* CXTPCalendarView::FindEventToEditByTAB(COleDateTime dtMinStart,
BOOL bReverse, CXTPCalendarEvent* pAfterEvent)
{
COleDateTime dtMinStartDay = CXTPCalendarUtils::ResetTime(dtMinStart);
COleDateTime dtMinStart2 = dtMinStartDay + COleDateTimeSpan(1, 0, 0, 0);
BOOL bAfterEventWas = pAfterEvent == NULL;
if (pAfterEvent)
{
COleDateTime dtAEStartDay = GetDateTimeDay(pAfterEvent->GetStartTime(), pAfterEvent->IsAllDayEvent());
if (bReverse ? dtAEStartDay > dtMinStartDay : dtAEStartDay < dtMinStartDay)
{
bAfterEventWas = TRUE;
}
}
int nDays = GetViewDayCount();
for (int nDay = bReverse ? nDays-1 : 0; bReverse ? nDay >= 0 : nDay < nDays;
bReverse ? nDay-- : nDay++)
{
CXTPCalendarViewDay* pVDay = GetViewDay_(nDay);
if (!pVDay)
{
ASSERT(FALSE);
continue;
}
COleDateTime dtDay = pVDay->GetDayDate();
if (bReverse ? dtDay > dtMinStartDay : dtDay < dtMinStartDay)
{
continue;
}
int nGroupsCount = pVDay->GetViewGroupsCount();
for (int nGroup = bReverse ? nGroupsCount - 1 : 0;
bReverse ? nGroup >= 0 : nGroup < nGroupsCount;
bReverse ? nGroup-- : nGroup++)
{
CXTPCalendarViewGroup* pViewGroup = pVDay->GetViewGroup_(nGroup);
ASSERT(pViewGroup);
if (!pViewGroup)
{
continue;
}
int nEvents = pViewGroup->GetViewEventsCount();
for (int nEvent = bReverse ? nEvents - 1 : 0;
bReverse ? nEvent >= 0 : nEvent < nEvents;
bReverse ? nEvent-- : nEvent++)
{
CXTPCalendarViewEvent* pVEvent = pViewGroup->GetViewEvent_(nEvent);
if (!pVEvent || !pVEvent->GetEvent())
{
ASSERT(FALSE);
continue;
}
if (pAfterEvent)
{
if (pAfterEvent->IsEqualIDs(pVEvent->GetEvent()))
{
bAfterEventWas = TRUE;
continue;
}
}
COleDateTime dtES = pVEvent->GetEvent()->GetStartTime();
COleDateTime dtESDay = GetDateTimeDay(dtES, pVEvent->GetEvent()->IsAllDayEvent());
if (bReverse ? (dtES > dtMinStart2 || dtESDay != dtDay) :
(dtES < dtMinStart || dtESDay < dtDay))
{
continue;
}
if (bAfterEventWas)
{
return pVEvent;
}
}
}
}
return NULL;
}
void CXTPCalendarView::UnselectAllEvents()
{
if (!m_pSelectedEvents || !GetCalendarControl())
{
return;
}
int nCount = m_pSelectedEvents->GetCount();
m_pSelectedEvents->RemoveAll();
if (nCount)
{
CXTPCalendarControl::CUpdateContext updateContext(GetCalendarControl(), xtpCalendarUpdateRedraw);
CSelectionChangedContext selChanged(this, xtpCalendarSelectionEvents);
}
}
void CXTPCalendarView::_ReSelectSelectEvents()
{
if (!m_pSelectedEvents)
return;
CXTPCalendarViewEventsPtr ptrSelEvents = GetSelectedEvents();
m_pSelectedEvents->RemoveAll();
CXTPCalendarEvent* pEvent;
if (ptrSelEvents)
{
int nCount = ptrSelEvents->GetCount();
for (int i = 0; i < nCount; i++)
{
if (ptrSelEvents->GetAt(i))
{
pEvent = ptrSelEvents->GetAt(i)->GetEvent();
if (pEvent)
SelectEvent(pEvent);
}
}
}
}
void CXTPCalendarView::SelectDays(COleDateTime dtNewSel)
{
CXTPCalendarControl::CUpdateContext updateContext(GetCalendarControl(), xtpCalendarUpdateRedraw);
m_selectedBlock.dtEnd = dtNewSel;
CSelectionChangedContext selChanged(this, xtpCalendarSelectionDays);
}
void CXTPCalendarView::SelectDay(COleDateTime dtSelDay, int nGroupIndex)
{
CXTPCalendarControl::CUpdateContext updateContext(GetCalendarControl(), xtpCalendarUpdateRedraw);
m_selectedBlock.dtBegin = m_selectedBlock.dtEnd = dtSelDay;
m_selectedBlock.nGroupIndex = nGroupIndex;
CSelectionChangedContext selChanged(this, xtpCalendarSelectionDays);
}
void CXTPCalendarView::SelectDay(CXTPCalendarViewDay* pDay, int nGroupIndex)
{
ASSERT(pDay);
if (pDay)
{
SelectDay(pDay->GetDayDate(), nGroupIndex);
}
}
void CXTPCalendarView::SelectViewEvent(CXTPCalendarViewEvent* pViewEvent, BOOL bSelect)
{
if (!m_pSelectedEvents || !pViewEvent || !pViewEvent->GetEvent())
{
ASSERT(FALSE);
return;
}
m_pSelectedEvents->Remove(pViewEvent->GetEvent());
if (bSelect)
{
pViewEvent->InternalAddRef();
m_pSelectedEvents->Add(pViewEvent);
}
CSelectionChangedContext selChanged(this, xtpCalendarSelectionEvents);
}
CXTPCalendarViewEvent* CXTPCalendarView::GetLastSelectedViewEvent() const
{
if (m_pSelectedEvents && m_pSelectedEvents->GetCount() > 0)
return m_pSelectedEvents->GetAt(m_pSelectedEvents->GetCount() - 1);
return NULL;
}
void CXTPCalendarView::SelectEvent(CXTPCalendarEvent* pEvent, BOOL bSelect)
{
if (!pEvent)
{
ASSERT(FALSE);
return;
}
int nCount = GetViewDayCount();
for (int i = 0; i < nCount; i++)
{
CXTPCalendarViewDay* pViewDay = GetViewDay_(i);
if (!pViewDay)
{
ASSERT(FALSE);
continue;
}
int nGroupsCount = pViewDay->GetViewGroupsCount();
for (int g = 0; g < nGroupsCount; g++)
{
CXTPCalendarViewGroup* pViewGroup = pViewDay->GetViewGroup_(g);
ASSERT(pViewGroup);
if (!pViewGroup)
{
continue;
}
int nECount = pViewGroup->GetViewEventsCount();
for (int j = 0; j < nECount; j++)
{
CXTPCalendarViewEvent* pViewEvent = pViewGroup->GetViewEvent_(j);
CXTPCalendarEvent* pEv = pViewEvent ? pViewEvent->GetEvent() : NULL;
ASSERT(pEv);
if (pEv && pEvent->IsEqualIDs(pEv) && pEvent->IsEqualStartEnd(pEv))
{
CXTPCalendarControl::CUpdateContext updateContext(GetCalendarControl(), xtpCalendarUpdateRedraw);
SelectViewEvent(pViewEvent, bSelect);
}
}
}
}
}
BOOL CXTPCalendarView::OnDragging(CPoint /*point*/, XTP_CALENDAR_HITTESTINFO* pHitTest)
{
ASSERT(pHitTest);
if (!pHitTest || !m_ptrDraggingEventNew || m_eDraggingMode == xtpCalendaDragModeEditSubject)
{
return FALSE;
}
//---------------------------------------------------------------------------
if (pHitTest->pViewDay)
{
if (m_eDraggingMode == xtpCalendaDragModeResizeBegin || m_eDraggingMode == xtpCalendaDragModeResizeEnd)
{
SelectDay(pHitTest->pViewDay, pHitTest->nGroup);
}
}
//---------------------------------------------------------------------------
COleDateTime dtNewTime;
if (_IsDragModeCopyMove(m_eDraggingMode))
{
if (!pHitTest->bTimePartValid)
{
dtNewTime = CXTPCalendarUtils::UpdateDate(m_ptrDraggingEventNew->GetStartTime(), pHitTest->dt);
}
else
{
dtNewTime = pHitTest->dt;
}
dtNewTime -= m_spDraggingStartOffset;
BOOL bChanged = FALSE;
//------------------------------------
if (!CXTPCalendarUtils::IsEqual(dtNewTime, m_ptrDraggingEventNew->GetStartTime()))
{
m_ptrDraggingEventNew->MoveEvent(dtNewTime);
bChanged = TRUE;
}
//***
if (bChanged)
{
return TRUE;
}
}
else if (m_eDraggingMode == xtpCalendaDragModeResizeBegin)
{
dtNewTime = pHitTest->dt;
COleDateTime dtEventEnd = m_ptrDraggingEventNew->GetEndTime();
if (!CXTPCalendarUtils::IsEqual(dtNewTime, m_ptrDraggingEventNew->GetStartTime()))
{
if (dtNewTime > dtEventEnd)
{
dtNewTime = dtEventEnd;
}
m_ptrDraggingEventNew->SetStartTime(dtNewTime);
BOOL bIsZeroStartEnd = CXTPCalendarUtils::IsZeroTime(m_ptrDraggingEventNew->GetStartTime()) &&
CXTPCalendarUtils::IsZeroTime(m_ptrDraggingEventNew->GetEndTime());
BOOL bIsZeroLen = CXTPCalendarUtils::IsEqual(m_ptrDraggingEventNew->GetStartTime(),
m_ptrDraggingEventNew->GetEndTime());
m_ptrDraggingEventNew->SetAllDayEvent(bIsZeroStartEnd && !bIsZeroLen);
return TRUE;
}
}
else if (m_eDraggingMode == xtpCalendaDragModeResizeEnd)
{
dtNewTime = pHitTest->dt;
if (!pHitTest->bTimePartValid)
{
dtNewTime += COleDateTimeSpan(1, 0, 0, 0);
}
COleDateTime dtEventStart = m_ptrDraggingEventNew->GetStartTime();
if (!CXTPCalendarUtils::IsEqual(dtNewTime, m_ptrDraggingEventNew->GetEndTime()))
{
if ((pHitTest->uHitCode & xtpCalendarHitTestDayViewTimeScale) &&
(pHitTest->pViewDay == NULL))
{
dtNewTime.SetDateTime(
dtEventStart.GetYear(), dtEventStart.GetMonth(), dtEventStart.GetDay(),
dtNewTime.GetHour(), dtNewTime.GetMinute(), dtNewTime.GetSecond());
}
if (dtNewTime < dtEventStart)
{
dtNewTime = dtEventStart;
}
m_ptrDraggingEventNew->SetEndTime(dtNewTime);
BOOL bIsZeroStartEnd = CXTPCalendarUtils::IsZeroTime(m_ptrDraggingEventNew->GetStartTime()) &&
CXTPCalendarUtils::IsZeroTime(m_ptrDraggingEventNew->GetEndTime());
BOOL bIsZeroLen = CXTPCalendarUtils::IsEqual(m_ptrDraggingEventNew->GetStartTime(),
m_ptrDraggingEventNew->GetEndTime());
m_ptrDraggingEventNew->SetAllDayEvent(bIsZeroStartEnd && !bIsZeroLen);
return TRUE;
}
}
return FALSE;
}
COleDateTime CXTPCalendarView::GetLastSelectedDate() const
{
if (m_selectedBlock.dtEnd.GetStatus() != COleDateTime::valid)
{
return GetViewDayDate(GetViewDayCount() / 2);
}
return CXTPCalendarUtils::ResetTime(m_selectedBlock.dtEnd);
}
int CXTPCalendarView::FindLastSelectedDay() const
{
COleDateTime dt = GetLastSelectedDate();
int nCount = GetViewDayCount();
for (int i = 0; i < nCount; i++)
{
CXTPCalendarViewDay* pViewDay = GetViewDay_(i);
ASSERT(pViewDay);
if (pViewDay && CXTPCalendarUtils::IsEqual(pViewDay->GetDayDate(), dt))
return i;
}
return -1;
}
void CXTPCalendarView::ProcessDaySelection(XTP_CALENDAR_HITTESTINFO* pInfo, UINT nFlags)
{
ASSERT(pInfo);
if (!pInfo)
{
UnselectAllEvents();
return;
}
if (nFlags & MK_SHIFT)
{
COleDateTime dtNewSelDay = GetViewDayDate(pInfo->nDay);
SelectDays(dtNewSelDay);
}
else
{
UnselectAllEvents();
ASSERT(pInfo->pViewDay);
if (pInfo->pViewDay)
{
pInfo->pViewDay->SetSelected();
}
}
}
void CXTPCalendarView::ProcessEventSelection(XTP_CALENDAR_HITTESTINFO* pInfo, UINT nFlags)
{
ASSERT(pInfo);
if (!pInfo)
{
return;
}
BOOL bUnselectEvents = !(nFlags & (MK_SHIFT | MK_CONTROL));
if (bUnselectEvents)
UnselectAllEvents();
ASSERT(pInfo->pViewDay);
ASSERT(pInfo->pViewEvent);
if (pInfo->pViewDay)
{
pInfo->pViewDay->SetSelected();
}
if (pInfo->pViewEvent)
{
BOOL bSelect = TRUE;
if (nFlags & MK_CONTROL)
{
bSelect = !pInfo->pViewEvent->IsSelected();
}
SelectEvent(pInfo->pViewEvent->GetEvent(), bSelect);
}
}
UINT CXTPCalendarView::SetTimer(UINT uTimeOut_ms)
{
if (GetCalendarControl())
{
return GetCalendarControl()->SetTimer(uTimeOut_ms);
}
return 0;
}
void CXTPCalendarView::KillTimer(UINT uTimerID)
{
if (GetCalendarControl())
{
VERIFY(GetCalendarControl()->KillTimer(uTimerID));
}
}
BOOL CXTPCalendarView::OnTimer(UINT_PTR uTimerID)
{
if (TBase::OnTimer(uTimerID))
{
return TRUE;
}
CXTPCalendarThemeOffice2007* pThemeX = DYNAMIC_DOWNCAST(CXTPCalendarThemeOffice2007, GetTheme());
if (pThemeX)
{
if (pThemeX->OnTimer(uTimerID))
return TRUE;
}
if (uTimerID == m_nTimerID_StartEditSubject)
{
KillTimer(m_nTimerID_StartEditSubject);
m_nTimerID_StartEditSubject = 0;
ASSERT(m_ptrEditingViewEvent);
if (m_ptrEditingViewEvent)
{
EmptyUndoBuffer();
StartEditSubject(m_ptrEditingViewEvent);
}
return TRUE;
}
else if (uTimerID == m_nKeyStateTimerID)
{
BOOL bIsCtrl = (GetKeyState(VK_CONTROL) < 0);
XTPCalendarDraggingMode eDraggingMode = bIsCtrl ? xtpCalendaDragModeCopy : xtpCalendaDragModeMove;
BOOL bPopulate = FALSE;
if (!_IsDragModeCopyMove(m_eDraggingMode))
{
KillTimer(m_nKeyStateTimerID);
m_nKeyStateTimerID = 0;
}
else if (m_eDraggingMode != eDraggingMode)
{
ASSERT(m_ptrDraggingEventNew);
if (m_ptrDraggingEventNew)
{
CXTPCalendarViewEvent* pEventView = FindViewEvent(m_ptrDraggingEventNew, m_ptrDraggingEventNew->GetStartTime());
if (!IsEditOperationDisabledNotify(_DragMod2Operation(eDraggingMode), pEventView))
{
m_eDraggingMode = eDraggingMode;
bPopulate = TRUE;
}
}
}
if (bPopulate && GetCalendarControl())
{
GetCalendarControl()->Populate();
GetCalendarControl()->m_mouseMode = m_eDraggingMode == xtpCalendaDragModeCopy ?
xtpCalendarMouseEventDragCopy : xtpCalendarMouseEventDragMove;
GetCalendarControl()->UpdateMouseCursor();
}
return TRUE;
}
else if (uTimerID == m_nTimerID_ShowToolTip)
{
ShowToolTip();
return TRUE;
}
return FALSE;
}
BOOL CXTPCalendarView::OnLButtonDblClk(UINT nFlags, CPoint point)
{
if (m_nTimerID_StartEditSubject)
{
KillTimer(m_nTimerID_StartEditSubject);
m_nTimerID_StartEditSubject = 0;
m_ptrEditingViewEvent = NULL;
}
return TBase::OnLButtonDblClk(nFlags, point);
}
void CXTPCalendarView::OnDraw(CDC* pDC)
{
if (GetTheme())
Draw2(pDC);
else
Draw(pDC);
}
void CXTPCalendarView::AdjustLayout(CDC* pDC, const CRect& rcView, BOOL bCallPostAdjustLayout)
{
UNREFERENCED_PARAMETER(pDC);
m_rcView = rcView;
_CalculateEventTimeFormat();
if (bCallPostAdjustLayout)
{
OnPostAdjustLayout();
}
}
void CXTPCalendarView::AdjustLayout2(CDC* pDC, const CRect& rcView, BOOL bCallPostAdjustLayout)
{
UNREFERENCED_PARAMETER(pDC);
UNREFERENCED_PARAMETER(bCallPostAdjustLayout);
ASSERT(GetTheme());
m_rcView = rcView;
//_CalculateEventTimeFormat();
// if (bCallPostAdjustLayout)
// {
// OnPostAdjustLayout();
// }
}
CXTPCalendarViewDay* CXTPCalendarView::_GetViewDay(const COleDateTime& dt) const
{
COleDateTime dtDay = CXTPCalendarUtils::ResetTime(dt);
int nDaysCount = GetViewDayCount();
if (!nDaysCount || !GetViewDay_(0))
{
return NULL;
}
COleDateTime dtDay0 = GetViewDay_(0)->GetDayDate();
COleDateTimeSpan spShift = dtDay - dtDay0;
ASSERT((double)spShift == (double)((int)(double)spShift) );
int nShift = CXTPCalendarUtils::GetTotalDays(spShift); //(int)(double)spShift
if (nShift < 0)
{
nShift = 0;
}
if (nShift >= nDaysCount)
{
nShift = nDaysCount - 1;
}
if (nShift >= 0 && nShift < nDaysCount)
{
return GetViewDay_(nShift);
}
return NULL;
}
COleDateTime CXTPCalendarView::GetDateTimeDay(const COleDateTime& dt, BOOL bWholeDayEvent) const
{
CXTPCalendarOptions* pOptions = GetCalendarControl()->GetCalendarOptions();
if ((DATE)pOptions->dtScaleMaxTime <= 1 || bWholeDayEvent)
return CXTPCalendarUtils::ResetTime(dt);
return CXTPCalendarUtils::ResetTime(dt - pOptions->dtScaleMinTime);
}
void CXTPCalendarView::StartEditNewEventInplace(LPCTSTR pcszInitialSubject)
{
if (m_ptrDraggingEventOrig || m_ptrDraggingEventNew || IsEditingSubject())
{
MessageBeep(0);
return;
}
BOOL bAllDayEvent = FALSE;
//---------------------------------------------------------------------------
COleDateTime dtSelBegin, dtSelEnd;
int nGroup = 0;
if (!GetSelection(&dtSelBegin, &dtSelEnd, &bAllDayEvent, &nGroup))
{
return;
}
//---------------------------------------------------------------------------
CXTPCalendarData* pData = NULL; //XTP_SAFE_GET1(GetCalendarControl(), GetDataProvider(), NULL);
CXTPCalendarViewDay* pViewDay = _GetViewDay(dtSelBegin);
if (!pViewDay)
{
return;
}
CXTPCalendarViewGroup* pViewGroup = NULL;
if (pViewDay && nGroup < pViewDay->GetViewGroupsCount())
{
pViewGroup = pViewDay->GetViewGroup_(nGroup);
pData = pViewGroup ? pViewGroup->GetDataProvider() : NULL;
}
//if (pData != NULL
// && pData->GetCustomProperties() != NULL)
//{
// CString sType(_T("Public"));
// CString sXML(_T("F:\\SecurityType.xml"));
// COleVariant rVarValue(sType);
// pData->GetCustomProperties()->LoadFromXML(sXML);
// if (pData->GetCustomProperties()->GetProperty(_T("SecurityType"), rVarValue))
// {
// AfxMessageBox(_T("SecurityType found"));
// }
// else
// {
// AfxMessageBox(_T("SecurityType not found"));
// pData->GetCustomProperties()->SetProperty(_T("SecurityType"), rVarValue);
// pData->GetCustomProperties()->SaveToXML(sXML);
// }
//}
m_ptrDraggingEventNew = pData ? pData->CreateNewEvent() : NULL;
if (!m_ptrDraggingEventNew)
{
return;
}
//---------------------------------------------------------------------------
UINT uScheduleID = XTP_SAFE_GET1(pViewGroup, GetScheduleID(), 0);
m_ptrDraggingEventNew->SetScheduleID(uScheduleID);
m_ptrDraggingEventNew->SetStartTime(min(dtSelBegin, dtSelEnd));
m_ptrDraggingEventNew->SetEndTime(max(dtSelBegin, dtSelEnd));
m_ptrDraggingEventNew->SetBusyStatus(bAllDayEvent ? xtpCalendarBusyStatusFree : xtpCalendarBusyStatusBusy);
m_ptrDraggingEventNew->SetAllDayEvent(bAllDayEvent);
//===========================================================================
XTP_SAFE_CALL1(GetCalendarControl(), Populate());
XTP_SAFE_CALL1(GetCalendarControl(), AdjustLayout());
//---------------------------------------------------------------------------
COleDateTime dtEventDay = m_ptrDraggingEventNew->GetStartTime();
dtEventDay = GetDateTimeDay(dtEventDay, m_ptrDraggingEventNew->IsAllDayEvent());
CXTPCalendarViewEvent* pViewEvent = FindViewEvent(m_ptrDraggingEventNew, dtEventDay);
if (!pViewEvent)
{
CancelDraggingEvent();
return;
}
StartEditSubject(pViewEvent);
CEdit* pEditor = DYNAMIC_DOWNCAST(CEdit, pViewEvent->GetSubjectEditor());
if (pEditor)
{
pEditor->SetWindowText(pcszInitialSubject);
int nInitTxtLen = (int)_tcsclen(pcszInitialSubject);
pEditor->SetSel(nInitTxtLen, nInitTxtLen);
}
}
void CXTPCalendarView::StartEditSubject(CXTPCalendarViewEvent* pViewEvent)
{
if (!pViewEvent)
return;
if (m_nTimerID_StartEditSubject)
{
KillTimer(m_nTimerID_StartEditSubject);
m_nTimerID_StartEditSubject = 0;
}
m_ptrEditingViewEvent = pViewEvent->StartEditSubject();
if (!m_ptrEditingViewEvent)
return;
CXTPCalendarControl::CUpdateContext updateContext(m_pControl, xtpCalendarUpdateRedraw);
m_ptrEditingViewEvent->InternalAddRef();
m_eDraggingMode = xtpCalendaDragModeEditSubject;
if (!m_ptrDraggingEventOrig && !m_ptrDraggingEventNew)
SetDraggingEvent(m_ptrEditingViewEvent->GetEvent());
SelectEvent(m_ptrDraggingEventNew);
}
void CXTPCalendarView::EndEditSubject(XTPCalendarEndEditSubjectAction eAction, BOOL bUpdateControl)
{
m_eDraggingMode = xtpCalendaDragModeUnknown;
// kill timeout request to edit subject
if (m_nTimerID_StartEditSubject)
{
ASSERT(m_ptrEditingViewEvent && !m_ptrDraggingEventOrig && !m_ptrDraggingEventNew);
KillTimer(m_nTimerID_StartEditSubject);
m_nTimerID_StartEditSubject = 0;
m_ptrEditingViewEvent = NULL;
return;
}
ASSERT(m_ptrEditingViewEvent && m_ptrDraggingEventNew);
CXTPCalendarEventPtr ptrEventToSelect(m_ptrDraggingEventNew, TRUE);
BOOL bPopulate = FALSE;
CString strNewSubject;
//- end edit subject operation in Event view (kill edit wnd) ----------------
if (m_ptrEditingViewEvent)
strNewSubject = m_ptrEditingViewEvent->EndEditSubject();
m_ptrEditingViewEvent = NULL;
//---------------------------------------------------------------------------
if (m_ptrDraggingEventNew)
{
if (eAction == xtpCalendarEditSubjectCommit)
{
m_ptrDraggingEventNew->SetSubject(strNewSubject);
if (!strNewSubject.IsEmpty())
bPopulate = CommitDraggingEvent();
else
{
ptrEventToSelect.SetPtr(m_ptrDraggingEventOrig, TRUE);
CancelDraggingEvent();
bPopulate = TRUE;
}
}
else if (eAction == xtpCalendarEditSubjectCancel)
{
ptrEventToSelect.SetPtr(m_ptrDraggingEventOrig, TRUE);
CancelDraggingEvent();
bPopulate = TRUE;
}
else
{
ASSERT(FALSE);
}
}
if (bUpdateControl && bPopulate && GetCalendarControl())
{
GetCalendarControl()->Populate();
if (ptrEventToSelect)
{
SelectEvent(ptrEventToSelect, TRUE);
}
}
}
void CXTPCalendarView::OnUpdateEditingSubject(CString strNewSubject)
{
if (m_ptrEditingViewEvent && m_ptrDraggingEventNew)
m_ptrDraggingEventNew->SetSubject(strNewSubject);
}
CRect CXTPCalendarView::GetSubjectEditorRect() const
{
ASSERT(m_ptrEditingViewEvent);
if (m_ptrEditingViewEvent)
{
return m_ptrEditingViewEvent->GetSubjectEditorRect();
}
return CRect(INT_MAX, INT_MAX, INT_MAX, INT_MAX);
}
CRect CXTPCalendarView::GetTooltipRect(const CPoint& ptHit, const XTP_CALENDAR_HITTESTINFO& hitInfo) const
{
CRect rcTip;
rcTip.SetRectEmpty();
if (hitInfo.pViewGroup)
{
rcTip = hitInfo.pViewGroup->GetTooltipRect(ptHit, hitInfo);
CXTPCalendarThemeOffice2007* pThemeX = DYNAMIC_DOWNCAST(CXTPCalendarThemeOffice2007, GetTheme());
if (pThemeX)
{
CRect rcExclude = XTP_SAFE_GET2(pThemeX->GetPrevNextEventButtonsPartX(),
GetNextEventButtonPartX(), GetRect(), CRect(0, 0, 0, 0));
if (!(rcTip.top > rcExclude.bottom || rcTip.bottom < rcExclude.top)
&& rcTip.right >= rcExclude.left)
{
rcTip.right = rcExclude.left - 1;
}
rcExclude = XTP_SAFE_GET2(pThemeX->GetPrevNextEventButtonsPartX(),
GetPrevEventButtonPartX(), GetRect(), CRect(0, 0, 0, 0));
if (!(rcTip.top > rcExclude.bottom || rcTip.bottom < rcExclude.top)
&& rcTip.left <= rcExclude.right)
{
rcTip.left = rcExclude.right + 1;
}
}
}
return rcTip;
}
void CXTPCalendarView::ShowToolTip(BOOL bShow)
{
if (m_nTimerID_ShowToolTip)
{
KillTimer(m_nTimerID_ShowToolTip);
m_nTimerID_ShowToolTip = 0;
}
CXTPCalendarControl* pControl = GetCalendarControl();
if (!pControl)
return;
if (!bShow)
{
// hide a tooltip
pControl->HideToolTip();
return;
}
if (pControl->IsToolTipVisible())
{
return;
}
// Verify whether mouse is still under tooltip rect
CRect rcTooltip;
rcTooltip.SetRectEmpty();
CPoint pt;
GetCursorPos(&pt);
pControl->ScreenToClient(&pt);
XTP_CALENDAR_HITTESTINFO hitInfo;
BOOL bHitTest = HitTest(pt, &hitInfo);
if (bHitTest)
{
rcTooltip = GetTooltipRect(pt, hitInfo);
}
if (m_rcTooltip != rcTooltip)
m_rcTooltip.SetRectEmpty();
if (m_rcTooltip.IsRectEmpty())
return;
CString strTip;
if (GetViewType() != xtpCalendarTimeLineView)
{
// if we are under event view -- do not show this tooltip
if (NULL != hitInfo.pViewEvent)
return;
BOOL bTipEnabled = XTP_SAFE_GET2(pControl, GetCalendarOptions(), bEnableAddNewTooltip, TRUE);
BOOL bAllowCreate = XTP_SAFE_GET2(pControl, GetCalendarOptions(), bEnableInPlaceCreateEvent, TRUE);
if (!bTipEnabled || !bAllowCreate)
return;
// create tooltip text
if (!pControl->m_bReadOnlyMode)
strTip = XTP_SAFE_GET2(pControl, GetCalendarOptions(), strTooltipAddNewText, _T("Click to add appointment"));
else
strTip.Empty();
}
else if (hitInfo.pViewEvent) //TimeLine mode
{
if (hitInfo.pViewEvent->GetEvent()
&& hitInfo.pViewEvent->GetEvent()->IsEventVisible())
strTip = hitInfo.pViewEvent->GetEvent()->GetSubject();
}
// show tooltip window
if (pControl)
{
CFont* pFont = &XTP_SAFE_GET2(GetPaintManager(), GetDayViewEventPart(), GetTextFont(), *((CFont*)(NULL)));
pControl->ShowToolTip(strTip, m_rcTooltip, pFont, TRUE);
}
}
void CXTPCalendarView::_CalculateEventTimeFormat()
{
////////////////////////////////////////////////////////////////////////////
// LOCALE_STIME // time separator
//
// LOCALE_ITLZERO //leading zeros in time field
// 0 No leading zeros for hours.
// 1 Leading zeros for hours.
//
// LOCALE_ITIME // time format specifier
// 0 AM / PM 12-hour format.
// 1 24-hour format.
//
// LOCALE_ITIMEMARKPOSN // time marker position
// 0 Use as suffix.
// 1 Use as prefix.
//
// LOCALE_S1159 // AM designator
// LOCALE_S2359 // PM designator
////////////////////////////////////////////////////////////////////////////
if(m_EventTimeFormat.isCustom == TRUE)
return;
CString strTmp;
CString strTimeSeparator = CXTPCalendarUtils::GetLocaleString(LOCALE_STIME, 16);
strTmp = CXTPCalendarUtils::GetLocaleString(LOCALE_ITIME, 16);
BOOL b24_HFormat = _ttoi(strTmp) == 1;
strTmp = CXTPCalendarUtils::GetLocaleString(LOCALE_ITLZERO, 16);
BOOL bH_LZero = _ttoi(strTmp) == 1;
strTmp = CXTPCalendarUtils::GetLocaleString(LOCALE_ITIMEMARKPOSN, 16);
BOOL bAM_PM_Prefix = _ttoi(strTmp) == 1;
//---------------------------------------------------------------------------
CString strTimeFormat;
strTimeFormat += strTimeSeparator;
strTimeFormat += _T("mm");
if (b24_HFormat)
{
strTmp = bH_LZero ? _T("HH") : _T("H");
strTimeFormat = strTmp + strTimeFormat;
}
else //12 AM/PM Format
{
strTmp = bH_LZero ? _T("hh") : _T("h");
strTimeFormat = strTmp + strTimeFormat;
if (bAM_PM_Prefix)
{
strTimeFormat = _T("tt ") + strTimeFormat;
}
else
{
strTimeFormat = strTimeFormat + _T("tt");
}
}
//---------------------------------------------------------------------------
m_EventTimeFormat.strFormat = strTimeFormat;
m_EventTimeFormat.b24_HFormat = b24_HFormat;
m_EventTimeFormat.strAM = CXTPCalendarUtils::GetLocaleString(LOCALE_S1159, 20);
m_EventTimeFormat.strPM = CXTPCalendarUtils::GetLocaleString(LOCALE_S2359, 20);
}
CString CXTPCalendarView::FormatEventTime(COleDateTime dtTime) const
{
CString strTime;
SYSTEMTIME st;
ZeroMemory(&st, sizeof(st));
if (CXTPCalendarUtils::GetAsSystemTime(dtTime, st))
{
strTime = CXTPCalendarUtils::GetTimeFormat(&st, m_EventTimeFormat.strFormat);
}
if (strTime.IsEmpty())
{
ASSERT(FALSE);
strTime.Format(_T("%d:%02d"), dtTime.GetHour(), dtTime.GetMinute());
}
//- make AM/PM as lower case ---------------------------------------
if (!m_EventTimeFormat.b24_HFormat)
{
CString strAM_lower = m_EventTimeFormat.strAM;
CString strPM_lower = m_EventTimeFormat.strPM;
strAM_lower.MakeLower();
strPM_lower.MakeLower();
strTime.Replace(m_EventTimeFormat.strAM, strAM_lower);
strTime.Replace(m_EventTimeFormat.strPM, strPM_lower);
}
return strTime;
}
void CXTPCalendarView::SetCustomTimeFormat(const CString& strFormat)
{
m_EventTimeFormat.strFormat = strFormat;
m_EventTimeFormat.isCustom = TRUE;
m_EventTimeFormat.b24_HFormat = TRUE;
m_EventTimeFormat.strAM = _T("");
m_EventTimeFormat.strPM = _T("");
}
void CXTPCalendarView::ResetCustomTimeFormat()
{
m_EventTimeFormat.isCustom = FALSE;
_CalculateEventTimeFormat();
}
CString CXTPCalendarView::GetItemTextEventTimeMax() const
{
COleDateTime dtTestTime;
dtTestTime.SetTime(23, 59, 59);
CString strTime = FormatEventTime(dtTestTime);
DWORD dwFlags = GetCalendarControl()->GetAskItemTextFlags();
if (dwFlags & (xtpCalendarItemText_EventStartTimeText | xtpCalendarItemText_EventEndTimeText))
{
XTP_CALENDAR_GETITEMTEXT_PARAMS objRequest;
::ZeroMemory(&objRequest, sizeof(objRequest));
objRequest.nItem = xtpCalendarItemText_EventStartTimeText /*| xtpCalendarItemText_EventEndTimeText*/;
objRequest.pstrText = &strTime;
GetCalendarControl()->SendNotificationAlways(XTP_NC_CALENDAR_GETITEMTEXT, (WPARAM)&objRequest, 0);
}
return strTime;
}
BOOL CXTPCalendarView::_Undo(CXTPCalendarEvent* pEvent)
{
if (IsEditingSubject())
EndEditSubject(xtpCalendarEditSubjectCommit);
if (!GetCalendarControl())
return FALSE;
CXTPAutoResetValue<BOOL> autoSet_UpdateCtrlNf(GetCalendarControl()->m_bUpdateWhenEventChangedNotify);
autoSet_UpdateCtrlNf = FALSE;
CXTPCalendarEventPtr ptrEventNew;
CXTPCalendarEventPtr ptrEventOld;
if (pEvent)
{
ptrEventNew = m_pUndoBuffer->UndoAllForEvent(pEvent);
ptrEventOld = m_pUndoBuffer->RedoAllForEvent(pEvent);
}
else
{
CXTPCalendarEventPtr ptrUndoEvent = m_pUndoBuffer->GetFirstUndoEvent();
if (ptrUndoEvent)
{
if (m_eUndoMode == xtpCalendarUndoModeUndo)
{
ptrEventNew = m_pUndoBuffer->UndoAllForEvent(ptrUndoEvent);
ptrEventOld = m_pUndoBuffer->RedoAllForEvent(ptrUndoEvent);
m_eUndoMode = xtpCalendarUndoModeRedo;
}
else
if (m_eUndoMode == xtpCalendarUndoModeRedo)
{
ptrEventNew = m_pUndoBuffer->RedoAllForEvent(ptrUndoEvent);
ptrEventOld = m_pUndoBuffer->UndoAllForEvent(ptrUndoEvent);
m_eUndoMode = xtpCalendarUndoModeUndo;
}
else
{
ASSERT(FALSE);
return FALSE;
}
}
}
if (ptrEventNew || ptrEventOld)
{
CXTPCalendarControl::CUpdateContext updateContext(m_pControl, xtpCalendarUpdateLayout | xtpCalendarUpdateRedraw);
if (ptrEventNew && ptrEventOld && ptrEventNew->GetDataProvider())
{
VERIFY( ptrEventNew->GetDataProvider()->ChangeEvent(ptrEventNew) );
}
else if (ptrEventNew && !ptrEventOld && ptrEventNew->GetDataProvider())
{
VERIFY( ptrEventNew->GetDataProvider()->AddEvent(ptrEventNew) );
}
else if (!ptrEventNew && ptrEventOld && ptrEventOld->GetDataProvider())
{
VERIFY( ptrEventOld->GetDataProvider()->DeleteEvent(ptrEventOld) );
}
XTP_SAFE_CALL1(GetCalendarControl(), Populate());
return TRUE;
}
return FALSE;
}
BOOL CXTPCalendarView::CanUndo() const
{
if (m_eUndoMode == xtpCalendarUndoModeUndo && m_pUndoBuffer->GetCount())
return TRUE;
return _CanSubjectEditor(ID_EDIT_UNDO);
}
CWnd* CXTPCalendarView::_GetSubjectEditorWnd() const
{
if (m_ptrEditingViewEvent)
return m_ptrEditingViewEvent->GetSubjectEditor();
return NULL;
}
BOOL CXTPCalendarView::_CanSubjectEditor(UINT idEditCmd) const
{
CWnd* pSEditorWnd = _GetSubjectEditorWnd();
if (!pSEditorWnd)
return FALSE;
CEdit* pSEditor = DYNAMIC_DOWNCAST(CEdit, pSEditorWnd);
if (!pSEditor)
return FALSE;
BOOL bSEFocused = CWnd::GetFocus() &&
CWnd::GetFocus()->GetSafeHwnd() == pSEditorWnd->GetSafeHwnd();
if (!bSEFocused)
return FALSE;
int nSel1 = -1, nSel2 = -1;
pSEditor->GetSel(nSel1, nSel2);
switch (idEditCmd)
{
case ID_EDIT_UNDO:
return pSEditor->CanUndo();
case ID_EDIT_CUT:
return nSel1 < nSel2;
case ID_EDIT_COPY:
return nSel1 < nSel2;
case ID_EDIT_PASTE:
return ::IsClipboardFormatAvailable(CF_TEXT);
}
return FALSE;
}
BOOL CXTPCalendarView::CanRedo() const
{
return m_eUndoMode == xtpCalendarUndoModeRedo && m_pUndoBuffer->GetCount();
}
BOOL CXTPCalendarView::Undo()
{
ASSERT(m_eUndoMode == xtpCalendarUndoModeUndo || _CanSubjectEditor(ID_EDIT_UNDO));
return _Undo();
}
BOOL CXTPCalendarView::Redo()
{
ASSERT(m_eUndoMode == xtpCalendarUndoModeRedo);
return _Undo();
}
CString CXTPCalendarView::_GetMaxWidthFormat(CDC* pDC, CString strFormat, BOOL bMonth) const
{
if (!pDC)
{
ASSERT(FALSE);
return _T("");
}
SYSTEMTIME st;
ZeroMemory(&st, sizeof(st));
st.wDay = 20;
st.wMonth = 1;
st.wYear = (WORD)CXTPCalendarUtils::GetCurrentTime().GetYear();
int nMax = 0;
CString str;
int nCount = bMonth ? 12 : 7;
for (int i = 0; i < nCount; i++)
{
CString strResult = CXTPCalendarUtils::GetDateFormat(&st, strFormat);
int nLen = pDC->GetTextExtent(strResult).cx;
if (nMax < nLen)
{
str = strResult;
nMax = nLen;
}
if (bMonth)
st.wMonth++;
else
st.wDay++;
}
return str;
}
int CXTPCalendarView::_GetMaxWidth(CDC* pDC, CString strFormat) const
{
if (!pDC)
{
ASSERT(FALSE);
return 1;
}
const TCHAR* chFormats[] =
{
_T("yyyy"), _T("yyy"), _T("yy"), _T("y"),
_T("MMMM"), _T("MMM"),
_T("dddd"), _T("ddd"), _T("dd"), _T("d")
};
for (int i = 0; i < _countof(chFormats); i++)
{
int nPos = strFormat.Find(chFormats[i]);
if (nPos >= 0)
{
strFormat.Replace(chFormats[i], _GetMaxWidthFormat(pDC, chFormats[i], i < 2));
}
}
return pDC->GetTextExtent(strFormat).cx;
}
void CXTPCalendarView::_RemoveYearPart(CString& strFormat)
{
strFormat = CXTPCalendarUtils::RemoveFormatPart(strFormat, _T('y'));
}
void CXTPCalendarView::_ReadDefaultHeaderFormats()
{
m_strDayHeaderFormatDefaultLong = CXTPCalendarUtils::GetLocaleString(LOCALE_SLONGDATE, 81);
if (!GetCalendarControl()->m_bFullDateMode)
_RemoveYearPart(m_strDayHeaderFormatDefaultLong);
m_strDayHeaderFormatDefaultMiddle = m_strDayHeaderFormatDefaultLong;
m_strDayHeaderFormatDefaultMiddle.Replace(_T("MMMM"), _T("MMM"));
m_strDayHeaderFormatDefaultShort = m_strDayHeaderFormatDefaultMiddle;
m_strDayHeaderFormatDefaultShort.Replace(_T("dddd"), _T("ddd"));
m_strDayHeaderFormatDefaultShortest = CXTPCalendarUtils::GetLocaleString(LOCALE_SSHORTDATE, 81);
if (!GetCalendarControl()->m_bFullDateMode)
_RemoveYearPart(m_strDayHeaderFormatDefaultShortest);
}
// nLevel = 0 - Long, 1 - Middle, 2 - Short, 3 - Shortest.
CString CXTPCalendarView::_GetDayHeaderFormat(int nLevel) const
{
switch (nLevel)
{
case 0:
return m_strDayHeaderFormatLong.IsEmpty() ? m_strDayHeaderFormatDefaultLong : m_strDayHeaderFormatLong;
case 1:
return m_strDayHeaderFormatMiddle.IsEmpty() ? m_strDayHeaderFormatDefaultMiddle : m_strDayHeaderFormatMiddle;
case 2:
return m_strDayHeaderFormatShort.IsEmpty() ? m_strDayHeaderFormatDefaultShort : m_strDayHeaderFormatShort;
case 3:
return m_strDayHeaderFormatShortest.IsEmpty() ? m_strDayHeaderFormatDefaultShortest : m_strDayHeaderFormatShortest;
}
ASSERT(FALSE);
return _T("");
}
void CXTPCalendarView::CalculateHeaderFormat(CDC* pDC, int nWidth, CFont* pTextFont)
{
if (!GetCalendarControl() || !pTextFont || !pDC)
{
ASSERT(FALSE);
return;
}
_ReadDefaultHeaderFormats();
CXTPFontDC fnt(pDC, pTextFont);
int arBorder[] = {40, 35, 20, 0};
for (int i = 0; i <= 3; i++)
{
m_strHeaderFormat = _GetDayHeaderFormat(i);
int nLen = _GetMaxWidth(pDC, m_strHeaderFormat);
if (nLen < nWidth - arBorder[i])
{
return;
}
}
}
COleDateTimeSpan CXTPCalendarView::GetEventDurationMin() const
{
return COleDateTimeSpan(0.);
}
BOOL CXTPCalendarView::CanCut() const
{
return !IsEditingSubject() && HasSelectedViewEvent() ||
IsEditingSubject() && _CanSubjectEditor(ID_EDIT_CUT);
}
BOOL CXTPCalendarView::CanCopy() const
{
return !IsEditingSubject() && HasSelectedViewEvent() ||
IsEditingSubject() && _CanSubjectEditor(ID_EDIT_COPY);
}
BOOL CXTPCalendarView::CanPaste() const
{
if (!GetSelection())
{
return FALSE;
}
//- Register or get existing Clipboard Format ID -------------------------
UINT uCF_Event = ::RegisterClipboardFormat(XTPCALENDARCTRL_CF_EVENT);
BOOL bIsEventInClipboard = ::IsClipboardFormatAvailable(uCF_Event);
return !IsEditingSubject() && bIsEventInClipboard ||
IsEditingSubject() && _CanSubjectEditor(ID_EDIT_PASTE);
}
BOOL CXTPCalendarView::Cut()
{
if (IsEditingSubject() && _GetSubjectEditorWnd())
{
if (CanCut())
{
_GetSubjectEditorWnd()->SendMessage(WM_CUT);
return TRUE;
}
return FALSE;
}
//===========================================================================
CXTPCalendarViewEventsPtr ptrSelViews = GetSelectedEvents();
if (!ptrSelViews || !ptrSelViews->GetCount())
{
return FALSE;
}
if (OnBeforeEditOperationNotify(xtpCalendarEO_Cut, ptrSelViews))
{
return FALSE;
}
//------------------------------------------------------------------------
DWORD dwCopyFlags = xtpCalendarCopyFlagCutMask;
COleDataSource* pData = _CopySelectedEvents(dwCopyFlags);
if (!pData)
{
return FALSE;
}
pData->SetClipboard();
int nCount = ptrSelViews->GetCount();
for (int i = 0; i < nCount; i++)
{
CXTPCalendarViewEvent* pViewEvent = ptrSelViews->GetAt(i, FALSE);
CXTPCalendarEvent* pEvent = pViewEvent ? pViewEvent->GetEvent() : NULL;
VERIFY( XTP_SAFE_GET2(pEvent, GetDataProvider(), DeleteEvent(pEvent), FALSE) );
}
XTP_SAFE_CALL1(GetCalendarControl(), Populate());
return TRUE;
}
BOOL CXTPCalendarView::Copy()
{
if (IsEditingSubject() && _GetSubjectEditorWnd())
{
if (CanCopy())
{
_GetSubjectEditorWnd()->SendMessage(WM_COPY);
return TRUE;
}
return FALSE;
}
CXTPCalendarViewEventsPtr ptrSelViews = GetSelectedEvents();
if (!ptrSelViews || !ptrSelViews->GetCount())
return FALSE;
if (OnBeforeEditOperationNotify(xtpCalendarEO_Copy, ptrSelViews))
return FALSE;
COleDataSource* pData = _CopySelectedEvents();
if (!pData)
return FALSE;
pData->SetClipboard();
return TRUE;
}
BOOL CXTPCalendarView::Paste()
{
if (IsEditingSubject() && _GetSubjectEditorWnd())
{
if (CanPaste())
{
_GetSubjectEditorWnd()->SendMessage(WM_PASTE);
return TRUE;
}
return FALSE;
}
COleDateTime dtSelBegin, dtSelEnd;
COleDateTimeSpan spSelectionResolution;
if (!GetSelection(&dtSelBegin, &dtSelEnd, NULL, NULL, &spSelectionResolution))
{
return FALSE;
}
dtSelBegin = min(dtSelBegin, dtSelEnd);
// Attach a COleDataObject to the clipboard and paste the data
COleDataObject objData;
if (!objData.AttachClipboard())
{
return FALSE;
}
DWORD dwCopyFlags = 0;
CXTPCalendarEventsPtr ptrEventsFromCB = _ReadEventsFromClipboard(&objData, &dwCopyFlags);
if (!ptrEventsFromCB)
return FALSE;
if (!GetCalendarControl())
return FALSE;
CXTPAutoResetValue<BOOL> autoSet_UpdateCtrlNf(GetCalendarControl()->m_bUpdateWhenEventChangedNotify);
autoSet_UpdateCtrlNf = FALSE;
COleDateTimeSpan spStartShift;
int nCount = ptrEventsFromCB->GetCount();
for (int i = 0; i < nCount; i++)
{
BOOL bUseChangeEvent = FALSE;
CXTPCalendarEvent* pNewEvent = ptrEventsFromCB->GetAt(i, FALSE);
if (!pNewEvent)
{
ASSERT(FALSE);
continue;
}
int nRState = pNewEvent->GetRecurrenceState();
if (nRState == xtpCalendarRecurrenceMaster)
{
ASSERT(FALSE); // WARNING. Master event in the clipboard - ???
VERIFY(pNewEvent->RemoveRecurrence());
}
if (nRState == xtpCalendarRecurrenceOccurrence &&
dwCopyFlags & xtpCalendarCopyFlagROccurrence2RException)
{
VERIFY(pNewEvent->MakeAsRException());
bUseChangeEvent = TRUE;
}
else
{
VERIFY(pNewEvent->RemoveRecurrence());
}
// Update recurrence state
nRState = pNewEvent->GetRecurrenceState();
if (nRState == xtpCalendarRecurrenceException &&
dwCopyFlags & xtpCalendarCopyFlagKeepRException)
{
CXTPCalendarRecurrencePatternPtr ptrPattern = pNewEvent->GetRecurrencePattern();
bUseChangeEvent = ptrPattern != NULL;
}
if (!bUseChangeEvent && nRState == xtpCalendarRecurrenceException)
{
VERIFY( pNewEvent->RemoveRecurrence() );
}
COleDateTime dtEventStart = pNewEvent->GetStartTime();
if (i == 0)
{
spStartShift = dtSelBegin - dtEventStart;
spStartShift += ((double)spStartShift < 0 ? -1 : 1) * XTP_HALF_SECOND;
double dCells = (double)spStartShift / (double)spSelectionResolution;
int nCells = (int)dCells; //+ (dCells >= 0 ? 1 : 0);
double dCellDrobTime = fabs(dCells - (DWORD)dCells)*(double)spSelectionResolution;
double dCellDrobTimeLimit = XTP_HALF_SECOND*2*10;
if (dCells >= 0 && dCellDrobTime > dCellDrobTimeLimit)
{
nCells++;
}
spStartShift = (double)spSelectionResolution * (double)nCells;
}
dtEventStart += spStartShift;
pNewEvent->MoveEvent(dtEventStart);
if (OnBeforePasteNotify(pNewEvent, bUseChangeEvent))
continue;
if (bUseChangeEvent)
{
VERIFY( XTP_SAFE_GET2(pNewEvent, GetDataProvider(), ChangeEvent(pNewEvent), FALSE) );
}
else
{
VERIFY( XTP_SAFE_GET2(pNewEvent, GetDataProvider(), AddEvent(pNewEvent), FALSE) );
}
}
if (dwCopyFlags & xtpCalendarCopyFlagClearCBAfterPaste)
{
if (::OpenClipboard(NULL))
{
::EmptyClipboard();
::CloseClipboard();
}
}
XTP_SAFE_CALL1(GetCalendarControl(), Populate());
return TRUE;
}
CXTPCalendarEventsPtr CXTPCalendarView::_ReadEventsFromClipboard(COleDataObject* pData, DWORD* pdwCopyFlags)
{
//- Register or get existing Clipboard Format ID -------------------------
CLIPFORMAT uCF_Event = (CLIPFORMAT)::RegisterClipboardFormat(XTPCALENDARCTRL_CF_EVENT);
ASSERT(pData);
if (!pData || !pData->IsDataAvailable(uCF_Event))
{
return NULL;
}
CXTPCalendarEventsPtr ptrEvents = new CXTPCalendarEvents();
if (!ptrEvents)
{
return NULL;
}
const int cErrTextSize = 1024;
TCHAR szErrText[cErrTextSize + 1];
try
{
HGLOBAL hData = pData->GetGlobalData(uCF_Event);
if (!hData)
{
return NULL;
}
CSharedFile fileSahred;
fileSahred.SetHandle(hData, FALSE);
CArchive ar(&fileSahred, CArchive::load);
CXTPPropExchangeArchive px(ar);
long nSchema = 0;
DWORD dwCopyFlags = 0;
PX_Long(&px, _T("Version"), (long&)nSchema);
px.ExchangeLocale();
PX_DWord(&px, _T("CopyFlags"), (DWORD&)dwCopyFlags);
if (nSchema != XTP_CLIPBOARD_EVENTS_DATA_VER)
{
ASSERT(FALSE);
return NULL;
}
CXTPPropExchangeSection sec(px.GetSection(_T("Events")));
CXTPPropExchangeEnumeratorPtr pEnumerator(sec->GetEnumerator(_T("Event")));
POSITION pos = pEnumerator->GetPosition();
UINT uScheduleID = 0;
CXTPCalendarData* pDPsel = _GetDataProviderBySelection(&uScheduleID);
while (pos)
{
CXTPPropExchangeSection secEvent(pEnumerator->GetNext(pos));
CXTPCalendarData* pDPevent = NULL;
//-- get data provider --------------------
CString strDataProvider;
PX_String(&secEvent, _T("DataProvider_ConnectionString"), strDataProvider, _T(""));
if (!strDataProvider.IsEmpty())
pDPevent = _GetDataProviderByConnStr(strDataProvider);
CXTPCalendarData* pDataProvider = pDPevent ? pDPevent : pDPsel;
ASSERT(pDataProvider);
//-- create event and read its data ---------
CXTPCalendarEventPtr ptrEvent = pDataProvider ? pDataProvider->CreateNewEvent() : NULL;
if (!ptrEvent)
return NULL;
ptrEvent->DoPropExchange(&secEvent);
if (!pDPevent
|| !_IsScheduleVisible(pDPevent, ptrEvent->GetScheduleID()))
ptrEvent->SetScheduleID(uScheduleID);
ptrEvents->Add(ptrEvent, TRUE);
}
ar.Close(); // detach from file
if (pdwCopyFlags)
*pdwCopyFlags = dwCopyFlags;
return ptrEvents;
}
catch(CArchiveException* pE)
{
if (pE->GetErrorMessage(szErrText, cErrTextSize))
{
TRACE(_T("EXCEPTION: CXTPCalendarView::_ReadEventsFromClipboard() - %s\n"), szErrText);
}
pE->Delete();
}
catch(CFileException* pE)
{
if (pE->GetErrorMessage(szErrText, cErrTextSize))
{
TRACE(_T("EXCEPTION: CXTPCalendarView::_ReadEventsFromClipboard() - %s\n"), szErrText);
}
pE->Delete();
}
catch(...)
{
TRACE(_T("EXCEPTION: CXTPCalendarView::_ReadEventsFromClipboard() - Unhandled Exception!\n"));
}
ASSERT(FALSE);
return NULL;
}
COleDataSource* CXTPCalendarView::_CopySelectedEvents(DWORD dwCopyFlags)
{
CXTPCalendarViewEventsPtr ptrSelViews = GetSelectedEvents();
if (!ptrSelViews || !ptrSelViews->GetCount())
return NULL;
const int cErrTextSize = 1024;
TCHAR szErrText[cErrTextSize + 1];
try
{
CSharedFile fileSahred(GMEM_MOVEABLE | GMEM_DDESHARE | GMEM_ZEROINIT);
CArchive ar(&fileSahred, CArchive::store);
CXTPPropExchangeArchive px(ar);
long nSchema = XTP_CLIPBOARD_EVENTS_DATA_VER;
PX_Long(&px, _T("Version"), (long&)nSchema);
px.ExchangeLocale();
PX_DWord(&px, _T("CopyFlags"), (DWORD&)dwCopyFlags);
int nCount = ptrSelViews->GetCount();
CXTPPropExchangeSection sec(px.GetSection(_T("Events")));
CXTPPropExchangeEnumeratorPtr pEnumerator(sec->GetEnumerator(_T("Event")));
POSITION posEnum = pEnumerator->GetPosition((DWORD)nCount);
for (int i = 0; i < nCount; i++)
{
CXTPCalendarViewEvent* pViewEvent = ptrSelViews->GetAt(i, FALSE);
CXTPCalendarEvent* pEvent = pViewEvent->GetEvent();
if (!pEvent)
{
ASSERT(FALSE);
continue;
}
CXTPPropExchangeSection secEvent(pEnumerator->GetNext(posEnum));
CString strDataProvider = XTP_SAFE_GET2(pEvent, GetDataProvider(), GetConnectionString(), _T(""));
PX_String(&secEvent, _T("DataProvider_ConnectionString"), strDataProvider);
pEvent->DoPropExchange(&secEvent);
}
ar.Close(); // perform Flush() and detach from file
//- Prepare Global data ----------------------------------------------
DWORD dwDataSize = (DWORD)fileSahred.GetLength();
HGLOBAL hData = fileSahred.Detach();
if (!hData)
{
ASSERT(FALSE);
return NULL;
}
hData = ::GlobalReAlloc(hData, dwDataSize, GMEM_MOVEABLE | GMEM_DDESHARE | GMEM_ZEROINIT);
if (!hData)
{
ASSERT(FALSE);
return NULL;
}
//- Register Clipboard Format ----------------------------------------
CLIPFORMAT uCF_Event = (CLIPFORMAT)::RegisterClipboardFormat(XTPCALENDARCTRL_CF_EVENT);
// Cache data
COleDataSource* pSource = new COleDataSource();
if (pSource)
{
pSource->CacheGlobalData(uCF_Event, hData);
}
return pSource;
}
catch(CArchiveException* pE)
{
if (pE->GetErrorMessage(szErrText, cErrTextSize))
{
TRACE(_T("EXCEPTION: CXTPCalendarView::_CopySelectedEvents() - %s\n"), szErrText);
}
pE->Delete();
}
catch(CFileException* pE)
{
if (pE->GetErrorMessage(szErrText, cErrTextSize))
{
TRACE(_T("EXCEPTION: CXTPCalendarView::_CopySelectedEvents() - %s\n"), szErrText);
}
pE->Delete();
}
catch(...)
{
TRACE(_T("EXCEPTION: CXTPCalendarView::_CopySelectedEvents() - Unhandled Exception!\n"));
}
ASSERT(FALSE);
return NULL;
}
////////////////////////////////////////////////////////////////////////////
CXTPCalendarPaintManager* CXTPCalendarView::GetPaintManager() const
{
ASSERT(m_pControl);
return m_pControl ? m_pControl->GetPaintManager() : NULL;
}
CXTPCalendarTheme* CXTPCalendarView::GetTheme() const
{
return m_pControl ? m_pControl->GetTheme() : NULL;
}
void CXTPCalendarView::SendNotification(XTP_NOTIFY_CODE EventCode, WPARAM wParam , LPARAM lParam)
{
if (m_pControl)
m_pControl->SendNotification(EventCode, wParam, lParam);
}
BOOL CXTPCalendarView::IsEditOperationDisabledNotify(XTPCalendarEditOperation eOperation, CXTPCalendarViewEvent* pEventView) const
{
return _EditOperationNotify(XTP_NC_CALENDAR_IS_EVENT_EDIT_OPERATION_DISABLED,
eOperation, pEventView);
}
BOOL CXTPCalendarView::OnBeforeEditOperationNotify(XTPCalendarEditOperation eOperation, CXTPCalendarViewEvent* pEventView)
{
if (IsEditOperationDisabledNotify(eOperation, pEventView))
return TRUE;
return _EditOperationNotify(XTP_NC_CALENDAR_BEFORE_EVENT_EDIT_OPERATION,
eOperation, pEventView);
}
BOOL CXTPCalendarView::OnBeforeEditOperationNotify(XTPCalendarEditOperation eOperation, CXTPCalendarViewEvents* pEventViews)
{
if (_EditOperationNotify(XTP_NC_CALENDAR_IS_EVENT_EDIT_OPERATION_DISABLED,
eOperation, NULL, pEventViews))
return TRUE;
return _EditOperationNotify(XTP_NC_CALENDAR_BEFORE_EVENT_EDIT_OPERATION,
eOperation, NULL, pEventViews);
}
BOOL CXTPCalendarView::OnBeforePasteNotify(CXTPCalendarEvent* pEvent, BOOL bPasteWillChangeExistingEvent)
{
XTP_EVENT_PASTE_OPERATION_PARAMS opPasteParams;
::ZeroMemory(&opPasteParams, sizeof(opPasteParams));
opPasteParams.eOperation = xtpCalendarEO_Paste;
opPasteParams.pEvent = pEvent;
opPasteParams.bPasteWillChangeExistingEvent = bPasteWillChangeExistingEvent;
BOOL bDisabledHandled = FALSE;
if (m_pControl)
{
m_pControl->SendNotification(XTP_NC_CALENDAR_IS_EVENT_EDIT_OPERATION_DISABLED,
(WPARAM)&opPasteParams, (LPARAM)&bDisabledHandled);
}
if (bDisabledHandled)
return TRUE;
if (m_pControl)
{
m_pControl->SendNotification(XTP_NC_CALENDAR_BEFORE_EVENT_EDIT_OPERATION,
(WPARAM)&opPasteParams, (LPARAM)&bDisabledHandled);
}
return bDisabledHandled;
}
BOOL CXTPCalendarView::OnInPlaceCreateEvent(LPCTSTR pcszInitialSubject)
{
XTP_EVENT_IN_PLACE_CREATE_EVENT_OPERATION_PARAMS opCrParams;
::ZeroMemory(&opCrParams, sizeof(opCrParams));
opCrParams.eOperation = xtpCalendarEO_InPlaceCreateEvent;
opCrParams.pcszInitialSubject = pcszInitialSubject;
BOOL bDisabledHandled = FALSE;
if (m_pControl)
{
m_pControl->SendNotification(XTP_NC_CALENDAR_IS_EVENT_EDIT_OPERATION_DISABLED,
(WPARAM)&opCrParams, (LPARAM)&bDisabledHandled);
}
if (bDisabledHandled)
return TRUE;
if (m_pControl)
{
m_pControl->SendNotification(XTP_NC_CALENDAR_BEFORE_EVENT_EDIT_OPERATION,
(WPARAM)&opCrParams, (LPARAM)&bDisabledHandled);
}
return bDisabledHandled;
}
CXTPCalendarOptions* CXTPCalendarView::GetCalendarOptions() const
{
return this && m_pControl ? m_pControl->GetCalendarOptions() : NULL;
}
BOOL CXTPCalendarView::_EditOperationNotify(XTP_NOTIFY_CODE ncEvent,
XTPCalendarEditOperation eOperation,
CXTPCalendarViewEvent* pEventView,
CXTPCalendarViewEvents* pEventViews) const
{
ASSERT(pEventView || pEventViews && !(pEventView && pEventViews));
XTP_EVENT_EDIT_OPERATION_PARAMS opParams;
::ZeroMemory(&opParams, sizeof(opParams));
CXTPCalendarViewEvents arEvents;
arEvents.Add(pEventView, TRUE);
opParams.eOperation = eOperation;
opParams.pEventViews = pEventView ? &arEvents : pEventViews;
BOOL bDisabledHandled = FALSE;
if (m_pControl)
{
m_pControl->SendNotification(ncEvent, (WPARAM)&opParams, (LPARAM)&bDisabledHandled);
}
return bDisabledHandled;
}
XTPEnumCalendarUpdateResult CXTPCalendarView::OnEventChanged_InDataProvider(
XTP_NOTIFY_CODE nfCode, CXTPCalendarEvent* pEvent)
{
if (!pEvent)
return xtpCalendar_Skip;
if (nfCode != XTP_NC_CALENDAREVENTWASADDED &&
nfCode != XTP_NC_CALENDAREVENTWASDELETED &&
nfCode != XTP_NC_CALENDAREVENTWASCHANGED)
return xtpCalendar_Skip;
int nDaysCount = GetViewDayCount();
COleDateTime dtFirstDay = nDaysCount ? XTP_SAFE_GET1(GetViewDay_(0), GetDayDate(), (DATE)0) : (DATE)0;
COleDateTime dtLastDay = nDaysCount ? XTP_SAFE_GET1(GetViewDay_(nDaysCount - 1), GetDayDate(), (DATE)0) : (DATE)0;
if (nfCode == XTP_NC_CALENDAREVENTWASADDED ||
nfCode == XTP_NC_CALENDAREVENTWASDELETED)
{
if (GetDateTimeDay(pEvent->GetStartTime(), pEvent->IsAllDayEvent()) > dtLastDay ||
GetDateTimeDay(pEvent->GetEndTime(), pEvent->IsAllDayEvent()) < dtFirstDay)
return xtpCalendar_Skip;
return xtpCalendar_Populate;
}
return xtpCalendar_Populate;
// *****
// An Idea how changing event processing can be optimized
// from xtpCalendar_Populate to xtpCalendar_Redraw or even xtpCalendar_Skip.
//
// int nRState_new = pEvent->GetRecurrenceState();
// if (nRState_new == xtpCalendarRecurrenceMaster) {
// return xtpCalendar_Populate;
// }
//
// //-----------------------------------------------------------------------
// BOOL bUpdateEvent = FALSE;
// int nDays = GetViewDayCount();
// for (int nDay = 0; nDay < nDays; nDay++)
// {
// CXTPCalendarViewDay* pDay = GetViewDay_(nDay);
// ASSERT(pDay);
// if (!pDay)
// continue;
//
//
// int nEvents = pDay->GetViewEventsCount();
// for (int nEvent = 0; nEvent < nEvents; nEvent++)
// {
// CXTPCalendarViewEvent* pEventView = pDay->GetViewEvent_(nEvent);
// if (!pEventView && !pEventView->GetEvent())
// {
// ASSERT(FALSE);
// continue;
// }
// CXTPCalendarEvent* pEvent_I = pEventView->GetEvent();
// if (pEvent_I->GetEventID() == dwEventID)
// {
// if (!bUpdateEvent)
// {
// if (pEvent_I->IsEqualStartEnd(pEvent))
// bUpdateEvent = TRUE;
// else
// return xtpCalendar_Populate;
// }
//
// if (bUpdateEvent)
// {
// int nRState_I = pEvent_I->GetRecurrenceState();
// //int nRState_new = pEvent->GetRecurrenceState();
//
// if (nRState_I == xtpCalendarRecurrenceOccurrence)
// pEvent_I->SetRecurrenceState_ExceptionOccurrence(xtpCalendarRecurrenceException);
//
// pEvent_I->Update(pEvent);
//
// if (nRState_new == xtpCalendarRecurrenceOccurrence ||
// nRState_new == xtpCalendarRecurrenceException)
// {
// ASSERT(nRState_I == xtpCalendarRecurrenceOccurrence ||
// nRState_I == xtpCalendarRecurrenceException);
//
// pEvent_I->SetRecurrenceState_ExceptionOccurrence((XTPCalendarEventRecurrenceState)nRState_new);
// }
// }
// }
// }
//
// }
//
// //-----------------------------------------------------------------------
// if (!bUpdateEvent &&
// !(CXTPCalendarUtils::ResetTime(pEvent->GetStartTime()) > dtLastDay ||
// CXTPCalendarUtils::ResetTime(pEvent->GetEndTime()) < dtFirstDay)
// )
// {
// return xtpCalendar_Populate;
// }
// return bUpdateEvent ? xtpCalendar_Redraw : xtpCalendar_Skip;
}
CXTPCalendarData* CXTPCalendarView::_GetDataProviderBySelection(UINT* puScheduleID)
{
COleDateTime dtSelBegin;
int nGroup = 0;
if (!GetSelection(&dtSelBegin, NULL, NULL, &nGroup))
return NULL;
CXTPCalendarViewDay* pViewDay = _GetViewDay(dtSelBegin);
if (!pViewDay)
return NULL;
CXTPCalendarData* pData = NULL;
CXTPCalendarViewGroup* pViewGroup = NULL;
if (pViewDay && nGroup < pViewDay->GetViewGroupsCount())
{
pViewGroup = pViewDay->GetViewGroup_(nGroup);
if (pViewGroup)
{
pData = pViewGroup->GetDataProvider();
if (puScheduleID)
*puScheduleID = pViewGroup->GetScheduleID();
}
}
return pData;
}
CXTPCalendarData* CXTPCalendarView::_GetDataProviderByConnStr(LPCTSTR pcszConnStr, BOOL bCompareNoCase)
{
CXTPCalendarViewDay* pViewDay = GetViewDay_(0);
COleDateTime dtSelBegin;
if (GetSelection(&dtSelBegin))
pViewDay = _GetViewDay(dtSelBegin);
if (!pViewDay)
return NULL;
int nGCount = pViewDay->GetViewGroupsCount();
for (int g = 0; g < nGCount; g++)
{
CXTPCalendarViewGroup* pViewGroup = pViewDay->GetViewGroup_(g);
if (pViewGroup)
{
CXTPCalendarData* pData = pViewGroup->GetDataProvider();
if (pData)
{
CString strConn_i = pData->GetConnectionString();
int nCmp = bCompareNoCase ? strConn_i.CompareNoCase(pcszConnStr) : strConn_i.Compare(pcszConnStr);
if (nCmp == 0)
return pData;
}
}
}
return NULL;
}
BOOL CXTPCalendarView::_IsScheduleVisible(CXTPCalendarData* pDataProvider, UINT uScheduleID)
{
CXTPCalendarViewDay* pViewDay = GetViewDay_(0);
COleDateTime dtSelBegin;
if (GetSelection(&dtSelBegin))
pViewDay = _GetViewDay(dtSelBegin);
if (!pViewDay)
return FALSE;
int nGCount = pViewDay->GetViewGroupsCount();
for (int g = 0; g < nGCount; g++)
{
CXTPCalendarViewGroup* pViewGroup = pViewDay->GetViewGroup_(g);
CXTPCalendarData* pData = pViewGroup ? pViewGroup->GetDataProvider() : NULL;
if (pData && pData == pDataProvider)
{
int nRCCount = XTP_SAFE_GET2(pViewGroup, GetResources(), GetCount(), 0);
for (int i = 0; i < nRCCount; i++)
{
if (XTP_SAFE_GET3(pViewGroup, GetResources(), GetAt(i), ExistsScheduleID(uScheduleID), FALSE))
return TRUE;
}
}
}
return FALSE;
}
CXTPCalendarWMHandler* CXTPCalendarView::GetChildHandlerAt(int nIndex) const
{
CXTPCalendarWMHandler* pDay = GetViewDay_(nIndex);
if (!pDay)
return NULL;
ASSERT_KINDOF(CXTPCalendarWMHandler, pDay);
return pDay;
}
CXTPCalendarResources* CXTPCalendarView::GetResources() const
{
ASSERT(this);
if (m_pResources)
return m_pResources;
return GetCalendarControl() ? GetCalendarControl()->GetResources() : NULL;
}
void CXTPCalendarView::SetResources(CXTPCalendarResources* pResources)
{
BOOL bChanged = TRUE;
if (!pResources)
{
bChanged = m_pResources != NULL;
CMDTARGET_RELEASE(m_pResources);
}
else
{
if (!m_pResources)
m_pResources = new CXTPCalendarResources();
if (!m_pResources)
return;
// copy data to allow using self as input parameter
CXTPCalendarResources arRes;
arRes.Append(pResources);
m_pResources->RemoveAll();
m_pResources->Append(&arRes);
}
if (bChanged)
SendNotification(XTP_NC_CALENDAR_RESOURCES_WHERE_CHANGED, 1, (LPARAM)this);
}
BOOL CXTPCalendarView::IsTodayVisible() const
{
COleDateTime dtToday = CXTPCalendarUtils::GetCurrentTime();
dtToday = GetDateTimeDay(dtToday, FALSE);
int nCount = GetViewDayCount();
for (int i = 0; i < nCount; i++)
{
COleDateTime dtDay = GetViewDayDate(i);
if (CXTPCalendarUtils::IsEqual(dtDay, dtToday))
return TRUE;
}
return FALSE;
}
void CXTPCalendarView::EmptyUndoBuffer()
{
m_pUndoBuffer->RemoveAll();
m_eUndoMode = xtpCalendarUndoModeUnknown;
}
BOOL CXTPCalendarView::HitTest(CPoint pt, XTP_CALENDAR_HITTESTINFO* pHitTest) const
{
return HitTestEx(pt, pHitTest);
}
BOOL CXTPCalendarView::HitTestEx(CPoint pt, XTP_CALENDAR_HITTESTINFO* pHitTest) const
{
if (!pHitTest)
{
ASSERT(FALSE);
return FALSE;
}
int nCount = GetViewDayCount();
for (int i = 0; i < nCount; i++)
{
CXTPCalendarViewDay* pViewDay = GetViewDay_(i);
ASSERT(pViewDay);
if (pViewDay && pViewDay->HitTestEx(pt, pHitTest))
{
ASSERT(!pHitTest->pViewDay || pHitTest->pViewDay == pViewDay);
pHitTest->nDay = i;
pHitTest->pViewDay = pViewDay;
return TRUE;
}
}
return FALSE;
}
/////////////////////////////////////////////////////////////////////////////
CXTPCalendarView::CSelectionChanged_ContextData::CSelectionChanged_ContextData()
{
m_nLockCount = 0;
m_nLockCount_Day = 0;
m_nLockCount_Event = 0;
m_bRequest_Day = FALSE;
m_bRequest_Event = FALSE;
}
/////////////////////////////////////////////////////////////////////////////
// class CSelectionChangedContext
//
CXTPCalendarView::CSelectionChangedContext::CSelectionChangedContext(CXTPCalendarView* pView, int eSelType)
{
if (!pView)
{
ASSERT(FALSE);
return;
}
m_pView = pView;
m_eSelType = eSelType;
m_pView->m_cntSelChanged.m_nLockCount += eSelType == xtpCalendarSelectionUnknown ? 1 : 0;
m_pView->m_cntSelChanged.m_nLockCount_Day += eSelType == xtpCalendarSelectionDays ? 1 : 0;
m_pView->m_cntSelChanged.m_nLockCount_Event += eSelType == xtpCalendarSelectionEvents ? 1 : 0;
}
CXTPCalendarView::CSelectionChangedContext::~CSelectionChangedContext()
{
if (!m_pView)
{
ASSERT(FALSE);
return;
}
if (m_eSelType == xtpCalendarSelectionUnknown)
m_pView->m_cntSelChanged.m_nLockCount--;
if (m_eSelType == xtpCalendarSelectionDays)
{
m_pView->m_cntSelChanged.m_nLockCount_Day--;
if (m_pView->m_cntSelChanged.m_nLockCount_Day == 0)
m_pView->m_cntSelChanged.m_bRequest_Day = TRUE;
}
if (m_eSelType == xtpCalendarSelectionEvents)
{
m_pView->m_cntSelChanged.m_nLockCount_Event--;
if (m_pView->m_cntSelChanged.m_nLockCount_Event == 0)
m_pView->m_cntSelChanged.m_bRequest_Event = TRUE;
}
if (m_pView->m_cntSelChanged.m_nLockCount == 0 && m_pView->m_cntSelChanged.m_bRequest_Day)
{
m_pView->m_cntSelChanged.m_bRequest_Day = FALSE;
m_pView->SendNotification(XTP_NC_CALENDAR_SELECTION_CHANGED, (WPARAM)xtpCalendarSelectionDays);
}
if (m_pView->m_cntSelChanged.m_nLockCount == 0 && m_pView->m_cntSelChanged.m_bRequest_Event)
{
m_pView->m_cntSelChanged.m_bRequest_Event = FALSE;
m_pView->SendNotification(XTP_NC_CALENDAR_SELECTION_CHANGED, (WPARAM)xtpCalendarSelectionEvents);
}
}
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
// CXTPCalendarWMHandler
CXTPCalendarWMHandler::CXTPCalendarWMHandler()
{
}
int CXTPCalendarWMHandler::GetChildHandlersCount() const
{
return 0;
}
CXTPCalendarWMHandler* CXTPCalendarWMHandler::GetChildHandlerAt(int nIndex) const
{
UNREFERENCED_PARAMETER(nIndex);
return NULL;
}
BOOL CXTPCalendarWMHandler::OnLButtonDown(UINT nFlags, CPoint point)
{
BOOL bHandled = FALSE;
int nCount = GetChildHandlersCount();
for (int i = 0; i < nCount; i++)
{
CXTPCalendarWMHandler* pChild = GetChildHandlerAt(i);
if (pChild && pChild->OnLButtonDown(nFlags, point))
{
bHandled = TRUE;
break;
}
}
return bHandled;
}
BOOL CXTPCalendarWMHandler::OnLButtonUp(UINT nFlags, CPoint point)
{
BOOL bHandled = FALSE;
int nCount = GetChildHandlersCount();
for (int i = 0; i < nCount; i++)
{
CXTPCalendarWMHandler* pChild = GetChildHandlerAt(i);
if (pChild && pChild->OnLButtonUp(nFlags, point))
{
bHandled = TRUE;
break;
}
}
return bHandled;
}
BOOL CXTPCalendarWMHandler::OnLButtonDblClk(UINT nFlags, CPoint point)
{
BOOL bHandled = FALSE;
int nCount = GetChildHandlersCount();
for (int i = 0; i < nCount; i++)
{
CXTPCalendarWMHandler* pChild = GetChildHandlerAt(i);
if (pChild && pChild->OnLButtonDblClk(nFlags, point))
{
bHandled = TRUE;
break;
}
}
return bHandled;
}
void CXTPCalendarWMHandler::OnMouseMove(UINT nFlags, CPoint point)
{
int nCount = GetChildHandlersCount();
for (int i = 0; i < nCount; i++)
{
CXTPCalendarWMHandler* pChild = GetChildHandlerAt(i);
if (pChild)
pChild->OnMouseMove(nFlags, point);
}
}
void CXTPCalendarWMHandler::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags)
{
int nCount = GetChildHandlersCount();
for (int i = 0; i < nCount; i++)
{
CXTPCalendarWMHandler* pChild = GetChildHandlerAt(i);
if (pChild)
pChild->OnChar(nChar, nRepCnt, nFlags);
}
}
void CXTPCalendarWMHandler::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
{
int nCount = GetChildHandlersCount();
for (int i = 0; i < nCount; i++)
{
CXTPCalendarWMHandler* pChild = GetChildHandlerAt(i);
if (pChild)
pChild->OnKeyDown(nChar, nRepCnt, nFlags);
}
}
void CXTPCalendarWMHandler::OnKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags)
{
int nCount = GetChildHandlersCount();
for (int i = 0; i < nCount; i++)
{
CXTPCalendarWMHandler* pChild = GetChildHandlerAt(i);
if (pChild)
pChild->OnKeyUp(nChar, nRepCnt, nFlags);
}
}
BOOL CXTPCalendarWMHandler::OnSysKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
{
BOOL bHandled = FALSE;
int nCount = GetChildHandlersCount();
for (int i = 0; i < nCount; i++)
{
CXTPCalendarWMHandler* pChild = GetChildHandlerAt(i);
if (pChild && pChild->OnSysKeyDown(nChar, nRepCnt, nFlags))
{
bHandled = TRUE;
break;
}
}
return bHandled;
}
BOOL CXTPCalendarWMHandler::OnTimer(UINT_PTR uTimerID)
{
int nCount = GetChildHandlersCount();
for (int i = 0; i < nCount; i++)
{
CXTPCalendarWMHandler* pChild = GetChildHandlerAt(i);
if (pChild && pChild->OnTimer(uTimerID))
return TRUE;
}
return FALSE;
}
BOOL CXTPCalendarWMHandler::OnWndMsg(UINT message, WPARAM wParam, LPARAM lParam, LRESULT* pResult)
{
ASSERT(NULL != pResult);
BOOL bHandled = FALSE;
const int nCount = GetChildHandlersCount();
for (int i = 0; i < nCount; i++)
{
CXTPCalendarWMHandler* pChild = GetChildHandlerAt(i);
if (NULL != pChild && pChild->OnWndMsg(message, wParam, lParam, pResult))
{
bHandled = TRUE;
break;
}
}
return bHandled;
}
void CXTPCalendarWMHandler::OnPostAdjustLayout()
{
int nCount = GetChildHandlersCount();
for (int i = 0; i < nCount; i++)
{
CXTPCalendarWMHandler* pChild = GetChildHandlerAt(i);
if (pChild)
pChild->OnPostAdjustLayout();
}
}
void CXTPCalendarWMHandler::OnFinalRelease()
{
OnBeforeDestroy();
CCmdTarget::OnFinalRelease();
}
void CXTPCalendarWMHandler::OnBeforeDestroy()
{
int nCount = GetChildHandlersCount();
for (int i = 0; i < nCount; i++)
{
CXTPCalendarWMHandler* pChild = GetChildHandlerAt(i);
if (pChild)
pChild->OnBeforeDestroy();
}
}