void CBCGPPlannerViewMonth::AdjustAppointments ()
{
	XBCGPAppointmentArray& arQueryApps = GetQueryedAppointments ();
	XBCGPAppointmentArray& arDragApps = GetDragedAppointments ();

	const int nDays = GetViewDuration ();

	if ((arQueryApps.GetSize () == 0 && arDragApps.GetSize () == 0) || 
		m_ViewRects.GetSize () != nDays)
	{
		ClearVisibleUpDownIcons ();		
		return;
	}

	BOOL bDragDrop        = IsDragDrop ();
	DROPEFFECT dragEffect = GetDragEffect ();
	BOOL bDragMatch       = IsCaptureMatched ();

	bDragDrop = !bDragDrop || 
		(bDragDrop && ((dragEffect & DROPEFFECT_COPY) == DROPEFFECT_COPY && bDragMatch) || 
		!bDragMatch);
	bDragDrop = bDragDrop && arDragApps.GetSize ();
	
	int nApp = 0;

	for (nApp = 0; nApp < 2; nApp++)
	{
		if (!bDragDrop && nApp == 0)
		{
			continue;
		}

		XBCGPAppointmentArray& arApps = nApp == 0 ? arDragApps : arQueryApps;

		for (int i = 0; i < arApps.GetSize (); i++)
		{
			CBCGPAppointment* pApp = arApps[i];
			ASSERT_VALID (pApp);

			pApp->ResetDraw ();
		}
	}

	COleDateTime date (m_DateStart);

	COleDateTimeSpan spanDay (1, 0, 0, 0);
	const int delta = m_nRowHeight + 2;

	XBCGPAppointmentArray arAllOrMulti;

	for (nApp = 0; nApp < 2; nApp++)
	{
		if (!bDragDrop && nApp == 1)
		{
			continue;
		}

		XBCGPAppointmentArray& arApps = nApp == 1 ? arDragApps : arQueryApps;

		for (int i = 0; i < arApps.GetSize (); i++)
		{
			CBCGPAppointment* pApp = arApps[i];
			ASSERT_VALID (pApp);

			if (pApp->IsAllDay () || pApp->IsMultiDay ())
			{
				arAllOrMulti.Add (pApp);
			}
		}
	}

	if (arAllOrMulti.GetSize () > 0)
	{
		SortAppointments (arAllOrMulti, (int) arAllOrMulti.GetSize ());
	}

	for (int nDay = 0; nDay < nDays; nDay ++)
	{
		CRect rect (m_ViewRects [nDay]);
		rect.top += m_nRowHeight + 1;
		rect.DeflateRect (1, 0);

		BOOL bTopEq    = TRUE;
		BOOL bBottomEq = TRUE;
		
		if (nDay > 0)
		{
			bTopEq    = m_ViewRects [nDay].top == m_ViewRects [nDay - 1].top;
			bBottomEq = m_ViewRects [nDay].bottom == m_ViewRects [nDay - 1].bottom;
		}

		CList<int, int> lsItems;

		// first draw all days or multi days
		for (int n = 0; n < 2; n++)
		{
			for (nApp = 0; nApp < 2; nApp++)
			{
				if (n == 0 && nApp == 1)
				{
					continue;
				}

				if (!bDragDrop)
				{
					if(n == 1 && nApp == 0)
					{
						continue;
					}
				}

				XBCGPAppointmentArray& arApps = 
					n == 0
					? arAllOrMulti
					: (nApp == 0 ? arDragApps : arQueryApps);

				for (int i = 0; i < arApps.GetSize (); i++)
				{
					CBCGPAppointment* pApp = arApps[i];
					ASSERT_VALID (pApp);

					BOOL bAllOrMulti = pApp->IsAllDay () || pApp->IsMultiDay ();

					if (CBCGPPlannerView::IsAppointmentInDate (*pApp, date) &&
						((n == 0 && bAllOrMulti) || (n == 1 && !bAllOrMulti)))
					{
						CRect rtApp (rect);

						int nItem = 0;

						while(TRUE)
						{
							POSITION pos = lsItems.Find (nItem);
							if (pos != NULL)
							{
								nItem++;
							}
							else
							{
								break;
							}
						}

						rtApp.top += nItem * delta;
						rtApp.bottom = rtApp.top + m_nRowHeight;

						// check for add new rect
						if (nDay > 0)
						{
							if (bTopEq && bAllOrMulti)
							{
								if (!pApp->GetDSDraw ().IsEmpty ())
								{
									CRect rt;
									rt = pApp->GetRectDraw (date - spanDay);

									if (!rt.IsRectEmpty () && rtApp.top != rt.top)
									{
										rtApp.top    = rt.top;
										rtApp.bottom = rt.bottom;
									}
								}
							}
						}

						if (((bTopEq && !bBottomEq) ||
							 (!bAllOrMulti && 
							  !IsOneDay (pApp->GetStart (), pApp->GetFinish ()))) &&
							!pApp->GetDSDraw ().IsEmpty ())
						{
							CRect rtInter;
							rtInter.IntersectRect (rtApp, m_ViewRects [nDay]);

							if (rtInter.Height () < rtApp.Height () || 
								rtInter.bottom >= rect.bottom || !bAllOrMulti)
							{
								// add impossible rect
								rtApp.OffsetRect (0, 1);
								pApp->SetRectDraw (rtApp, date);
								// return rect
								rtApp.OffsetRect (0, -1);
							}
						}

						pApp->SetRectDraw (rtApp, date);

						lsItems.AddTail ((rtApp.top - rect.top) / delta);
					}
				}
			}
		}

		CheckVisibleAppointments(date, rect, TRUE);

		date += spanDay;
	}

	CheckVisibleUpDownIcons (TRUE);

	m_bUpdateToolTipInfo = TRUE;
}
void CBCGPPlannerPrintMonth::AdjustAppointments ()
{
	XBCGPAppointmentArray& arQueryApps = GetQueryedAppointments ();

	const int nDays = GetViewDuration ();

	if (arQueryApps.GetSize () == 0 || m_ViewRects.GetSize () != nDays)
	{
		return;
	}

	for (int i = 0; i < arQueryApps.GetSize (); i++)
	{
		CBCGPAppointment* pApp = arQueryApps[i];
		ASSERT_VALID (pApp);

		pApp->ResetPrint ();
	}

	COleDateTime date (m_DateStart);

	COleDateTimeSpan spanDay (1, 0, 0, 0);
	const int delta = m_nRowHeight + 2 * m_OnePoint.cy;

	for (int nDay = 0; nDay < nDays; nDay ++)
	{
		CRect rect (m_ViewRects [nDay]);
		rect.top += m_nRowHeight + 2 * m_OnePoint.cy;
		rect.DeflateRect (m_OnePoint.cx, 0);

		BOOL bTopEq    = TRUE;
		BOOL bBottomEq = TRUE;
		
		if (nDay > 0)
		{
			bTopEq    = m_ViewRects [nDay].top == m_ViewRects [nDay - 1].top;
			bBottomEq = m_ViewRects [nDay].bottom == m_ViewRects [nDay - 1].bottom;
		}

		CList<int, int> lsItems;

		for (int i = 0; i < arQueryApps.GetSize (); i++)
		{
			CBCGPAppointment* pApp = arQueryApps[i];
			ASSERT_VALID (pApp);

			if (CBCGPPlannerView::IsAppointmentInDate (*pApp, date))
			{
				CRect rtApp (rect);

				int nItem = 0;

				while(TRUE)
				{
					POSITION pos = lsItems.Find (nItem);
					if (pos != NULL)
					{
						nItem++;
					}
					else
					{
						break;
					}
				}

				rtApp.top += nItem * delta;
				rtApp.bottom = rtApp.top + m_nRowHeight;

				BOOL bAllOrMulti = pApp->IsAllDay () || pApp->IsMultiDay ();

				// check for add new rect
				if (nDay > 0)
				{
					if (bTopEq && bAllOrMulti)
					{
						if (!pApp->GetDSPrint ().IsEmpty ())
						{
							CRect rt;
							rt = pApp->GetRectPrint (date - spanDay);

							if (!rt.IsRectEmpty () && rtApp.top != rt.top)
							{
								rtApp.top    = rt.top;
								rtApp.bottom = rt.bottom;
							}
						}
					}
				}

				if (((bTopEq && !bBottomEq) ||
					 (!bAllOrMulti && 
					  !CBCGPPlannerView::IsOneDay (pApp->GetStart (), pApp->GetFinish ()))) &&
					!pApp->GetDSDraw ().IsEmpty ())
				{
					CRect rtInter;
					rtInter.IntersectRect (rtApp, m_ViewRects [nDay]);

					if (rtInter.Height () < rtApp.Height () || 
						rtInter.bottom >= rect.bottom || !bAllOrMulti)
					{
						// add impossible rect
						rtApp.OffsetRect (0, m_OnePoint.cy);
						pApp->SetRectPrint (rtApp, date);
						// return rect
						rtApp.OffsetRect (0, -m_OnePoint.cy);
					}
				}

				pApp->SetRectPrint (rtApp, date);

				lsItems.AddTail ((rtApp.top - rect.top) / delta);
			}
		}

		CheckVisibleAppointments(date, rect, TRUE);

		date += spanDay;
	}
}
void CBCGPPlannerViewMulti::AdjustAppointments ()
{
	XBCGPAppointmentArray& arQueryApps = GetQueryedAppointments ();
	XBCGPAppointmentArray& arDragApps = GetDragedAppointments ();

	const int nDays = GetViewDuration ();

	if ((arQueryApps.GetSize () == 0 && arDragApps.GetSize () == 0) || 
		m_ViewRects.GetSize () != nDays)
	{
		ClearVisibleUpDownIcons ();
		return;
	}

	BOOL bDrawShadow = IsDrawAppsShadow ();

	BOOL bDragDrop        = IsDragDrop ();
	DROPEFFECT dragEffect = GetDragEffect ();
	BOOL bDragMatch       = IsCaptureMatched ();

	bDragDrop = !bDragDrop || 
		(bDragDrop && ((dragEffect & DROPEFFECT_COPY) == DROPEFFECT_COPY && bDragMatch) || 
		!bDragMatch);
	bDragDrop = bDragDrop && arDragApps.GetSize ();

	const int nTimeDelta = CBCGPPlannerView::GetTimeDeltaInMinuts (GetTimeDelta ());
	const int yOffset = GetViewHourOffset () * m_nRowHeight;
	const int yHeaderOffset = m_nHeaderScrollOffset * (m_nRowHeight + s_HeaderAllDayPadding);

	COleDateTime date (m_DateStart);

	for (int nApp = 0; nApp < 2; nApp++)
	{
		if (!bDragDrop && nApp == 0)
		{
			continue;
		}

		XBCGPAppointmentArray& arApps = nApp == 0 ? arDragApps : arQueryApps;

		for (int i = 0; i < arApps.GetSize (); i++)
		{
			CBCGPAppointment* pApp = arApps[i];
			ASSERT_VALID (pApp);

			pApp->ResetDraw ();
			pApp->GetDSDraw ().SetConcatenate (FALSE);
		}
	}

	COleDateTimeSpan spanDay (1, 0, 0, 0);

	int nDay = 0;

	const BOOL bNoDuration = 
		(GetPlanner ()->GetDrawFlags () & BCGP_PLANNER_DRAW_VIEW_NO_DURATION) == 
		BCGP_PLANNER_DRAW_VIEW_NO_DURATION;

	for (int nRes = 0; nRes < m_Resources.GetSize (); nRes++)
	{
		XResource& resource = m_Resources[nRes];

		date = m_DateStart;

		for (nDay = 0; nDay < nDays; nDay ++)
		{
			XBCGPAppointmentArray arAllDays;

			for (int nApp = 0; nApp < 2; nApp++)
			{
				if (!bDragDrop && nApp == 1)
				{
					continue;
				}

				XBCGPAppointmentArray& arApps = nApp == 1 ? arDragApps : arQueryApps;

				XBCGPAppointmentArray arByDate;

				int i;

				CRect rectFill (resource.m_Rects[nDay]);
				rectFill.top -= yOffset;

				if (bNoDuration && nDay > 0)
				{
					rectFill.left++;
				}

				int nStartIndex = 0;
				for (i = 0; i < arApps.GetSize (); i++)
				{
					const CBCGPAppointment* pApp = arApps[i];
					if (pApp != NULL && pApp->GetResourceID () == resource.m_ResourceID)
					{
						nStartIndex = i;
						break;
					}
				}

				for (i = nStartIndex; i < arApps.GetSize (); i++)
				{
					CBCGPAppointment* pApp = arApps[i];
					ASSERT_VALID (pApp);

					if (pApp->GetResourceID () != resource.m_ResourceID)
					{
						break;
					}

					if (CBCGPPlannerView::IsAppointmentInDate (*pApp, date))
					{
						CRect rtApp (rectFill);

						// trimming top and bottom edge, starting from TimeDelta and Appointment interval
						rtApp.top = rectFill.top + m_nRowHeight * 
							long((pApp->GetStart ().GetHour () * 60 + 
								 pApp->GetStart ().GetMinute ()) / nTimeDelta) - 1;

						if (pApp->IsAllDay () || pApp->IsMultiDay ())
						{
							BOOL bAdd = TRUE;

							for (int i = 0; i < arAllDays.GetSize (); i++)
							{
								if (arAllDays[i] == pApp)
								{
									bAdd = FALSE;
									break;
								}
							}

							if (bAdd)
							{
								arAllDays.Add (pApp);
							}
						}
						else
						{
							rtApp.right -= 2 * BCGP_PLANNER_APPOINTMENT_SPACE;

							if (pApp->GetStart () != pApp->GetFinish ())
							{
								COleDateTime dtAF (pApp->GetFinish ());
								int minutes = dtAF.GetHour () * 60 + dtAF.GetMinute ();

								if (!IsOneDay (pApp->GetStart (), dtAF))
								{
									BOOL bStartDay   = IsOneDay (date, pApp->GetStart ());
									BOOL bFinishNULL = dtAF.GetHour () == 0 && 
													   dtAF.GetMinute () == 0;

									if (bStartDay)
									{
										minutes = 24 * 60;
									}

									if (bFinishNULL)
									{
										if (!bStartDay)
										{
											if (pApp->GetDSDraw ().GetCount () == 1)
											{
												pApp->GetDSDraw ()[0].m_date2 = date;
												continue;
											}
										}
									}
									else
									{
										if (!bStartDay)
										{
											rtApp.top = rectFill.top - 1;
										}
									}
								}

								rtApp.bottom = rectFill.top + m_nRowHeight * 
									(long)ceil(minutes / (double)nTimeDelta) - 1;
							}
							else
							{
								rtApp.bottom = rtApp.top + m_nRowHeight;
							}

							pApp->SetRectDraw (rtApp, date);
							arByDate.Add (pApp);
						}
					}
				}

				// resort appointments in the view, if count of collection is great than 1
				if (arByDate.GetSize () > 1)
				{
					XBCGPAppointmentArray* ar = new XBCGPAppointmentArray;

					// array, that contains columns
					CArray<XBCGPAppointmentArray*, XBCGPAppointmentArray*> arColumns;
					arColumns.Add (ar);

					// initialize first column
					ar->Copy (arByDate);

					while (ar != NULL)
					{
						CBCGPAppointment* pApp1 = ar->GetAt (0);

						XBCGPAppointmentArray* arNew = NULL;

						i = 1;

						// remove appointments, that have collisions in rects, from previous column 
						// to the next column
						while (i < ar->GetSize ())
						{
							CBCGPAppointment* pApp2 = ar->GetAt (i);

							CRect rtInter;
							if (rtInter.IntersectRect (pApp1->GetRectDraw (date), pApp2->GetRectDraw (date)))
							{
								if (arNew == NULL)
								{
									// add a new column
									arNew = new XBCGPAppointmentArray;
									arColumns.Add (arNew);
								}

								arNew->Add (pApp2);
								ar->RemoveAt (i);
							}
							else
							{
								pApp1 = pApp2;
								i++;
							}
						}

						ar = arNew;
					}

					int nCount = (int) arColumns.GetSize ();

					// reinitialize drawing rects, if found great than 1 columns
					if (nCount > 1)
					{
						int nWidth = rectFill.Width () / nCount;
						int nL = rectFill.left;

						// left border of appointments, based on column order
						for (i = 0; i < nCount; i++)
						{
							ar = arColumns[i];

							for (int j = 0; j < ar->GetSize (); j++)
							{
								CBCGPAppointment* pApp = ar->GetAt (j);
								ASSERT_VALID (pApp);

								CRect rtApp (pApp->GetRectDraw (date));
								rtApp.left = nL;

								pApp->SetRectDraw (rtApp, date);
							}

							nL += nWidth;
						}

						// correcting right border of appointments
						for (i = 0; i < nCount; i++)
						{
							ar = arColumns[i];

							for (int j = 0; j < ar->GetSize (); j++)
							{
								CBCGPAppointment* pApp = ar->GetAt (j);
								CRect rtApp (pApp->GetRectDraw (date));

								for (int k = i + 1; k < nCount; k++)
								{
									XBCGPAppointmentArray* arNext = arColumns[k];

									for (int m = 0; m < arNext->GetSize (); m++)
									{
										CBCGPAppointment* pAppNext = arNext->GetAt (m);
									
										CRect rtInter;
										if (rtInter.IntersectRect (rtApp, pAppNext->GetRectDraw (date)))
										{
											rtApp.right = rectFill.left + nWidth * k - 
												(bDrawShadow ? BCGP_PLANNER_APPOINTMENT_SPACE : 0);
											pApp->SetRectDraw (rtApp, date);
											break;
										}
									}
								}
							}
						}
					}

					// clean up columns array
					for (i = 0; i < nCount; i++)
					{
						delete arColumns[i];
					}

					arColumns.RemoveAll ();
				}
			}

			// adjust "all day" or "multi day" appointments
			if (arAllDays.GetSize () > 0)
			{
				const int c_Count = (int) arAllDays.GetSize ();

				CRect rectFill (0, 0, 0, 0);

				rectFill.top    = m_nHeaderHeight + 1 - yHeaderOffset;
				rectFill.bottom = rectFill.top + m_nRowHeight;

				int i = 0;

				for (i = 0; i < c_Count; i++)
				{
					CBCGPAppointment* pApp = arAllDays[i];

					rectFill.left  = resource.m_Rects [nDay].left;
					rectFill.right = resource.m_Rects [nDay].right;

					if (CBCGPPlannerView::IsAppointmentInDate (*pApp, date))
					{
						pApp->SetRectDraw (rectFill, date);
					}
				}

				for (i = 1; i < c_Count; i++)
				{
					CBCGPAppointment* pApp1 = arAllDays[i];

					CRect rtApp1;
					if (pApp1->GetDSDraw ().IsEmpty ())
					{
						rtApp1 = pApp1->GetRectDraw ();
					}
					else
					{
						rtApp1 = pApp1->GetDSDraw ().Get (date)->GetRect ();
					}

					for (int j = 0; j < i; j++)
					{
						CBCGPAppointment* pApp2 = arAllDays[j];

						CRect rtApp2;
						if (pApp2->GetDSDraw ().IsEmpty ())
						{
							rtApp2 = pApp2->GetRectDraw ();
						}
						else
						{
							rtApp2 = pApp2->GetDSDraw ().Get (date)->GetRect ();
						}

						CRect rtInter;
						if (rtInter.IntersectRect (rtApp1, rtApp2))
						{
							rtApp1.top    = rtApp2.top;
							rtApp1.bottom = rtApp2.bottom;
							rtApp1.OffsetRect (0, m_nRowHeight + 2);
							
							if (pApp1->GetDSDraw ().IsEmpty ())
							{
								pApp1->SetRectDraw (rtApp1);
							}
							else
							{
								pApp1->GetDSDraw ().Get (date)->SetRect (rtApp1);
							}

							j = 0;
						}
					}
				}
			}

			date += spanDay;
		}
	}	

	date = m_DateStart;

	for (nDay = 0; nDay < nDays; nDay ++)
	{
		CheckVisibleAppointments (date, m_rectApps, FALSE);

		date += spanDay;
	}

	CheckVisibleUpDownIcons(FALSE);

	m_bUpdateToolTipInfo = TRUE;
}