// GanttCtrl.cpp: implementation of the CGanttCtrl class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "GanttCtrl.h"
//#include "apl_api.h"
#include "GanttView.h"
#include <locale.h>
//#include "ximage.h"
//#include "ReportDict.h"
#include "ShowGanttDlg.h"
#include <ReportDict.h>

//__declspec (dllexport) bool SaveBitmapAs(HBITMAP hBM, LPCTSTR FileName, int DPI = -1, BOOL bColor = TRUE, DWORD CompressionMode=0);

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif


bool m_bShowMultipleColors=true;

COLORREF gantt_color=RGB(0,150,250);
COLORREF gantt_border_color=RGB(0,51,153);
COLORREF gantt_worked_color=RGB(0,102,151);

COLORREF group_color=RGB(51,51,153);


BEGIN_MESSAGE_MAP(CGanttCtrl, CWnd)
	//{{AFX_MSG_MAP(CaplTreeListCtrl)
	ON_WM_PAINT()
	ON_WM_LBUTTONDOWN()
	ON_WM_LBUTTONDBLCLK()
	ON_WM_MOUSEMOVE()
	ON_WM_DESTROY()	
	//}}AFX_MSG_MAP
	ON_MESSAGE(WM_MOUSELEAVE, OnMouseLeave)
	ON_WM_ERASEBKGND()
	ON_WM_LBUTTONUP()
	ON_WM_SETCURSOR()
END_MESSAGE_MAP()

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CGanttCtrl::CGanttCtrl()
{
	m_nColumnsWidth = 0;
	m_nOffset = 0;
	m_bShowVerLiles=true;
	m_blockHeight=16;
	m_pixelsInDay=10;
	m_headerHeight=40;
	m_col_days=0;
	m_api=0;
	m_project_mgr=0;
	m_dlg=0;
	m_view_mode=APL_MODE_MONTHS;
	m_bShowRelations=true;

	m_grag_item=0;

	COLORMAP  cm[2];
	cm[0].from=RGB(255,255,255);
	cm[0].to=gantt_color;
	cm[1].from=RGB(0,0,128);
	cm[1].to=RGB(255,255,255);
	//cm[1].to=RGB(5,255,255);
	//cm.to=GetSysColor(COLOR_BTNFACE);

	//m_pattern_bmp.LoadBitmap(IDB_PATTERN);
//	m_pattern_bmp.LoadMappedBitmap(IDB_PATTERN,0,cm,2);
	m_project_id_width=200;
	m_max_id_length=0;

	LOGFONT lf;
	CFont *font=(CFont*)CFont::FromHandle((HFONT)GetStockObject(ANSI_VAR_FONT));
	font->GetLogFont(&lf);
	lf.lfWeight=FW_NORMAL;
	m_pFont.CreateFontIndirect(&lf);
	m_ToolTip.m_pFont=&m_pFont;
	m_ToolTip.m_delay_time=100;
	
	bIsRect=false;
	bIsLine=false;

}

CGanttCtrl::~CGanttCtrl()
{

}

void CGanttCtrl::GetAllSubItems(HTREEITEM hItem, tItemsAplTAggt &items)
{
	if(hItem!=TVI_ROOT)
	{
		CGanttItem *gitem =(CGanttItem*)(m_gantt_view->m_tree_view->m_tree.GetItemData(hItem));
		if(0!=gitem) items.Add(gitem);
	}
	HTREEITEM hChildItem = m_gantt_view->m_tree_view->m_tree.GetNextItem(hItem, TVGN_CHILD);
	while (hChildItem)
	{
		GetAllSubItems(hChildItem,items);
		hChildItem = m_gantt_view->m_tree_view->m_tree.GetNextItem(hChildItem, TVGN_NEXT);
	}
}


void CGanttCtrl::RenumGanttItems(HTREEITEM hItem, int &counter)
{
	CGanttItem *gitem=0;
	if(hItem!=TVI_ROOT)
	{
		gitem=(CGanttItem*)(m_gantt_view->m_tree_view->m_tree.GetItemData(hItem));
		if(0!=gitem)
		{
			gitem->pos=counter;
			gitem->rect_plan.top=0;
			gitem->rect_plan.bottom=0;
			counter++;
		}
	}
	int cur_counter=counter;
	HTREEITEM hChildItem = m_gantt_view->m_tree_view->m_tree.GetNextItem(hItem, TVGN_CHILD);
	while (hChildItem)
	{
		RenumGanttItems(hChildItem,counter);
		hChildItem = m_gantt_view->m_tree_view->m_tree.GetNextItem(hChildItem, TVGN_NEXT);
	}
	if(0!=gitem) gitem->sub_items_count=counter-cur_counter;

}

CGanttItem::CGanttItem()
{
	prj=0;
	hTreeItem=0;
	id=_T("");
	name=_T("");
	itemData=0;
	pl_date_begin.SetStatus(COleDateTime::null);
	pl_date_end.SetStatus(COleDateTime::null);
	act_date_begin.SetStatus(COleDateTime::null);
	act_date_end.SetStatus(COleDateTime::null);
	act_date_end_prognoz.SetStatus(COleDateTime::null);

	percentage=0;
	sub_items_count=-1;
	color=gantt_color;

	pos=-1;

	rect_plan.left=rect_plan.right=rect_plan.top=rect_plan.bottom=-1;

	prev_progn_prj=0;
	prev_progn_item=0;

	first_progn_sub_prj=0;
	first_progn_sub_item=0;
	last_progn_sub_prj=0; 
	last_progn_sub_item=0;

	instMyLock=0;
}
/*
CGanttItem* CGanttCtrl::FindItem(HTREEITEM hItem)
{
	if(!hItem) return 0;
	for(int i=0;i<m_items.GetSize();i++)
	{
		if(m_items[i].hTreeItem==hItem) return &m_items[i];
	}
	return 0;
}


int CGanttCtrl::InsertItem(CGanttItem &new_item)
{
	return m_items.Add(new_item);
}

void CGanttCtrl::RemoveAllItems()
{
	m_items.RemoveAll();
	m_items_rels.RemoveAll();
}
*/

void CGanttCtrl::UpdateCalendar(bool resetScrollBar)
{
	COleDateTime old_max_date=m_max_date;
	COleDateTime old_min_date=m_min_date;
	int old_pix_in_day=m_pixelsInDay;
	CalcMaxMinDates();
	if(old_max_date!=m_max_date || old_min_date!=m_min_date || old_pix_in_day!=m_pixelsInDay) 
	{
		RecalcColumnsWidth();
		if(resetScrollBar) ((CGanttView*)GetParent())->ResetScrollBar();
	}
}

void CGanttCtrl::CalcMaxMinDates()
{
	if(!m_gantt_view->m_items.GetSize()) return;

	COleDateTime dt=COleDateTime::GetCurrentTime(),dt1;
	m_min_date=dt;
	m_max_date=dt;

	int i;
	for(i=0;i<m_gantt_view->m_items.GetSize();i++)
	{
		CGanttItem *item=m_gantt_view->m_items[i];
		if(0==item) continue;
		if(item->pl_date_begin.GetStatus()==COleDateTime::valid)
		{
			if(item->pl_date_begin>m_max_date) m_max_date=item->pl_date_begin;
			if(item->pl_date_begin<m_min_date) m_min_date=item->pl_date_begin;
		}

		if(item->pl_date_end.GetStatus()==COleDateTime::valid)
		{
			if(item->pl_date_end>m_max_date) m_max_date=item->pl_date_end;
			if(item->pl_date_end<m_min_date) m_min_date=item->pl_date_end;
		}

		if(item->act_date_begin.GetStatus()==COleDateTime::valid)
		{
			if(item->act_date_begin>m_max_date) m_max_date=item->act_date_begin;
			if(item->act_date_begin<m_min_date) m_min_date=item->act_date_begin;
		}
		if(item->act_date_end.GetStatus()==COleDateTime::valid)
		{
			if(item->act_date_end>m_max_date) m_max_date=item->act_date_end;
			if(item->act_date_end<m_min_date) m_min_date=item->act_date_end;
		}

		if(m_gantt_view->m_bShowPrognoz)
		{
			if(item->act_date_end_prognoz.GetStatus()==COleDateTime::valid)
			{
				if(item->act_date_end_prognoz>m_max_date) m_max_date=item->act_date_end_prognoz;
			}
		}

	}
	if(m_max_date<m_min_date)
	{
		COleDateTime buf=m_min_date;
		m_min_date=m_max_date;
		m_max_date=buf;
	}


	// Округляем до первого числа месяца

	m_max_date+=COleDateTimeSpan(40,0,0,0);
	m_min_date-=COleDateTimeSpan(10,0,0,0);;

	m_min_date.SetDateTime(m_min_date.GetYear(),m_min_date.GetMonth(),1,0,0,0);
	m_max_date.SetDateTime(m_max_date.GetYear(),m_max_date.GetMonth(),1,0,0,0);
}

void CGanttCtrl::ResetVertScrollBar()
{
	CGanttView *pFrame = (CGanttView*)GetParent();

	CRect m_ganttRect;
	GetClientRect(&m_ganttRect);

	CRect m_wndRect;
	pFrame->GetClientRect(&m_wndRect);

	CRect m_barRect;
	pFrame->m_horScrollBar.GetClientRect(&m_barRect);

/*	if(!pFrame->HorizontalScrollVisible())
		SetWindowPos(&wndTop, 0, 0, m_wndRect.Width(), m_wndRect.Height()-m_headerHeight, SWP_NOMOVE);
	else
		SetWindowPos(&wndTop, 0, 0, m_wndRect.Width(), m_wndRect.Height()-m_barRect.Height()-m_headerHeight, SWP_NOMOVE);*/
	if(!pFrame->HorizontalScrollVisible())
		SetWindowPos(&wndTop, 0, 0, m_wndRect.Width(), m_wndRect.Height(), SWP_NOMOVE);
	else
		SetWindowPos(&wndTop, 0, 0, m_wndRect.Width(), m_wndRect.Height()-m_barRect.Height(), SWP_NOMOVE);

	if(pFrame->HorizontalScrollVisible())
	{
		if(!pFrame->VerticalScrollVisible())
		{
			pFrame->m_horScrollBar.SetWindowPos(&wndTop, 0, 0, m_wndRect.Width(), m_barRect.Height(), SWP_NOMOVE);
			
			int nMin, nMax;
			pFrame->m_horScrollBar.GetScrollRange(&nMin, &nMax);
			if((nMax-nMin) == (GetColumnsWidth()-m_ganttRect.Width()+GetSystemMetrics(SM_CXVSCROLL)))
				// i.e. it disappeared because of calling
				// SetWindowPos
			{
				if(nMax - GetSystemMetrics(SM_CXVSCROLL) > 0)
					pFrame->m_horScrollBar.SetScrollRange(nMin, nMax - GetSystemMetrics(SM_CXVSCROLL));
				else
					// hide the horz scroll bar and update the tree
				{
					pFrame->m_horScrollBar.EnableWindow(FALSE);

					// we no longer need it, so hide it!
					{
						pFrame->m_horScrollBar.ShowWindow(SW_HIDE);

						//SetWindowPos(&wndTop, 0, 0, m_wndRect.Width(), m_wndRect.Height() - m_headerHeight, SWP_NOMOVE);
						SetWindowPos(&wndTop, 0, 0, m_wndRect.Width(), m_wndRect.Height(), SWP_NOMOVE);
						// the tree takes scroll's place
					}

					pFrame->m_horScrollBar.SetScrollRange(0, 0);

					// set scroll offset to zero
					{
						m_nOffset = 0;
						Invalidate();
					}
				}
			}
		}
		else
		{
			pFrame->m_horScrollBar.SetWindowPos(&wndTop, 0, 0, m_wndRect.Width() - GetSystemMetrics(SM_CXVSCROLL), m_barRect.Height(), SWP_NOMOVE);

			int nMin, nMax;
			pFrame->m_horScrollBar.GetScrollRange(&nMin, &nMax);
			if((nMax-nMin) == (GetColumnsWidth()-m_ganttRect.Width()-GetSystemMetrics(SM_CXVSCROLL)))
				// i.e. it appeared because of calling
				// SetWindowPos
			{
				pFrame->m_horScrollBar.SetScrollRange(nMin, nMax + GetSystemMetrics(SM_CXVSCROLL));
			}
		}
	}
	else
	if(pFrame->VerticalScrollVisible())
	{
		if(GetColumnsWidth()>m_ganttRect.Width())
			// the vertical scroll bar takes some place
			// and the columns are a bit bigger than the client
			// area but smaller than (client area + vertical scroll width)
		{
			// show the horz scroll bar
			{
				pFrame->m_horScrollBar.EnableWindow(TRUE);

				pFrame->m_horScrollBar.ShowWindow(SW_SHOW);

				// the tree becomes smaller
				//SetWindowPos(&wndTop, 0, 0, m_wndRect.Width(), m_wndRect.Height()-m_barRect.Height()-m_headerHeight, SWP_NOMOVE);
				SetWindowPos(&wndTop, 0, 0, m_wndRect.Width(), m_wndRect.Height()-m_barRect.Height(), SWP_NOMOVE);

				pFrame->m_horScrollBar.SetWindowPos(&wndTop, 0, 0, m_wndRect.Width() - GetSystemMetrics(SM_CXVSCROLL), m_barRect.Height(), SWP_NOMOVE);
			}

			pFrame->m_horScrollBar.SetScrollRange(0, GetColumnsWidth()-m_ganttRect.Width());
		}
	}
}
/*
int CGanttCtrl::GetColumnWidth(int nCol)
{
	HD_ITEM hItem;
	hItem.mask = HDI_WIDTH;
	if(!m_wndHeader.GetItem(nCol, &hItem))
		return 0;

	return hItem.cxy;
}

bool CGanttCtrl::GetColumnDate(int nCol,CString &buf)
{
	if(nCol>m_wndHeader.GetItemCount()) return false;
	buf=_T("");
	buf=m_wndHeader.m_dates[nCol];
	return true;
}
*/
void CGanttCtrl::RecalcColumnsWidth()
{
	m_nColumnsWidth = 0;
	COleDateTimeSpan dt_span=m_max_date-m_min_date;
	if(dt_span.GetStatus()==COleDateTimeSpan::valid) 
	{
		m_col_days=dt_span.GetDays()+1;
		m_nColumnsWidth=m_col_days*m_pixelsInDay;

	}
}

void CGanttCtrl::PaintCalendar(CDC &dc,long mode)
{
	CRect rcClient;
	GetClientRect(&rcClient);

	CPoint p=dc.GetViewportOrg();
	dc.SetViewportOrg(m_nOffset+p.x, p.y);
	//dc.SetTextColor(m_wndColor);

	// First let the control do its default drawing.
	//CWnd::DefWindowProc( WM_PAINT, (WPARAM)dc.m_hDC, 0 );

	CFont *pFont = CFont::FromHandle((HFONT)GetStockObject(SYSTEM_FONT));
	CFont *pSmallFont=CFont::FromHandle((HFONT)GetStockObject(ANSI_VAR_FONT));
	CFont *oldFont=dc.SelectObject(pFont);

	int i;
	CString buf;
	COleDateTime dt;
	CPen pen(PS_SOLID,1,RGB(192,192,192));
	CPen *oldPen=dc.SelectObject(&pen);  // просто запоминаем
	int High=rcClient.Height();
	bool foundSaturday=false;
	int top=m_headerHeight+1;
	if(m_blockHeight*m_gantt_view->m_items.GetSize()+top>High) High=m_blockHeight*m_gantt_view->m_items.GetSize()+top;
	int leftBound=2;
	COleDateTimeSpan dt_span,week_span;
	dt_span.SetDateTimeSpan(1,0,0,0);
	week_span.SetDateTimeSpan(7,0,0,0);
	dt.SetDateTime(m_min_date.GetYear(),m_min_date.GetMonth(),m_min_date.GetDay(),0,0,0);

	CRect holidayRect;
	holidayRect.top=top;
	holidayRect.bottom=High;

	CRect curDayRect;
	curDayRect.top=top;
	curDayRect.bottom=High;

	CRect weekRect;
	weekRect.left=2;

	CRect yearRect;
	yearRect.left=2;
	yearRect.top=0;
	yearRect.bottom=m_headerHeight;

	CRect monthRect;
	monthRect.left=2;
	monthRect.top=0;
	monthRect.bottom=m_headerHeight;
	if(m_view_mode==APL_MODE_YEARS)
	{
		monthRect.top=int(m_headerHeight/2);
		monthRect.bottom=m_headerHeight-3;
	}
	else if(m_view_mode==APL_MODE_MONTHS)
	{
		monthRect.top=0;
		monthRect.bottom=m_headerHeight;
	}
	else if(m_view_mode==APL_MODE_WEEKS)
	{
		weekRect.top=0;
		weekRect.bottom=m_headerHeight;
	}
	//
	TCHAR *locale=_setlocale(LC_TIME,_T("Russian"));
	COleDateTime dt0;
	CRect dayRect;
	dayRect.top=int(m_headerHeight/2);
	dayRect.bottom=m_headerHeight-3;
	dayRect.left=2;

	int dayRectWidth=30;
	LOGFONT logfont;
	if(pSmallFont)
	{
		pFont->GetLogFont( &logfont );
		dayRectWidth=logfont.lfWidth*5;
	}

	COleDateTime cur_dt=COleDateTime::GetCurrentTime();
	cur_dt.SetDateTime(cur_dt.GetYear(),cur_dt.GetMonth(),cur_dt.GetDay(),0,0,0);

	CBrush holidayBrush,curDayBrush;
	holidayBrush.CreateSolidBrush(RGB(250,250,250));
	curDayBrush.CreateSolidBrush(RGB(255,255,102));
	CBrush *oldBrush=dc.SelectObject(&holidayBrush); // просто запоминаем

	/*if(mode==APL_MODE_SAVE)//отрисока заголовка проектов
	{
		monthRect.left=leftBound;
		monthRect.right=m_project_id_width-1;
		dc.DrawText(APL_T("Проект"), monthRect,DT_CENTER);
		//Отрисовка линий 
		dc.MoveTo(leftBound-1,top);
		dc.LineTo(leftBound-1,High);
		dc.MoveTo(leftBound+m_project_id_width-1,top);
		dc.LineTo(leftBound+m_project_id_width-1,High);
		leftBound+=m_project_id_width;
	}*/
	int nameLeftBound=leftBound;
	int monthLeftBound=leftBound;

	bool bDrawPrewYear=false; // был ли отрисован год, если он был до 1 го 1 января

	for(i=0;i<=m_col_days;i++)
	{
		if(mode!=APL_MODE_SAVE && ((leftBound+m_pixelsInDay)>(rcClient.right-m_nOffset)))
			break;
		if(mode==APL_MODE_SAVE ||(leftBound+m_nOffset)>0)
		{
			if(dt.GetStatus()==COleDateTime::valid)
			{
				// Отрисовка вертикальных линий дней
				dc.MoveTo(leftBound-1,m_headerHeight-3);
				dc.LineTo(leftBound-1,m_headerHeight);
				dc.MoveTo(leftBound+m_pixelsInDay-1,m_headerHeight-3);
				dc.LineTo(leftBound+m_pixelsInDay-1,m_headerHeight);

				if(m_view_mode==APL_MODE_YEARS)
				{
					// Отрисовка вертикальных линий годов и вывод их названий
					if((dt.GetMonth()==1 && dt.GetDay()==1) || dt==m_max_date)
					{
						if(dt==m_max_date)
						{
							dc.MoveTo(leftBound+m_pixelsInDay-1,0);
							dc.LineTo(leftBound+m_pixelsInDay-1,m_headerHeight);
							//yearRect.right=leftBound+m_pixelsInDay;
						}
						else
						{
							dc.MoveTo(leftBound-1,0);
							dc.LineTo(leftBound-1,m_headerHeight);
							//yearRect.right=leftBound;
						}

						if(!bDrawPrewYear)
						{
							// Рисуем предыдущий год
							buf.Format(_T("%i"),dt.GetYear()-1);
							CRect prevYearRect=yearRect;
							prevYearRect.right=leftBound;
							prevYearRect.left=0;
							if(prevYearRect.Width()>50)	dc.DrawText(buf, prevYearRect,DT_CENTER);
							bDrawPrewYear=true;
						}

						int numDaysToDrawYear=365;
						
						int k1=dt.GetYear();
						int k2=m_max_date.GetYear();
						if(dt.GetYear()==m_max_date.GetYear()) // Это последний год, и для него
						{
							numDaysToDrawYear=(m_max_date-dt).GetDays();
						}

						yearRect.left=leftBound;
						yearRect.right=yearRect.left+numDaysToDrawYear*m_pixelsInDay;
						//dt0=dt-dt_span;
						buf=dt.Format(_T("%Y"));
						dc.DrawText(buf, yearRect,DT_CENTER);
						nameLeftBound=leftBound;
					}
					// Отрисовка вертикальных линий месяцев и вывод их названий
					if(dt.GetDay()==1 || dt==m_max_date)
					{
						if(dt==m_max_date)
						{
							dc.MoveTo(leftBound+m_pixelsInDay-1,monthRect.top);
							dc.LineTo(leftBound+m_pixelsInDay-1,monthRect.bottom);
							monthRect.right=leftBound+m_pixelsInDay;
						}
						else
						{
							dc.MoveTo(leftBound-1,monthRect.top);
							dc.LineTo(leftBound-1,monthRect.bottom);
							monthRect.right=leftBound;
						}
						dc.SelectObject( pSmallFont );
						monthRect.left=monthLeftBound;
						monthRect.right=monthRect.left+(28*m_pixelsInDay);
						dt0=dt-dt_span;
						if(m_pixelsInDay>=3) buf=dt0.Format(_T("%B %Y"));
						else if(m_pixelsInDay>=2) buf=dt0.Format(_T("%m.%Y"));
						else buf=dt0.Format(_T("%m"));

						dc.DrawText(buf, monthRect,DT_CENTER);
						dc.SelectObject( pFont );
						monthLeftBound=leftBound;
					}
					if(dt.GetDayOfWeek()==2)
					{
						if(m_bShowVerLiles)
						{
							dc.MoveTo(leftBound-1,top);
							dc.LineTo(leftBound-1,High);
						}
					}
				}
				else if(m_view_mode==APL_MODE_MONTHS)
				{
					// Отрисовка вертикальных линий месяцев и вывод их названий
					if(dt.GetDay()==1 || dt==m_max_date)
					{
						if(dt==m_max_date)
						{
							dc.MoveTo(leftBound+m_pixelsInDay-1,0);
							dc.LineTo(leftBound+m_pixelsInDay-1,m_headerHeight);
							monthRect.right=leftBound+m_pixelsInDay;
						}
						else
						{
							dc.MoveTo(leftBound-1,0);
							dc.LineTo(leftBound-1,m_headerHeight);
							monthRect.right=leftBound;
						}
						monthRect.left=nameLeftBound;
						dt0=dt-dt_span;
						buf=dt0.Format(_T("%B %Y"));
						dc.DrawText(buf, monthRect,DT_CENTER);
						nameLeftBound=leftBound;
					}
					// Отрисовка вертикальных линий, отмечающих выходные дни на календаре
					if(dt.GetDayOfWeek()==7)
					{
						foundSaturday=true;
						holidayRect.left=leftBound;
					}
					else if(dt.GetDayOfWeek()==1)
					{
						if(m_bShowVerLiles)
						{
							if(foundSaturday)
							{
								dc.MoveTo(holidayRect.left-1,top);
								dc.LineTo(holidayRect.left-1,High);
								dc.MoveTo(leftBound+m_pixelsInDay-1,top);
								dc.LineTo(leftBound+m_pixelsInDay-1,High);
								holidayRect.right=leftBound+m_pixelsInDay-1;
								dc.FillRect(holidayRect, &holidayBrush);
							}
						}
					}
					if(dt.GetDayOfWeek()==2)
					{
						//даты, на которые приходятся понедельники
						dc.SelectObject( pSmallFont );
						dayRect.left=leftBound;
						dayRect.right=leftBound+m_pixelsInDay;
						buf=dt.Format(_T("%d"));
						dc.DrawText(buf, dayRect,DT_BOTTOM|DT_NOCLIP);
						dc.SelectObject( pFont );
					}
				}
				else if(m_view_mode==APL_MODE_WEEKS)
				{
					// Отрисовка вертикальных линий недель и вывод их названий
					if(dt.GetDayOfWeek()==2 || dt==m_max_date)
					{
						if(dt==m_max_date)
						{
							dc.MoveTo(leftBound+m_pixelsInDay-1,0);
							dc.LineTo(leftBound+m_pixelsInDay-1,m_headerHeight);
							weekRect.right=leftBound+m_pixelsInDay;
						}
						else
						{
							dc.MoveTo(leftBound-1,0);
							dc.LineTo(leftBound-1,m_headerHeight);
							weekRect.right=leftBound;
						}

						weekRect.left=nameLeftBound;
						dt0=dt-week_span;
						buf=dt0.Format(_T("%d %B %Y"));
						if((dt-m_min_date).GetDays()>=7) dc.DrawText(buf, weekRect,DT_CENTER);
						nameLeftBound=leftBound;

					}
					// Отрисовка выходных дней
					if(dt.GetDayOfWeek()==7)
					{
						foundSaturday=true;
						holidayRect.left=leftBound;
					}
					else if(dt.GetDayOfWeek()==1)
					{
						if(m_bShowVerLiles)
						{
							if(foundSaturday)
							{
								dc.MoveTo(holidayRect.left-1,top);
								dc.LineTo(holidayRect.left-1,High);
								dc.MoveTo(leftBound+m_pixelsInDay-1,top);
								dc.LineTo(leftBound+m_pixelsInDay-1,High);
								holidayRect.right=leftBound+m_pixelsInDay-1;
								dc.FillRect(holidayRect, &holidayBrush);
							}
						}
					}
					//вывод названий дней
					dc.SelectObject( pSmallFont );
					dayRect.left=leftBound;
					dayRect.right=leftBound+m_pixelsInDay;
					buf=dt.Format(_T("%d"));
					dc.DrawText(buf, dayRect,DT_BOTTOM|DT_NOCLIP);
					dc.SelectObject( pFont );
					//Отрисовка линий дней
					dc.MoveTo(leftBound-1,top);
					dc.LineTo(leftBound-1,High);
				}
				//Отрисовка текущей даты
				if(dt==cur_dt && i<m_col_days-1)
				{
					curDayRect.left=leftBound-1;
					curDayRect.right=curDayRect.left+m_pixelsInDay-1;
					dc.FillRect(curDayRect, &curDayBrush);
					dc.MoveTo(curDayRect.left,top);
					dc.LineTo(curDayRect.left,High);
					dc.MoveTo(curDayRect.right,top);
					dc.LineTo(curDayRect.right,High);
				}

			}
		}
		dt+=dt_span;
		leftBound+=m_pixelsInDay;
	}

	//отрисовка разделительной линии между заголовком и основной частью 
	dc.MoveTo(0,m_headerHeight);
	dc.LineTo(max(rcClient.Width(),GetColumnsWidth()),m_headerHeight);

	dc.SelectObject(&oldBrush);
	dc.SelectObject(&oldPen);
	dc.SelectObject(oldFont);
}
// x1= левая точка x2 = правая точка  x3 - если x3>x1, то хвост не рисуется , size - размер стрелки
void ganttDrawArrow(int x1, int x2, int x3, int y, int size, CDC &dc, CPen *pen, CBrush *brush)
{
	if(x1<=0) return;
	if(x2<=0) return;
	if(y<=0) return;

	if(size<4) size=4;

	int cy1=size-2;
	int cy2=(size-cy1)*2;
	
	CPen *oldpen=0;
	CBrush *oldbrush=0;

	if (0!=pen) oldpen=dc.SelectObject(pen);
	if (0!=brush) oldbrush=dc.SelectObject(brush);

	POINT p[8];
	int k=0;
	p[k].x=x2-size; p[k].y=y-size;  k++;

	if((x1<(x2-size-1)) && x1>x3)
	{
		p[k].x=p[0].x;		p[k].y=p[0].y+cy1;  k++;
		p[k].x=x1;			p[k].y=p[k-1].y;	k++;
		p[k].x=x1;			p[k].y=p[k-1].y+cy2;  k++;
		p[k].x=p[0].x;		p[k].y=p[k-1].y;	k++;
	}
	p[k].x=x2-size;	p[k].y=y+size;	k++;
	p[k].x=x2;		p[k].y=y;		k++;
	p[k]=p[0];
	dc.Polygon(p,k);

	if (0!=pen) dc.SelectObject(oldpen);
	if (0!=brush) dc.SelectObject(oldbrush);
}


void CGanttCtrl::PaintDiagram(CDC &dc,long mode)	
{
	if(0==m_gantt_view) return;

	PaintCalendar(dc,mode);
	
	//**** Рисование прямоугольников

	CRect rcClient;
	GetClientRect(&rcClient);

	HTREEITEM hSelItem=m_gantt_view->m_tree_view->m_tree.GetSelectedItem();

	CRect rect,gantt_rect,persentage_rect,actual_rect;
	int height=m_headerHeight;
	int top=m_headerHeight+1;

	CFont *pFont = CFont::FromHandle((HFONT)GetStockObject(SYSTEM_FONT));
	CFont *pSmallFont=CFont::FromHandle((HFONT)GetStockObject(ANSI_VAR_FONT));

	COLORREF crSelect = GetSysColor(COLOR_HIGHLIGHT);
	COLORREF crSelectFill=aplColor_GetHilightColor(crSelect,75);
	COLORREF prev_color=RGB(255,255,255);

	CBrush variable_brush_prj, variable_brush_procent;
	CBrush gantt_border_brush,group_border_brush,gantt_brush,group_brush,dark_brush;
	CBrush select_brush,actual_brush,persentage_brush;
	gantt_border_brush.CreateSolidBrush(gantt_border_color);
	group_border_brush.CreateSolidBrush(aplColor_GetHilightColor(gantt_color,75));
	group_brush.CreateSolidBrush(group_color);
	dark_brush.CreateSolidBrush(RGB(100,100,100));
	select_brush.CreateSolidBrush(RGB(204,204,153));
	actual_brush.CreateSolidBrush(gantt_border_color);
	persentage_brush.CreateSolidBrush(gantt_color);
	CBrush actual_working_prognoz_brush; 
	actual_working_prognoz_brush.CreateSolidBrush(gantt_worked_color);//gantt_border_color);
	gantt_brush.CreateSolidBrush(aplColor_GetHilightColor(gantt_color,75));

	LOGBRUSH lbr; lbr.lbColor=gantt_worked_color; lbr.lbHatch=0; lbr.lbStyle=BS_SOLID;
	CPen actual_end_pen;
	actual_end_pen.CreatePen(PS_SOLID|PS_GEOMETRIC|PS_ENDCAP_FLAT|PS_JOIN_MITER,3,&lbr);
	CPen actual_pen_arrow(PS_SOLID|PS_GEOMETRIC|PS_ENDCAP_FLAT,1,gantt_worked_color);
	CPen actual_ended_pen(PS_SOLID,5,gantt_worked_color);//gantt_border_color);
	
	CPen prognoz_arrow_pen(PS_SOLID|PS_GEOMETRIC|PS_ENDCAP_SQUARE|PS_JOIN_MITER,1,RGB(196,0,196));//gantt_worked_color);
	LOGBRUSH prognoz_not_worked_brush; prognoz_not_worked_brush.lbStyle = BS_SOLID; prognoz_not_worked_brush.lbHatch=0; prognoz_not_worked_brush.lbColor = gantt_worked_color;
	CPen prognoz_pen(PS_DOT|PS_GEOMETRIC|PS_ENDCAP_SQUARE|PS_JOIN_MITER,1,&prognoz_not_worked_brush);
	CPen prognoz_prev_pen(PS_SOLID|PS_GEOMETRIC|PS_ENDCAP_SQUARE|PS_JOIN_MITER,0,RGB(255,0,255));//aplColor_GetHilightColor(gantt_worked_color,40));

	CPen red_pen(PS_SOLID,2,RGB(255,0,0));
	CPen black_pen(PS_SOLID,1,RGB(0,0,0));

	LOGBRUSH logBrush; logBrush.lbStyle = BS_SOLID;  logBrush.lbColor = gantt_worked_color; logBrush.lbHatch=0;
	CPen actual_working_pen(PS_DASH|PS_GEOMETRIC|PS_ENDCAP_FLAT, 3, &logBrush);  
	CPen actual_working_toend_pen(PS_DOT|PS_GEOMETRIC|PS_ENDCAP_FLAT, 3, &logBrush);  

	CPen border_pen(PS_SOLID|PS_GEOMETRIC|PS_ENDCAP_FLAT,1,crSelect);
	CPen border_select_pen(PS_SOLID|PS_GEOMETRIC|PS_ENDCAP_FLAT,1,aplColor_GetHilightColor(crSelectFill,-100));

	//CPen border_pen4chekout(PS_SOLID|PS_GEOMETRIC|PS_ENDCAP_FLAT,1,crSelect);

	CRect group_rect;

	COleDateTimeSpan dt_span1,dt_span2;
	COleDateTime dt_begin,dt_end;

	int xPrognoz;

	CBrush *oldBrush=dc.SelectObject(&group_border_brush);	// просто запоминаем
	CPen   *oldPen=dc.SelectObject(&black_pen);				// просто запоминаем
	CFont *oldFont=dc.SelectObject(pFont);					// просто запоминаем

	int i=0,n = m_gantt_view->m_tree_view->m_tree.GetVisibleCount();
	CString buf,sdate;
	bool bIsVisible=false;

	//обнуляем координаты всех 
	for(i=0;i<m_gantt_view->m_items.GetSize();i++) 
	{
		CGanttItem *gitem=m_gantt_view->m_items[i];
		RECT &r=gitem->rect_plan;
		r.left=Date2Pos(gitem->pl_date_begin);
		r.right=Date2Pos(gitem->pl_date_end);
		r.top=0;
		r.bottom=0;
	}


	if(mode==APL_MODE_SAVE)
	{

	}


	//Определяем расположение элементов
	m_visible_items.Clear();

	if(mode==APL_MODE_SAVE) GetAllSubItems(TVI_ROOT,m_visible_items);
	else
	{
		int i=0, visible_count=m_gantt_view->m_tree_view->m_tree.GetVisibleCount();

		HTREEITEM hItem = m_gantt_view->m_tree_view->m_tree.GetFirstVisibleItem();
		while(hItem!=NULL && n>=0)
		{
			if(i>visible_count) break;
			i++;
			CGanttItem *gitem=(CGanttItem*)m_gantt_view->m_tree_view->m_tree.GetItemData(hItem);
			if(0!=gitem)  m_visible_items.Add(gitem);
			hItem = m_gantt_view->m_tree_view->m_tree.GetNextVisibleItem(hItem);
		}
	}

	
	for(i=0;i<m_visible_items.GetSize();i++)	
	{
		CGanttItem *gitem=m_visible_items[i];
		if(0==gitem) continue;
		height+=m_blockHeight;
		gitem->rect_plan.top=top+4;
		gitem->rect_plan.bottom=top+18;

		//выделение строки
		if(gitem->hTreeItem==hSelItem && mode!=APL_MODE_SAVE)
		{
			int x1=max(rcClient.Width(),GetColumnsWidth());
			dc.FillSolidRect(0,top,x1,height-top,crSelectFill);
			dc.SelectObject(&border_select_pen);
			dc.MoveTo(0,top);
			dc.LineTo(x1,top);
			dc.MoveTo(0,height);
			dc.LineTo(x1,height);
		}
		top+=m_blockHeight;
	}

	//Теперь рисуем
	for(i=0;i<m_visible_items.GetSize();i++)
	{
		CGanttItem &item=*m_visible_items[i];

		//плановые даты 
		gantt_rect=item.rect_plan;
		if(mode==APL_MODE_SAVE) 
		{
			//вывод id проекта
			RECT id_rect=gantt_rect;
			id_rect.right=id_rect.left-4;
			id_rect.left=0;
			dc.SetTextColor(RGB(0,0,0));
			dc.SetBkColor(RGB(255,255,255));
			dc.SelectObject( pSmallFont );
			dc.DrawText(item.id, &id_rect,DT_RIGHT);
		}

		COLORREF newcolor=item.color;
		if(prev_color!=newcolor && m_bShowMultipleColors)
		{
			if(variable_brush_prj.m_hObject!=0) variable_brush_prj.DeleteObject();
			if(variable_brush_procent.m_hObject!=0) variable_brush_procent.DeleteObject();
			variable_brush_prj.CreateSolidBrush(aplColor_GetHilightColor(newcolor,60));
			COLORREF color1=newcolor;
			variable_brush_procent.CreateSolidBrush(color1);
			prev_color=newcolor;
		}

		if(item.pl_date_begin==item.pl_date_end)
		{
			// реперная точка
			int y1=(gantt_rect.top+gantt_rect.bottom)/2;
			POINT apoints[5];
			apoints[0].x=gantt_rect.left+7; apoints[0].y=gantt_rect.top;
			apoints[1].x=apoints[0].x-7;	apoints[1].y=y1;
			apoints[2].x=apoints[0].x;		apoints[2].y=gantt_rect.bottom;
			apoints[3].x=apoints[0].x+7;   apoints[3].y=y1;
			apoints[4]=apoints[0];

			dc.SelectObject(&border_pen);
			dc.SelectObject(&variable_brush_prj);
			dc.Polygon(apoints,5);

			item.rect_plan.left=apoints[1].x;
			item.rect_plan.right=apoints[3].x;
		}
		else
		{
			// нормальный проект
			dc.FillRect (gantt_rect, &variable_brush_prj);

			//процент выполнения
			int percentage=int(item.percentage);
			if(percentage>100) percentage=100;
			if(percentage>0)
			{
				//int width=int((gantt_rect.Width()*m_items[i].percentage)/100);
				int width=int((gantt_rect.Width()*percentage)/100);
				persentage_rect.left=gantt_rect.left;
				persentage_rect.top=gantt_rect.top;
				persentage_rect.bottom=gantt_rect.bottom;
				persentage_rect.right=persentage_rect.left+width;
				COLORREF oldBackColor=dc.SetBkColor(gantt_color);
				if(!m_bShowMultipleColors)	dc.FillRect(persentage_rect,&persentage_brush);
				else dc.FillRect(persentage_rect,&variable_brush_procent);
				dc.SetBkColor(oldBackColor);
			}

			// обводка плана
			dc.SelectObject(&border_pen);
			dc.Draw3dRect(gantt_rect,crSelect,crSelect);

			if(item.instMyLock!=0)
			{
				CRect r1=gantt_rect;
				r1.DeflateRect(CSize(1,1));
				dc.Draw3dRect(r1,RGB(255,0,0),RGB(255,0,0));
			}
		}

		GetActualRect(item,actual_rect,top,height, &xPrognoz);
		int yc=(item.rect_plan.top+item.rect_plan.bottom)/2;

		//фактические даты 
		if(m_gantt_view->m_bShowFact)
		{
			if(item.act_date_end.GetStatus()==COleDateTime::valid) //закончена
			{
				dc.SelectObject(&actual_ended_pen);
				dc.MoveTo(actual_rect.left+1,yc);
				dc.LineTo(actual_rect.right-2,yc);
			}
			else if(item.act_date_begin.GetStatus()==COleDateTime::valid) // начата, но не закончена
			{
				ganttDrawArrow(actual_rect.left,xPrognoz-3,-1,yc,6,dc,&actual_pen_arrow,&actual_working_prognoz_brush);

				if( (xPrognoz>actual_rect.left) && (xPrognoz<actual_rect.right))
				{
					if(actual_rect.left>(item.rect_plan.right+10))
					{
						dc.SelectObject(&actual_working_toend_pen);
						dc.MoveTo(actual_rect.left-5,yc);
						dc.LineTo(item.rect_plan.right+5,yc);
					}
				}
				else
				{
					dc.SelectObject(&actual_working_toend_pen);
					dc.MoveTo(actual_rect.left,yc);
					dc.LineTo(actual_rect.right-1,yc);
				}
			}
			else if(item.act_date_end_prognoz.GetStatus()==COleDateTime::valid) //не начата, но есть прогноз
			{
				// если нет плановых дат, то никакого прогнозирования
				if(m_gantt_view->m_bShowPrognoz && item.pl_date_end.GetStatus()==COleDateTime::valid)
				{
					int x_start=xPrognoz;
					if(item.act_date_begin_prognoz.GetStatus()==COleDateTime::valid)
					{
						x_start=Date2Pos(item.act_date_begin_prognoz);
					}
					else
					{
						if((item.pl_date_end.GetStatus()==COleDateTime::valid)&&(item.pl_date_begin.GetStatus()==COleDateTime::valid))
						{
							COleDateTimeSpan dts=item.pl_date_end-item.pl_date_begin;
							if(dts.GetStatus()==COleDateTimeSpan::valid) 
							{
								COleDateTime dt_s=item.act_date_end_prognoz-dts;
								x_start=Date2Pos(dt_s);
							}
						}
					}
					int left_ogr_no_draw=item.rect_plan.left+5;
					if(x_start>(item.rect_plan.right))
					{
						dc.SelectObject(&prognoz_pen);
						dc.MoveTo(item.rect_plan.right,yc);			
						dc.LineTo(x_start-2,yc);
					}
					else if(xPrognoz<(item.rect_plan.left))
					{
						dc.SelectObject(&prognoz_pen);
						dc.MoveTo(item.rect_plan.left,yc);			
						dc.LineTo(xPrognoz,yc);
						left_ogr_no_draw=x_start-1;
					}
					ganttDrawArrow(x_start,xPrognoz-3,left_ogr_no_draw,yc,6,dc,&prognoz_arrow_pen,&variable_brush_procent);

					if(0!=item.prev_progn_item) //линию к предыдущему
					{
						int x1=Date2Pos(item.prev_progn_item->act_date_end_prognoz);
						if(x1>0)
						{
							int y1=(item.prev_progn_item->rect_plan.top+item.prev_progn_item->rect_plan.bottom)/2;
							if(y1<=0) y1=m_headerHeight;
							dc.SelectObject(&prognoz_prev_pen);
							int d=2;
							if(y1>yc) d=-2;
							dc.MoveTo(x1-2,y1);	
							dc.LineTo(x_start,y1+d);
							dc.LineTo(x_start,yc);
						}
					}
					if(0!=item.first_progn_sub_item) //линию к первому подпроекту (всегда вниз)
					{
						int x1=Date2Pos(item.first_progn_sub_item->act_date_begin_prognoz);
						int y1=(item.first_progn_sub_item->rect_plan.top+item.first_progn_sub_item->rect_plan.bottom)/2;
						if(y1<=0) y1=rcClient.bottom;
						dc.SelectObject(&prognoz_prev_pen);
						dc.MoveTo(x1,y1);	
						dc.LineTo(x1,yc+2);
					}
					if(0!=item.last_progn_sub_item) //линию к последнему подпроекту (всегда вниз)
					{
						int x1=Date2Pos(item.last_progn_sub_item->act_date_end_prognoz)-2;
						int y1=(item.last_progn_sub_item->rect_plan.top+item.last_progn_sub_item->rect_plan.bottom)/2;
						if(y1<=0) y1=rcClient.bottom;
						dc.SelectObject(&prognoz_prev_pen);
						dc.MoveTo(x1,y1);	
						dc.LineTo(x1,yc);
					}
				}
			}

			// концовки
			if(item.act_date_begin.GetStatus()==COleDateTime::valid)
			{
				dc.SelectObject(&actual_end_pen);
				dc.MoveTo(actual_rect.left,gantt_rect.top);
				dc.LineTo(actual_rect.left,gantt_rect.bottom);
			}
			if(item.act_date_end.GetStatus()==COleDateTime::valid)
			{
				dc.SelectObject(&actual_end_pen);
				dc.MoveTo(actual_rect.right,gantt_rect.top);
				dc.LineTo(actual_rect.right,gantt_rect.bottom);
			}

		}

		// обводка родителей
		if(item.sub_items_count>0) 
		{
			//dc.SelectObject(&gantt_border_brush);
			//dc.FrameRect(gantt_rect,&gantt_border_brush);
			group_rect=item.rect_plan;
			group_rect.InflateRect(1,1);
			dc.FrameRect(&group_rect, &gantt_border_brush);
		}

		//отрисовка крестиков, показывающих не заданные даты
		if(item.pl_date_begin.GetStatus()!=COleDateTime::valid)
		{
			dc.SelectObject(&red_pen);
			dc.MoveTo(gantt_rect.left+2,gantt_rect.top+2);
			dc.LineTo(gantt_rect.left+9,gantt_rect.bottom-3);
			dc.MoveTo(gantt_rect.left+9,gantt_rect.top+2);
			dc.LineTo(gantt_rect.left+2,gantt_rect.bottom-3);
		}
		if(item.pl_date_end.GetStatus()!=COleDateTime::valid)
		{
			dc.SelectObject(&red_pen);
			dc.MoveTo(gantt_rect.right-2,gantt_rect.top+2);
			dc.LineTo(gantt_rect.right-9,gantt_rect.bottom-3);
			dc.MoveTo(gantt_rect.right-9,gantt_rect.top+2);
			dc.LineTo(gantt_rect.right-2,gantt_rect.bottom-3);
		}
	}
	
	//отрисовка линий к нижнему из входящих в проект
	height=m_headerHeight;
	top=m_headerHeight+1;
	dc.SelectObject(&black_pen);
	for(i=0;i<m_visible_items.GetSize();i++)
	{
		CGanttItem &item=*(m_visible_items[i]);
		height+=m_blockHeight;

		if(item.sub_items_count>0)
		{
			int l_left=item.rect_plan.left-1;
			int l_right=item.rect_plan.right;
			int l_top=item.rect_plan.bottom;
			int l_bottom=height+(m_blockHeight*item.sub_items_count)-2;

			dc.MoveTo(l_left,	l_top);
			dc.LineTo(l_left,	l_bottom);
			dc.LineTo(l_left+4,	l_bottom);
			dc.MoveTo(l_right,	l_top);
			dc.LineTo(l_right,	l_bottom);
			dc.LineTo(l_right-4,l_bottom);
		}
		top+=m_blockHeight;
	}
		
	// отрисовка связей проектов
	if(m_gantt_view->m_bShowRelations)
	{
		CPen relation_pen(PS_SOLID|PS_JOIN_BEVEL,1,RGB(0,0,223));
		CBrush relation_brush; relation_brush.CreateSolidBrush(RGB(0,0,223));
		dc.SelectObject(&relation_pen);
		dc.SelectObject(&relation_brush);

		POINT points[20];

		// Определяем счетчик для верхнего и нижнего видимого
		int top_counter=-1;
		int bottom_counter=-1;

		if(m_visible_items.GetSize()>0)
		{
			top_counter=m_visible_items[0]->pos;
			bottom_counter=m_visible_items[m_visible_items.GetSize()-1]->pos;
		}

		for(i=0;i<m_items_rels.GetSize();i++)
		{
			CGanttItem *prev=m_items_rels[i].prev;
			CGanttItem *next=m_items_rels[i].next;
			if(0==prev || 0== next) continue;

			if(prev->pos<top_counter && next->pos<top_counter) continue; //оба выше
			if(prev->pos>bottom_counter && next->pos>bottom_counter) continue; //оба ниже
			
			RECT *r_prev =&prev->rect_plan;
			RECT *r_next =&next->rect_plan;

			int y_p=(r_prev->top+r_prev->bottom)/2;
			int y_n=(r_next->top+r_next->bottom)/2;

			bool bPrevTopVisible=true;
			bool bNextTopVisible=true;

			if(0==y_p) //невидим
			{
				if(prev->pos>top_counter) y_p=rcClient.bottom+10;
				else
				{
					y_p=m_headerHeight;
					bPrevTopVisible=false;
				}
				//prev->rect_plan.left=Date2Pos(prev->pl_date_begin);	
				//prev->rect_plan.right=Date2Pos(prev->pl_date_end);
				prev->rect_plan.top=y_p;
				prev->rect_plan.bottom=y_p;
				
			}

			if(0==y_n) //невидим
			{
				if(next->pos>top_counter) y_n=rcClient.bottom+10;
				else
				{
					y_n=m_headerHeight;
					bNextTopVisible=false;
				}
				//next->rect_plan.left=Date2Pos(next->pl_date_begin);
				//next->rect_plan.right=Date2Pos(next->pl_date_end);
				next->rect_plan.top=y_n;
				next->rect_plan.bottom=y_n;
			}

			int x1=r_next->left-10;

			int k=0;
			int dx=2,dy=2;
			if(y_p>y_n) dy*=-1;
			//dc.MoveTo(r_prev->right,y_p);
			points[k].x=r_prev->right; points[k].y=y_p; k++;

			if((r_prev->right<=r_next->left)) // вперед
			{
				int y1;
				int dir;
				if(r_prev->top < r_next->top) {y1=r_next->top-1; dir=1;} // предыдущее сверху
				else {y1=r_next->bottom; dir=-1;}
				int x1=r_prev->right+2+dx;
				if(x1<(r_next->left+4)) x1=r_next->left+4;

				if(bPrevTopVisible)
				{
					points[k].x=x1-2; points[k].y=y_p; k++;
					points[k].x=x1; points[k].y=y_p+(dx*dir); k++;
				}
				else
				{
					k=0;
					points[k].x=x1;		points[k].y=y_p; k++;	
				}

				if(bNextTopVisible)
				{
					points[k].x=x1; points[k].y=y1; k++;	
				}
				else 
				{
					points[k].x=x1; points[k].y=y_n; k++;	
				}

				dc.Polyline(points,k);

				if(bNextTopVisible)
				{
					POINT apoints[4];
					apoints[0]=points[k-1];
					apoints[1].x=apoints[0].x-4;  apoints[1].y=apoints[0].y-(4*dir);
					apoints[2].x=apoints[0].x+4;  apoints[2].y=apoints[1].y;
					apoints[3]=apoints[0];
					dc.Polygon(apoints,4);
				}
			}
			else // назад
			{
				// зигзюг назад
				int x0=r_prev->right+3;
				int y1;
				if(r_prev->top < r_next->top) y1=r_next->top-4; // предыдущее сверху
				else y1=r_prev->top-3;

				if(bPrevTopVisible)
				{
					points[k].x=x0-dx;	points[k].y=y_p;	k++;
					points[k].x=x0;		points[k].y=y_p+dy; k++;	
				}
				else 
				{
					k=0;
					points[k].x=x0;		points[k].y=y_p; k++;	
				}
				points[k].x=x0;		points[k].y=y1-dy;  k++;
				points[k].x=x0-dx;	points[k].y=y1;		k++;
				points[k].x=x1+dx;	points[k].y=y1;		k++;
				points[k].x=x1;		points[k].y=y1+dy;  k++;
				points[k].x=x1;		points[k].y=y_n-dy; k++;
				
				if(bNextTopVisible)
				{
					points[k].x=x1+dx; points[k].y=y_n; k++;
					points[k].x=r_next->left; points[k].y=y_n; k++;
				}
				dc.Polyline(points,k);

				if(bNextTopVisible)
				{
					POINT apoints[4];
					apoints[0].x=r_next->left-1;  apoints[0].y=y_n;
					apoints[1].x=apoints[0].x-4;  apoints[1].y=apoints[0].y-4;
					apoints[2].x=apoints[1].x;  apoints[2].y=apoints[0].y+4;
					apoints[3]=apoints[0];
					dc.Polygon(apoints,4);
				}
			}
		}
	}

	dc.SelectObject(&oldBrush);
	dc.SelectObject(&oldPen);
	dc.SelectObject(oldFont);


}

bool CGanttCtrl::Paint2DC(CDC &memDC, CBitmap &bm)
{
	CPaintDC pDC(this); // device context for painting
	if(!memDC.CreateCompatibleDC(&pDC)) return false;
	int old_offset=m_nOffset;
	m_nOffset=0;

	int cx=m_pixelsInDay*m_col_days+4;
	int cy=m_headerHeight+m_gantt_view->m_items.GetSize()*m_blockHeight;

	int tree_width=0;
	int i;
	for(i=0;i<m_gantt_view->m_tree_view->m_tree.GetColumnsNum();i++)
	{
		tree_width += m_gantt_view->m_tree_view->m_tree.GetColumnWidth(i);
	}
	//tree_width+=1;
	cx+=tree_width;
	bm.CreateCompatibleBitmap(&pDC,cx,cy);
	// Это замена FillSolidRect, т.к. он тормозит
	{
		BITMAP bitmap;
		bm.GetBitmap(&bitmap);
		DWORD dwcount=bitmap.bmHeight * bitmap.bmWidthBytes;
		int i,k=(int)((dwcount+4)/4);
		long *buf=new long[k];
		for(i=0;i<k;i++) buf[i]=0xffffffff;
		bm.SetBitmapBits(dwcount,buf);
		delete buf;
	}
	CBitmap *old = memDC.SelectObject(&bm);
	memDC.SetViewportOrg(tree_width,0);
	PaintDiagram(memDC,APL_MODE_SAVE);
	memDC.SetViewportOrg(0,19);
	m_gantt_view->m_tree_view->m_tree.PaintAll(memDC,cx,cy);


	m_nOffset=old_offset;
	//m_pixelsInDay=old_m_pixelsInDay;
	//m_nColumnsWidth=old_m_nColumnsWidth;
	return true;
}

bool CGanttCtrl::ExportDiagramBmp(CString &bmp_f_name)
{
	CDC memDC;
	CBitmap bmp;
	if(!Paint2DC(memDC,bmp)) return false;

	bool result=SaveBitmapAs(bmp,bmp_f_name);
	//memDC.SelectObject(old);
	memDC.DeleteDC();
	return result;
}

void CGanttCtrl::OnPaint()
{
	CPaintDC dc(this); // device context for painting
	if(!IsWindowVisible( ))
	{
		CWnd::DefWindowProc( WM_PAINT, (WPARAM)dc.m_hDC, 0 );
		return;
	}

	bool bDrawed=false;
	CDC MemDC;

	if(MemDC.CreateCompatibleDC(&dc))
	{
		CBitmap bm;
		CBitmap *pOldBm = NULL;
		CRect rect;
		GetClientRect(&rect);
		MemDC.SetMapMode(dc.GetMapMode());
		if(bm.CreateCompatibleBitmap(&dc, rect.right, rect.bottom))
		{
			// Это замена FillSolidRect, т.к. он тормозит
			BITMAP bitmap;
			bm.GetBitmap(&bitmap);
			DWORD dwcount=bitmap.bmHeight * bitmap.bmWidthBytes;
			int i,k=(int)((dwcount+4)/4);
			long *buf=new long[k];
			for(i=0;i<k;i++) buf[i]=0xffffffff;
			bm.SetBitmapBits(dwcount,buf);
			delete buf;
			pOldBm = MemDC.SelectObject(&bm);
			//MemDC.FillSolidRect(0, 0, rect.right, rect.bottom, RGB(255,255,255));
			PaintDiagram(MemDC,APL_MODE_EDIT);
			dc.BitBlt(0, 0, rect.right, rect.bottom, &MemDC, -m_nOffset, 0, SRCCOPY);
			bDrawed=true;
		}

		MemDC.SelectObject(pOldBm);
		MemDC.DeleteDC();	
	}

	if(!bDrawed)
	{
		PaintDiagram(dc,APL_MODE_EDIT);
	}

}

void CGanttCtrl::AutoResizeDiagram(bool bReduce,bool bInvalidate)
{
	COleDateTimeSpan dt_span;
	dt_span=m_max_date-m_min_date;
	if(dt_span.GetStatus()==COleDateTimeSpan::valid) 
	{
		if(dt_span.GetDays()<=0) return;
	} //else return;


	CRect rcClient;
	GetClientRect(&rcClient);
	double koef=double(rcClient.Width())/double(GetColumnsWidth());
	if(GetColumnsWidth()) 
	{
		if((rcClient.Width()>GetColumnsWidth()) || bReduce)
		{
			m_pixelsInDay=int(m_pixelsInDay*koef);
			CheckSetPixelsInDay(m_pixelsInDay);
			RecalcColumnsWidth();
			if(bInvalidate) Invalidate();
		}
	}
}

void CGanttCtrl::CheckSetPixelsInDay(int pixelsInDay)
{
	if(m_view_mode==APL_MODE_YEARS)
	{
		if(pixelsInDay<1) pixelsInDay=1;
	}
	else if(m_view_mode==APL_MODE_MONTHS) 
	{
		if(pixelsInDay<4) pixelsInDay=4;
	}
	else if(m_view_mode==APL_MODE_WEEKS) 
	{
		if(pixelsInDay<18) pixelsInDay=18;
	}
	m_pixelsInDay=pixelsInDay;
}

bool CGanttCtrl::SetPixelsInDay(int pixelsInDay)
{
	CheckSetPixelsInDay(pixelsInDay);
	RecalcColumnsWidth();
	((CGanttView*)GetParent())->ResetScrollBar();
	if(((CGanttView*)GetParent())->m_bShrinkToFit) AutoResizeDiagram(false,false);
	((CGanttView*)GetParent())->Invalidate();
	return true;
}

int  CGanttCtrl::Date2Pos(COleDateTime &date_begin)
{
	if(date_begin.GetStatus()!=COleDateTime::valid) return 0;
	COleDateTimeSpan dt_span1=date_begin-m_min_date;
	if(dt_span1.GetStatus()!=COleDateTimeSpan::valid)  return 0;
	return (int)(m_pixelsInDay*dt_span1.m_span+2);
}

int CGanttCtrl::GetDlitDays(COleDateTime &date_begin, COleDateTime &date_end)
{
	COleDateTime dt_begin,dt_end;

	if(date_begin.GetStatus()==COleDateTime::valid) 
		dt_begin.SetDateTime(date_begin.GetYear(),date_begin.GetMonth(),date_begin.GetDay(),0,0,0);
	else 
		dt_begin.SetDateTime(m_min_date.GetYear(),m_min_date.GetMonth(),m_min_date.GetDay(),0,0,0);
	
	if(date_end.GetStatus()==COleDateTime::valid) 
	{
		dt_end.SetDateTime(date_end.GetYear(),date_end.GetMonth(),date_end.GetDay(),0,0,0);
	}
	else 
		dt_end.SetDateTime(m_max_date.GetYear(),m_max_date.GetMonth(),m_max_date.GetDay(),0,0,0);
	
	COleDateTimeSpan dt_span=dt_end-dt_begin;
	int dlit_days=0;
	if(dt_span.GetStatus()==COleDateTimeSpan::valid) dlit_days=dt_span.GetDays()+1;
	return dlit_days;
}

bool CGanttCtrl::PointToVal(CPoint *point, CGanttItem **gItem, HTREEITEM &hItem,CaplInstance **inst, bool bFullRow)
{
	int i;
	hItem=0;
	if(0!=gItem) *gItem =0;
	if(0!=inst)*inst=0;

	int p_y=point->y;
	int p_x=point->x-m_nOffset;


	for(i=0;i<m_visible_items.GetSize();i++)
	{
		CGanttItem *item=m_visible_items[i];
		if(p_y > (item->rect_plan.bottom+2)) continue;
		if(p_y < (item->rect_plan.top-1))    continue;
		if(!bFullRow)
		{
			if(p_x > item->rect_plan.right) continue;
			if(p_x < item->rect_plan.left)  continue;
		}
		if(0!=gItem) *gItem =item;
		hItem=item->hTreeItem;
		if(inst!=0) *inst=item->prj;
		return true;
	}

	return false;
}

void CGanttCtrl::OnLButtonDblClk(UINT nFlags, CPoint point) 
{
	CaplInstance *sel_project=0;
	HTREEITEM hItem;
	if(!PointToVal(&point,0,hItem,&sel_project)) return;
	if(!sel_project) return;
	if(!hItem) return;
	if(!m_project_mgr) return;
	HideToolTip();
	if(m_project_mgr->ShowProjectProperties(sel_project))
	{
		CalcMaxMinDates();
		if(m_dlg)
		{
			//m_dlg->RefreshItem(hItem);
			m_dlg->RefreshAllItems();
			((CShowGanttDlg*)m_dlg)->UpdateGanttView(true,true);
		}
	}	
	CWnd::OnLButtonDblClk(nFlags, point);
}

void CGanttCtrl::OnLButtonDown(UINT nFlags, CPoint point) 
{	
	HideToolTip();
	CaplInstance *sel_project=0;
	CGanttItem *gitem=0;
	HTREEITEM hItem;
	if(false==PointToVal(&point,&gitem,hItem,&sel_project)) return;
	//if(!sel_project) return;
	if(!hItem) return;
	((CGanttView*)GetParent())->m_tree_view->m_tree.SelectItem(hItem);
	((CGanttView*)GetParent())->Update(false);


	if(gitem!=0)
	{
		m_grag_item=gitem;
		m_last_drag_point=m_first_drag_point=point;

		if(m_grag_item_mode<0)m_hCursor=AfxGetApp()->LoadCursor(IDC_TO_LEFT );
		else if(m_grag_item_mode>0)m_hCursor=AfxGetApp()->LoadCursor(IDC_TO_RIGHT );
		else m_hCursor=AfxGetApp()->LoadCursor(IDC_CURS_MOVE );
		
		SetCursor(m_hCursor);
	}
	
	CWnd::OnLButtonDown(nFlags, point);
}

void CGanttCtrl::OnLButtonUp(UINT nFlags, CPoint point)
{
	if(0!=m_grag_item)
	{
		CPoint new_point=point;
		HTREEITEM hItem;
		CGanttItem *gItem=0;

		if(point.y>=m_grag_item->rect_plan.top && point.y<=m_grag_item->rect_plan.bottom) // в пределах 1-ой строки
		{
			CString buf,name1,sDateOld,sDateNew;
			int dx=(point.x-m_first_drag_point.x)/m_pixelsInDay;
			if(dx<=-1 || dx>=1) // перемещение 1го дня//{ AfxMessageBox(APL_T("Перемещение менее 1 дня."),MB_ICONSTOP|MB_OK);
			{
				COleDateTimeSpan odts(dx);
				COleDateTime odtNewBegin, odtNewEnd;
				odtNewBegin.SetStatus(COleDateTime::null);
				odtNewEnd.SetStatus(COleDateTime::null);

				if(m_grag_item_mode<=0)
				{
					odtNewBegin=m_grag_item->pl_date_begin+odts;
					if(odtNewBegin>=m_grag_item->pl_date_end && m_grag_item_mode!=0) 
					{
						AfxMessageBox(APL_T("Начало не может быть позднее завершения !"),MB_OK|MB_ICONSTOP); 
						m_grag_item=0;
						m_hCursor=0;
						bIsLine=false;
						bIsRect=false;
						Invalidate();
						return ;
					}
				}
				if(m_grag_item_mode>=0)
				{
					odtNewEnd=m_grag_item->pl_date_end+odts;
					if(odtNewEnd<=m_grag_item->pl_date_begin && m_grag_item_mode!=0) 
					{
						AfxMessageBox(APL_T("Завершение не может быть раньше начала !"),MB_OK|MB_ICONSTOP); 
						m_grag_item=0;
						m_hCursor=0;
						bIsLine=false;
						bIsRect=false;
						Invalidate();
						return ;
					}
				}
				/*else
				{
					if(m_grag_item->pl_date_begin.GetStatus()!=COleDateTime::valid) AfxMessageBox(APL_T("Операция невозможна! Сначала задайте дату начала!"),MB_ICONSTOP|MB_OK);
					else
					{
						COleDateTimeSpan odts(dx);
						COleDateTime odt=m_grag_item->pl_date_begin+odts;
						if(m_project_mgr->SetProjectPlanedBeginDate(m_grag_item->prj,odt))
						{
							m_gantt_view->UpdateGanttView(true,true);
						}
					}
				}*/
				if(m_project_mgr->SetProjectNewPlanedDate(m_grag_item->prj,odtNewBegin,odtNewEnd))
				{
					m_gantt_view->UpdateGanttView(true,true);
				}		
			}
		}
		else if(PointToVal(&new_point,&gItem,hItem,0,false))
		{
			if(gItem!=0 && gItem!=m_grag_item)
			{
				CaplInstance *inst=m_project_mgr->CreateProjectSequence(m_grag_item->prj,gItem->prj);
				if(0!=inst)
				{
					m_gantt_view->UpdateGanttView(true,true);
				}
			}
		}
		Invalidate();
	}
	m_grag_item=0;
	m_hCursor=0;
	bIsLine=false;
	bIsRect=false;

	CWnd::OnLButtonUp(nFlags, point);
}

BOOL CGanttCtrl::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message)
{
	if(0!=m_grag_item && 0!=m_hCursor)
	{
		::SetCursor(m_hCursor);
		return TRUE;
	}
	return CWnd::OnSetCursor(pWnd, nHitTest, message);
}

void CGanttCtrl::OnMouseMove(UINT nFlags, CPoint point) 
{
	m_ToolTip.Hide();
	CaplInstance *sel_project=0;
	HTREEITEM hItem;
	CGanttItem *gItem=0;
	CPoint new_point=point;
	//ClientToScreen(&new_point); 

	if(bIsLine || bIsRect) // стираем линию
	{
		CDC *dc=GetDC(); 
		if(dc)
		{
			CPen pen(PS_SOLID,1,RGB(0,0,128));
			CPen *oldPen=dc->SelectObject(&pen);
			dc->SetROP2(R2_NOTXORPEN);
			if(bIsLine)
			{
				dc->MoveTo(m_first_drag_point);
				dc->LineTo(m_last_drag_point);	
			}
			if(bIsRect) dc->Rectangle(&m_prevRect);

			dc->SelectObject(oldPen);
		}
		bIsLine=false;
		bIsRect=false;
	}
	CWnd::OnMouseMove(nFlags,point); 

	if(0!=m_grag_item)
	{
		bool bShowToolTip=false;
		CDC *dc=GetDC(); 
		if(dc)
		{
			CPen pen(PS_SOLID,1,RGB(0,0,128));
			CPen *oldPen=dc->SelectObject(&pen);
			dc->SetROP2(R2_NOTXORPEN);

			if(point.y>=m_grag_item->rect_plan.top && point.y<=m_grag_item->rect_plan.bottom)
			{
				m_prevRect=m_grag_item->rect_plan;
				m_prevRect.top-=1;
				m_prevRect.bottom+=1;
				int dx=point.x-m_first_drag_point.x;
				if(m_grag_item_mode<0)
				{
					m_hCursor=AfxGetApp()->LoadCursor(IDC_TO_LEFT );
					m_prevRect.left+=(dx+m_nOffset);
					m_prevRect.right+=m_nOffset;
				}
				else if(m_grag_item_mode>0)
				{
					m_hCursor=AfxGetApp()->LoadCursor(IDC_TO_RIGHT );
					m_prevRect.left+=m_nOffset;
					m_prevRect.right+=(dx+m_nOffset);
				}
				else
				{
					m_hCursor=AfxGetApp()->LoadCursor(IDC_CURS_MOVE );
					m_prevRect.left+=(dx+m_nOffset);
					m_prevRect.right+=(dx+m_nOffset);
				}
				if(m_prevRect.left<m_prevRect.right)
				{
					dc->Rectangle(&m_prevRect);
					bIsRect=true;
				}
			}
			else
			{
				m_hCursor=AfxGetApp()->LoadCursor(IDC_CUR_REL );
				dc->MoveTo(m_first_drag_point);
				dc->LineTo(point);
				bIsLine=true;
				bShowToolTip=true;
			}
			dc->SelectObject(oldPen);
		}
		m_last_drag_point=point;
		if(bShowToolTip)DisplayToolTip(point,*m_grag_item);
		return;
	}

	PointToVal(&new_point,&gItem,hItem,&sel_project,true);
	if(0==gItem) return;

	int p_x=new_point.x-m_nOffset;

	if(p_x > gItem->rect_plan.left && p_x <(gItem->rect_plan.left+4))
	{
		m_hCursor=AfxGetApp()->LoadCursor(IDC_TO_LEFT );
		SetCursor(m_hCursor);
		m_grag_item_mode=-1;
	}
	else  if(p_x  < gItem->rect_plan.right && p_x >(gItem->rect_plan.right-4))
	{
		m_hCursor=AfxGetApp()->LoadCursor(IDC_TO_RIGHT );
		SetCursor(m_hCursor);
		m_grag_item_mode=1;
	}
	else m_grag_item_mode=0;
	/*else if(p_x  > gItem->rect_plan.left && p_x <gItem->rect_plan.right)
	{
		m_hCursor=AfxGetApp()->LoadCursor(IDC_CURS_MOVE );
		SetCursor(m_hCursor);
	}*/

	DisplayToolTip(point,*gItem);

	TRACKMOUSEEVENT		csTME;
	csTME.cbSize = sizeof(csTME);
	csTME.dwFlags = TME_LEAVE;
	csTME.hwndTrack = m_hWnd;
	::_TrackMouseEvent(&csTME);
}

void CGanttCtrl::DisplayToolTip(CPoint point,CGanttItem &gItem)
{
	CString buf;
	CString tooltip_text=APL_T("Проект: ");
	if(gItem.name!=_T("")) tooltip_text+=gItem.name+_T("\n");
	else tooltip_text+=gItem.id+_T("\n");
	tooltip_text+=_T("\n");
	if(gItem.pl_date_begin.GetStatus()==COleDateTime::valid || gItem.pl_date_end.GetStatus()==COleDateTime::valid)
	{
		tooltip_text+=APL_T("План: ");
		if(gItem.pl_date_begin.GetStatus()==COleDateTime::valid)	
		{
			buf=gItem.pl_date_begin.Format(_T("%d.%m.%Y  %H:%M"));
			tooltip_text+=APL_T("начало: ")+buf+_T("   ");
		}
		if(gItem.pl_date_end.GetStatus()==COleDateTime::valid)	
		{
			buf=gItem.pl_date_end.Format(_T("%d.%m.%Y  %H:%M"));
			tooltip_text+=APL_T("окончание: ")+buf;
		}
		tooltip_text+=_T("\n");
	}
	
	if(gItem.act_date_begin.GetStatus()==COleDateTime::valid || gItem.act_date_end.GetStatus()==COleDateTime::valid || gItem.act_date_end_prognoz.GetStatus()==COleDateTime::valid)
	{
		tooltip_text+=APL_T("Факт: ");
		if(gItem.act_date_begin.GetStatus()==COleDateTime::valid)	
		{
			buf=gItem.act_date_begin.Format(_T("%d.%m.%Y %H:%M"));
			tooltip_text+=APL_T("начало: ")+buf+_T("   ");
		}
		if(gItem.act_date_end.GetStatus()==COleDateTime::valid)	
		{
			buf=gItem.act_date_end.Format(_T("%d.%m.%Y %H:%M"));
			tooltip_text+=APL_T("окончание: ")+buf;
		}
		if(gItem.act_date_end_prognoz.GetStatus()==COleDateTime::valid)
		{
			buf=gItem.act_date_end_prognoz.Format(_T("%d.%m.%Y %H:%M"));
			tooltip_text+=APL_T("прогноз завершения: ")+buf;
		}
		tooltip_text+=_T("\n");
	}
	if(gItem.percentage)
	{
		buf.Format(APL_T("Выполнено: %g"),gItem.percentage);
		tooltip_text+=buf;
		tooltip_text+=_T("%\n");
	}
	
	CPoint pnt;
	pnt.x=point.x+10;
	pnt.y=point.y;
	ClientToScreen(&pnt);
	m_ToolTip.Show(pnt.x, pnt.y, tooltip_text,480);}

void CGanttCtrl::HideToolTip()
{
	m_ToolTip.Hide();
}

void CGanttCtrl::OnKillFocus(CWnd* pNewWnd) 
{
	CWnd::OnKillFocus(pNewWnd);
	HideToolTip();
}

void CGanttCtrl::OnDestroy() 
{
	HideToolTip();
	CWnd::OnDestroy();
}

LRESULT CGanttCtrl::OnMouseLeave(WPARAM wParam, LPARAM lParam)
{
	HideToolTip();
	return 1;
}


void CGanttCtrl::GetActualRect(CGanttItem &item,CRect &rect,int top,int height, int *xPosPrognoz)
{
	if(item.act_date_begin.GetStatus()==COleDateTime::valid) rect.left= Date2Pos(item.act_date_begin); else rect.left=2;
	if(item.act_date_end.GetStatus()  ==COleDateTime::valid) rect.right=Date2Pos(item.act_date_end);   else rect.right=m_nColumnsWidth-1;

	rect.top=top+4;
	rect.bottom=rect.top+13;

	if(0!=xPosPrognoz)
	{
		if(item.act_date_end_prognoz.GetStatus()!=COleDateTime::valid) *xPosPrognoz=0;
		else
		{
			*xPosPrognoz=Date2Pos(item.act_date_end_prognoz);
		}
	}
}


void CGanttCtrl::UpdateRelations()
{
	m_items_rels.RemoveAll();
	aplExtent ext_rel;
	m_api->m_data.GetEntityExtent(m_project_mgr->e_project_seg,ext_rel);
	if(ext_rel.GetSize()<1) return;	
	
	int i;	
	CaplMap prj_map;
	for(i=0;i<m_gantt_view->m_items.GetSize();i++)
	{
		CGanttItem *pitem=m_gantt_view->m_items.GetAt(i);
		if(0==pitem) continue;
		prj_map.Add((long)(pitem->prj),(long)pitem);
	}
	prj_map.SortIn();


	CaplInstance *inst;
	for(i=0;i<ext_rel.GetSize();i++)
	{
		inst=ext_rel[i];
		if(inst->GetType()==0) continue;

		CaplInstance *prev,*next;
		m_api->m_data.GetAttr(inst,m_project_mgr->a_project_seq_next,next);
		if(0==next) continue;
		m_api->m_data.GetAttr(inst,m_project_mgr->a_project_seq_prev,prev);
		if(0==prev) continue;
	
		CGanttItem *item_next=(CGanttItem *)prj_map.QGetPointerByIn((long)next);
		if((long)item_next<1)continue;
		CGanttItem *item_prev=(CGanttItem *)prj_map.QGetPointerByIn((long)prev);
		if((long)item_prev<1)continue;

		CGanttItemRel item_rel;
		item_rel.prev=item_prev;
		item_rel.next=item_next;
		m_items_rels.Add(item_rel);
	}

	// определение  prev_item_from_prognoz
	for(i=0;i<m_gantt_view->m_items.GetSize();i++)
	{
		CGanttItem *pitem=m_gantt_view->m_items.GetAt(i);
		if(0==pitem) continue;

		if(0!=pitem->prev_progn_prj) pitem->prev_progn_item=(CGanttItem *)prj_map.QGetPointerByIn((long)(pitem->prev_progn_prj));
		if(0!=pitem->first_progn_sub_prj) pitem->first_progn_sub_item=(CGanttItem *)prj_map.QGetPointerByIn((long)(pitem->first_progn_sub_prj));
		if(0!=pitem->last_progn_sub_prj) pitem->last_progn_sub_item=(CGanttItem *)prj_map.QGetPointerByIn((long)(pitem->last_progn_sub_prj));
		// если ==0 - значит этот проект не отображается
	}
}

BOOL CGanttCtrl::OnEraseBkgnd(CDC* pDC)
{
	return TRUE;
	//return CWnd::OnEraseBkgnd(pDC);
}



