void CBCGPPlannerViewMulti::OnDrawAppointmentsDuration (CDC* pDC)
{
	if ((GetPlanner ()->GetDrawFlags () & BCGP_PLANNER_DRAW_VIEW_NO_DURATION) == 
			BCGP_PLANNER_DRAW_VIEW_NO_DURATION)
	{
		return;
	}

	XBCGPAppointmentArray& arQueryApps = GetQueryedAppointments ();
	XBCGPAppointmentArray& arDragApps  = GetDragedAppointments ();

	if (arQueryApps.GetSize () == 0 && arDragApps.GetSize () == 0)
	{
		return;
	}

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

	COleDateTime dtS = GetDateStart ();
	COleDateTime dtE = GetDateEnd ();

	const int nMinuts = CBCGPPlannerView::GetTimeDeltaInMinuts (GetTimeDelta ());
	const int nCount = GetViewHours() * 60 / nMinuts;
	const int yOffset = GetViewHourOffset () * m_nRowHeight;

	for (int nApp = 0; nApp < 2; nApp++)
	{
		XBCGPAppointmentArray& arApps = nApp == 1 ? arDragApps : arQueryApps;

		if (nApp == 1)
		{
			bDragDrop = bDragDrop && arDragApps.GetSize ();
		}

		if (arApps.GetSize () == 0)
		{
			continue;
		}

		for (int i = 0; i < arApps.GetSize (); i++)
		{
			CBCGPAppointment* pApp = arApps [i];
			if (pApp == NULL || !(pApp->IsAllDay () || pApp->IsMultiDay ()) || 
				pApp->GetDurationColor () == CLR_DEFAULT)
			{
				continue;
			}

			BOOL bDraw = FALSE;

			if (bDragDrop && dragEffect != DROPEFFECT_NONE && 
				pApp->IsSelected () && nApp == 0)
			{
				if ((dragEffect & DROPEFFECT_COPY) == DROPEFFECT_COPY || bDragMatch)
				{
					bDraw = TRUE;
				}
			}
			else
			{
				bDraw = TRUE;
			}

			if(!bDraw)
			{
				continue;
			}

			int nResourceIndex = FindResourceIndexByID (pApp->GetResourceID ());
			ASSERT(nResourceIndex != -1);
			XResource& resource = m_Resources[nResourceIndex];

			COleDateTime dtStart  = pApp->GetStart ();
			COleDateTime dtFinish = pApp->GetFinish ();

			dtStart.SetDate (dtStart.GetYear (), dtStart.GetMonth (), dtStart.GetDay ());
			dtFinish.SetDate (dtFinish.GetYear (), dtFinish.GetMonth (), dtFinish.GetDay ());

			BOOL bStart = FALSE;
			BOOL bEnd   = FALSE;

			if (dtStart < dtS)
			{
				dtStart = dtS;
				bStart  = TRUE;
			}

			if (dtE < dtFinish)
			{
				dtFinish = dtE;
				bEnd     = TRUE;
			}

			COleDateTimeSpan span (dtFinish - dtStart);

			int nStart = (dtStart - dtS).GetDays ();
			int nEnd   = min(nStart + span.GetDays () + 1, GetViewDuration ());

			CBrush br (pApp->GetDurationColor () == CLR_DEFAULT
				? globalData.clrWindow
				: pApp->GetDurationColor ());

			for(int i = nStart; i < nEnd; i++)
			{
				CRect rt (resource.m_Rects[i]);

				rt.right  = rt.left + 
					CBCGPPlannerViewMulti::BCGP_PLANNER_DURATION_BAR_WIDTH + 1;		
				rt.left  -= (i == 0) ? 1 : 0;
				rt.top   -= 1;
				rt.bottom = rt.top + nCount * m_nRowHeight;
				rt.DeflateRect (1, 0);
				
				if (!pApp->IsAllDay ())
				{
					rt.OffsetRect (0, -yOffset);

					if (i == (nEnd - 1) && !bEnd)
					{
						dtFinish = pApp->GetFinish ();
						const double dDelta = (dtFinish.GetHour () * 60 + dtFinish.GetMinute ()) / (double)nMinuts;

						rt.bottom = rt.top + CBCGPPlannerView::round(dDelta * m_nRowHeight);
					}

					if (i == nStart && !bStart)
					{
						dtStart  = pApp->GetStart ();
						const double dDelta = 
							(dtStart.GetHour () * 60 + dtStart.GetMinute ()) / (double)nMinuts;

						rt.top += CBCGPPlannerView::round(dDelta * m_nRowHeight);
					}

					rt.IntersectRect (rt, resource.m_Rects[i]);
				}

				pDC->FillRect (rt, &br);
			}
		}
	}
}
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;
}