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