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

#include "stdafx.h"
#include "WfGanttCtrl.h"
//#include "apl_api.h"
#include "WfGanttView.h"
#include <locale.h>
//#include "ximage.h"
#include "ReportDict.h"

#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,100,254);
COLORREF gantt_border_color=RGB(0,51,153);
COLORREF group_color=RGB(51,51,153);


BEGIN_MESSAGE_MAP(CWfGanttCtrl, 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)
END_MESSAGE_MAP()

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

CWfGanttCtrl::CWfGanttCtrl()
{
	m_max_date=_T("");
	m_min_date=_T("");
	m_max_calendar_date=_T("");
	m_min_calendar_date=_T("");
	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_dlg=0;
	m_view_mode=APL_MODE_MONTHS;

	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;
	

}

CWfGanttCtrl::~CWfGanttCtrl()
{

}


/*
int CWfGanttCtrl::InsertColumn( int nCol, const char *dateTime)
{
	if(!dateTime) return -1;
	COleDateTime dt;
	CString buf=dateTime;
	if(!aplString2Date(buf,dt)) return -1;
	if(dt.GetStatus()!=COleDateTime::valid) return -1; 

	m_wndHeader.m_dates.Add(dateTime);

	HD_ITEM hdi;
	hdi.mask = HDI_TEXT | HDI_FORMAT;
	int nFormat, nWidth; 
	if(m_wndHeader.m_format==0)	
	{
		buf =dt.Format(_T("%d.%m.%y"));
		hdi.pszText = (LPTSTR)(LPCTSTR)buf;
		nFormat=LVCFMT_LEFT;
		nWidth=50;
	}

	if(nWidth!=-1)
	{
		hdi.mask |= HDI_WIDTH;
		hdi.cxy = nWidth;
	}

	hdi.fmt = HDF_OWNERDRAW;

	if(nFormat == LVCFMT_RIGHT)
		hdi.fmt |= HDF_RIGHT;
	else
	if(nFormat == LVCFMT_CENTER)
		hdi.fmt |= HDF_CENTER;
	else
		hdi.fmt |= HDF_LEFT;

	int m_nReturn = m_wndHeader.InsertItem(nCol, &hdi);
	((CWfGanttView*)GetParent())->ResetScrollBar();

	RecalcColumnsWidth();
//	SetBkColor(m_wndColor);
	return m_nReturn;
}

void CWfGanttCtrl::DeleteAllColumns()
{
	int nCount = m_wndHeader.GetItemCount();

	// Delete all of the items.
	for (int i=0;i < nCount;i++)
	{
		m_wndHeader.DeleteItem(0);
	}
	m_wndHeader.m_dates.RemoveAll();
}
*/

CGanttItem::CGanttItem()
{
	id=_T("");
	name=_T("");
	itemData=0;
	hTreeItem=NULL;
	pl_date_begin=_T("");
	pl_date_end=_T("");
	act_date_begin=_T("");
	act_date_end=_T("");
	percentage=0;
	last_sub_item=-1;
	color=gantt_color;
}

CGanttItem* CWfGanttCtrl::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 CWfGanttCtrl::GetItemNum(CGanttItem &gItem)
{
	for(int i=0;i<m_items.GetSize();i++)
	{
		if(m_items[i].itemData==gItem.itemData) return i;
	}
	return -1;
}


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

void CWfGanttCtrl::RemoveAllItems()
{
	m_items.RemoveAll();
}

void CWfGanttCtrl::UpdateCalendar(bool resetScrollBar)
{
	CString old_max_date=m_max_date;
	CString 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) ((CWfGanttView*)GetParent())->ResetScrollBar();
	}
}

void CWfGanttCtrl::CalcMaxMinDates()
{
	if(!m_items.GetSize()) return;

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

	int i;
	for(i=0;i<m_items.GetSize();i++)
	{
		if(m_items[i].pl_date_begin!=_T(""))
		{
			if(m_items[i].pl_date_begin>m_max_date) m_max_date=m_items[i].pl_date_begin;
			if(m_items[i].pl_date_begin<m_min_date) m_min_date=m_items[i].pl_date_begin;
		}

		if(m_items[i].pl_date_end!=_T(""))
		{
			if(m_items[i].pl_date_end>m_max_date) m_max_date=m_items[i].pl_date_end;
			if(m_items[i].pl_date_end<m_min_date) m_min_date=m_items[i].pl_date_end;
		}

		if(m_items[i].act_date_begin!=_T(""))
		{
			if(m_items[i].act_date_begin>m_max_date) m_max_date=m_items[i].act_date_begin;
			if(m_items[i].act_date_begin<m_min_date) m_min_date=m_items[i].act_date_begin;
		}
		if(m_items[i].act_date_end!=_T(""))
		{
			if(m_items[i].act_date_end>m_max_date) m_max_date=m_items[i].act_date_end;
			if(m_items[i].act_date_end<m_min_date) m_min_date=m_items[i].act_date_end;
		}

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

	aplString2Date(m_max_date,m_max_dt);

	if(m_max_dt.GetStatus()!=COleDateTime::valid)
	{
		CString buf;
		buf=m_max_date.Left(6);
		buf+=_T("01000000");
		aplString2Date(buf,m_max_dt);
	}

	aplString2Date(m_min_date,m_min_dt);

	COleDateTimeSpan dts(30);
	m_max_dt+=dts;

	m_min_calendar_dt.SetDateTime(m_min_dt.GetYear(),m_min_dt.GetMonth(),1,0,0,0);
	m_max_calendar_dt.SetDateTime(m_max_dt.GetYear(),m_max_dt.GetMonth(),1,0,0,0);


	/* Не совсем рабочий код Бороздина
	m_max_date=m_items[0].pl_date_end;
	COleDateTime dt;
	int i;
	for(i=0;i<m_items.GetSize();i++)
	{
		if(m_items[i].pl_date_begin>m_max_date && m_items[i].pl_date_begin!=_T(""))
			m_max_date=m_items[i].pl_date_begin;
		if(m_items[i].pl_date_end>m_max_date && m_items[i].pl_date_end!=_T(""))
			m_max_date=m_items[i].pl_date_end;
		if(m_items[i].act_date_begin>m_max_date && m_items[i].act_date_begin!=_T(""))
			m_max_date=m_items[i].act_date_begin;
		if(m_items[i].act_date_end>m_max_date && m_items[i].act_date_end!=_T(""))
			m_max_date=m_items[i].act_date_end;
	}
	aplString2Date(m_max_date,dt);
	if(dt.GetStatus()==COleDateTime::valid) 
	{
		m_max_dt.SetDateTime(dt.GetYear(),dt.GetMonth(),dt.GetDay(),0,0,0);
		COleDateTimeSpan dt_span0;
		dt_span0.SetDateTimeSpan(1,0,0,0);
		if(m_max_dt.GetMonth()==12) dt.SetDateTime(m_max_dt.GetYear()+1,1,1,0,0,0);
		else dt.SetDateTime(m_max_dt.GetYear(),m_max_dt.GetMonth()+1,1,0,0,0);
		dt=dt-dt_span0;
		m_max_calendar_dt.SetDateTime(dt.GetYear(),dt.GetMonth(),dt.GetDay(),0,0,0);
		aplDate2String(m_max_calendar_dt,m_max_calendar_date);
	}
	m_min_date=m_max_date;
	for(i=0;i<m_items.GetSize();i++)
	{
		if(m_items[i].pl_date_begin<m_min_date && m_items[i].pl_date_begin!=_T(""))
			m_min_date=m_items[i].pl_date_begin;
		if(m_items[i].pl_date_end<m_min_date && m_items[i].pl_date_end!=_T(""))
			m_min_date=m_items[i].pl_date_end;
		if(m_items[i].act_date_begin<m_min_date && m_items[i].act_date_begin!=_T(""))
			m_min_date=m_items[i].act_date_begin;
		if(m_items[i].act_date_end<m_min_date && m_items[i].act_date_end!=_T(""))
			m_min_date=m_items[i].act_date_end;
	}
	aplString2Date(m_min_date,dt);
	if(dt.GetStatus()==COleDateTime::valid) 
	{
		m_min_dt.SetDateTime(dt.GetYear(),dt.GetMonth(),dt.GetDay(),0,0,0);
		m_min_calendar_dt.SetDateTime(dt.GetYear(),dt.GetMonth(),1,0,0,0);
		aplDate2String(m_min_calendar_dt,m_min_calendar_date);
	}
	*/

}

void CWfGanttCtrl::ResetVertScrollBar()
{
	CWfGanttView *pFrame = (CWfGanttView*)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 CWfGanttCtrl::GetColumnWidth(int nCol)
{
	HD_ITEM hItem;
	hItem.mask = HDI_WIDTH;
	if(!m_wndHeader.GetItem(nCol, &hItem))
		return 0;

	return hItem.cxy;
}

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

	}
}

void CWfGanttCtrl::PaintDiagram(CDC &dc,long mode)
{
	CRect rcClip, rcClient;
	dc.GetClipBox( &rcClip );
	GetClientRect(&rcClient);

	dc.SetViewportOrg(m_nOffset, 0);
	//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);
	
	CWfGanttView *gantt_view=((CWfGanttView*)GetParent());
	HTREEITEM hSelItem=NULL;
	if(gantt_view)
	{
		if(gantt_view->m_tree_view!=0)
			hSelItem=gantt_view->m_tree_view->m_tree.GetSelectedItem();
	}

	//Определение отображаемых границ по горизонтали
	RECT visible_rect;
	GetClientRect(&visible_rect);
	CWfGanttView *pFrame = (CWfGanttView*)GetParent();
	if(0!=pFrame)
	{
		//int nMin, nMax;
		//pFrame->m_horScrollBar.GetScrollRange(&nMin, &nMax);

		int scrol_pos=pFrame->m_horScrollBar.GetScrollPos();
		visible_rect.left+=(scrol_pos- 20); // 10 -запас на всякие концовки
		visible_rect.right+=(scrol_pos+ 20); 
	}


	int i;
	CString buf;
	COleDateTime dt;
	CPen pen(PS_SOLID,1,RGB(192,192,192));
	CPen black_pen(PS_SOLID,1,RGB(0,0,0));
	CPen red_pen(PS_SOLID,2,RGB(255,0,0));
	CPen *oldPen=dc.SelectObject(&pen);
	int Width = 0;
	int High=rcClient.Height();
	bool foundSaturday=false;
	int top=m_headerHeight+1;
	if(m_blockHeight*m_items.GetSize()+top>High) High=m_blockHeight*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_calendar_dt.GetYear(),m_min_calendar_dt.GetMonth(),m_min_calendar_dt.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=NULL;

	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;
	for(i=0;i<m_col_days;i++)
	{
		if(dt.GetStatus()==COleDateTime::valid)
		{
			CString dt_s;
			aplDate2String(dt,dt_s);
			// Отрисовка вертикальных линий дней
			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_s==m_max_calendar_date)
				{
					if(dt_s==m_max_calendar_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;
					}
					yearRect.left=nameLeftBound;
					dt0=dt-dt_span;
					buf=dt0.Format(_T("%Y"));
					dc.DrawText(buf, yearRect,DT_CENTER);
					nameLeftBound=leftBound;
				}
				// Отрисовка вертикальных линий месяцев и вывод их названий
				if(dt.GetDay()==1 || dt_s==m_max_calendar_date)
				{
					if(dt_s==m_max_calendar_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;
					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_s==m_max_calendar_date)
				{
					if(dt_s==m_max_calendar_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_s==m_max_calendar_date)
				{
					if(dt_s==m_max_calendar_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_calendar_dt).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)
						{
							if(holidayRect.right>visible_rect.left && holidayRect.left<visible_rect.right)
							{
								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;

				if(dayRect.right>visible_rect.left && dayRect.left<visible_rect.right)
				{
					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.SelectObject(&oldPen);
	
	CRect rect,gantt_rect,persentage_rect,actual_rect;
	int height=m_headerHeight;
	top=m_headerHeight+1;

	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));
	//gantt_brush.CreateSolidBrush(gantt_color);

	COLORREF prev_color=RGB(255,255,255);
	CBrush variable_brush_prj, variable_brush_procent;

	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);
	CPen actual_pen(PS_SOLID,2,gantt_border_color);
	CPen actual_pen_arrow(PS_SOLID|PS_GEOMETRIC|PS_ENDCAP_FLAT,1,gantt_border_color);

	CPen actual_ended_pen(PS_SOLID,4,gantt_border_color);
	//	CPen actual_working_pen(PS_DASH|PS_COSMETIC,3,gantt_border_color);
	LOGBRUSH logBrush;
	logBrush.lbStyle = BS_SOLID;
	logBrush.lbColor = gantt_border_color;
	CPen actual_working_pen(PS_DASH|PS_GEOMETRIC|PS_ENDCAP_FLAT, 2, &logBrush);  
	CPen actual_working_toend_pen(PS_DOT|PS_GEOMETRIC|PS_ENDCAP_FLAT, 2, &logBrush);  
	CBrush actual_working_prognoz_brush; actual_working_prognoz_brush.CreateSolidBrush(gantt_border_color);

	//gantt_brush.CreatePatternBrush(&m_pattern_bmp);
	//gantt_brush.CreateHatchBrush(HS_DIAGCROSS,gantt_color);
	gantt_brush.CreateSolidBrush(aplColor_GetHilightColor(gantt_color,75));

	CRect group_rect;

	COleDateTimeSpan dt_span1,dt_span2;
	COleDateTime dt_begin,dt_end;

	int xPrognoz;

	for(i=0;i<m_items.GetSize();i++)
	{
		height+=m_blockHeight;

		//плановые даты 
		GetPlannedRect(m_items[i],gantt_rect,top,height);
		
		if(gantt_rect.left<visible_rect.left) gantt_rect.left=visible_rect.left; // Обрезаем чтобы меньше рисовать
		if(gantt_rect.right>visible_rect.right) gantt_rect.right=visible_rect.right;

		if(mode==APL_MODE_SAVE) 
		{
			//вывод id проекта
			dc.SelectObject( pSmallFont );
			CRect id_rect;
			id_rect.left=2;
			id_rect.right=m_project_id_width-1;
			id_rect.top=gantt_rect.top;
			id_rect.bottom=gantt_rect.bottom;
			dc.DrawText(m_items[i].id, id_rect,DT_LEFT);
			dc.SelectObject( pFont );

			gantt_rect.left+=m_project_id_width;
			gantt_rect.right+=m_project_id_width;
		}

		//else dc.FillRect (gantt_rect, &gantt_brush);
		if(!m_bShowMultipleColors)dc.FillRect (gantt_rect, &gantt_brush);
		else
		{
			COLORREF newcolor=m_items[i].color;
			if(prev_color!=newcolor)
			{
				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(newcolor);
				COLORREF color1=aplColor_GetHilightColor(newcolor,-400);
				variable_brush_procent.CreateSolidBrush(color1);
				prev_color=newcolor;
			}
			dc.FillRect (gantt_rect, &variable_brush_prj);
		}
		
				
		//процент выполнения
		//if(m_items[i].percentage && m_items[i].percentage<100)
		/*
		ЯАИ: в WF нет процента выполнения
		int percentage=int(m_items[i].percentage);
		if(percentage>100) percentage=100;
		if(m_items[i].percentage)
		{
			//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.FrameRect(persentage_rect,&group_brush);
		}

		*/

		//фактические даты 
		if(m_items[i].act_date_begin!=_T("") || m_items[i].act_date_end!=_T(""))
		{
			GetActualRect(m_items[i],actual_rect,top,height, &xPrognoz);

			if(actual_rect.left<visible_rect.left) actual_rect.left=visible_rect.left; // Обрезаем чтобы меньше рисовать
			if(actual_rect.right>visible_rect.right) actual_rect.right=visible_rect.right;

			if(mode==APL_MODE_SAVE) 
			{
				actual_rect.left+=m_project_id_width;
				actual_rect.right+=m_project_id_width;
			}
			//dc.FillRect(actual_rect,&actual_brush);
			if(m_items[i].act_date_end!=_T(""))
			{
				dc.SelectObject(&actual_ended_pen);
				dc.MoveTo(actual_rect.left,actual_rect.top+2);
				dc.LineTo(actual_rect.right-1,actual_rect.top+2);
			}
			else
			{
				// не завершена
				if( (xPrognoz>actual_rect.left) && (xPrognoz<actual_rect.right))
				{
					dc.SelectObject(&actual_working_pen);
					dc.MoveTo(actual_rect.left,actual_rect.top+2);
					dc.LineTo(xPrognoz-7,actual_rect.top+2);

					dc.SelectObject(&actual_working_toend_pen);
					dc.MoveTo(xPrognoz+3,actual_rect.top+2);
					dc.LineTo(actual_rect.right-1,actual_rect.top+2);

					dc.SelectObject(&actual_pen_arrow);
					
					//dc.MoveTo(xPrognoz-10,actual_rect.top-3);
					//dc.LineTo(xPrognoz,actual_rect.top+2);
					//dc.MoveTo(xPrognoz-10,actual_rect.top+6);
					//dc.LineTo(xPrognoz,actual_rect.top+2);

					//dc.MoveTo(xPrognoz-10,actual_rect.top-3);
					//dc.LineTo(xPrognoz,actual_rect.top+1);
					//dc.LineTo(xPrognoz-10,actual_rect.top+5);
					//dc.LineTo(xPrognoz-10,actual_rect.top-3);

					CBrush *oldBrush=dc.SelectObject(&actual_working_prognoz_brush);
					POINT apoints[5];
					apoints[0].x=xPrognoz-7;  apoints[0].y=actual_rect.top-3;
					apoints[1].x=xPrognoz;    apoints[1].y=actual_rect.top+1;
					apoints[2].x=xPrognoz-7;  apoints[2].y=actual_rect.top+5;
					apoints[3]=apoints[0];
					dc.Polygon(apoints,4);
					dc.SelectObject(oldBrush);

				}
				else
				{
					dc.SelectObject(&actual_working_toend_pen);
					dc.MoveTo(actual_rect.left,actual_rect.top+2);
					dc.LineTo(actual_rect.right-1,actual_rect.top+2);
				}
			}

			// концовки
			if(m_items[i].act_date_begin!=_T(""))
			{
				dc.SelectObject(&actual_pen);
				dc.MoveTo(actual_rect.left,gantt_rect.top+1);
				dc.LineTo(actual_rect.left,gantt_rect.bottom-1);
				dc.SelectObject(&oldPen);
			}
			if(m_items[i].act_date_end!=_T(""))
			{
				dc.SelectObject(&actual_pen);
				dc.MoveTo(actual_rect.right,gantt_rect.top+1);
				dc.LineTo(actual_rect.right,gantt_rect.bottom-1);
				dc.SelectObject(&oldPen);
			}
		}
	
		oldBrush=dc.SelectObject(&gantt_border_brush);
		dc.FrameRect(gantt_rect,&gantt_border_brush);

		group_rect=gantt_rect;
		group_rect.DeflateRect(1,1);
		if(m_items[i].last_sub_item>-1) 
			dc.FrameRect(&group_rect, &gantt_border_brush);

		
		//выделение выделенного в дереве проекта
		if(m_items[i].hTreeItem==hSelItem)
		{
			CRect sel_rect=gantt_rect;
			for(int sel=0;sel<2;sel++)
			{
				sel_rect.top-=1;
				sel_rect.bottom+=1;
				sel_rect.left-=1;
				sel_rect.right+=1;
				dc.FrameRect(sel_rect,&select_brush);
			}
		}

		//if(m_items[i].act_date_begin!=_T("") || m_items[i].act_date_end!=_T(""))
		//	dc.FrameRect(actual_rect,&dark_brush);

		//отрисовка крестиков, показывающих не заданные даты
		if(m_items[i].pl_date_begin==_T(""))
		{
			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);
			dc.SelectObject(&oldPen);
		}
		if(m_items[i].pl_date_end==_T(""))
		{
			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);
			dc.SelectObject(&oldPen);
		}

		top+=m_blockHeight;
		dc.SelectObject(oldBrush);
	}

	//отрисовка линий к нижнему из входящих в проект
	height=m_headerHeight;
	top=m_headerHeight+1;
	dc.SelectObject(&black_pen);
	for(i=0;i<m_items.GetSize();i++)
	{
		height+=m_blockHeight;

		if(m_items[i].last_sub_item>-1)
		{
			int first_planned=GetFirstDays(m_items[i].pl_date_begin);
			int dlit_planned=GetDlitDays(m_items[i].pl_date_begin,m_items[i].pl_date_end);

			gantt_rect.left=m_pixelsInDay*first_planned-m_pixelsInDay+2;
			gantt_rect.top=top+3;
			gantt_rect.bottom=height-3;
			gantt_rect.right=gantt_rect.left+m_pixelsInDay*dlit_planned;

			if(mode==APL_MODE_SAVE) 
			{
				gantt_rect.left+=m_project_id_width;
				gantt_rect.right+=m_project_id_width;
			}

			int item_num=m_items[i].last_sub_item;
			int item_count=item_num-i;

			dc.MoveTo(gantt_rect.left,gantt_rect.top);
			dc.LineTo(gantt_rect.left,height+m_blockHeight*item_count-3);
			dc.LineTo(gantt_rect.left+4,height+m_blockHeight*item_count-3);
			dc.MoveTo(gantt_rect.right-1,gantt_rect.top);
			dc.LineTo(gantt_rect.right-1,height+m_blockHeight*item_count-3);
			dc.LineTo(gantt_rect.right-5,height+m_blockHeight*item_count-3);
		}
		top+=m_blockHeight;
	}
	dc.SelectObject(&pen);
	
	//отрисовка разделительной линии между заголовком и основной частью 
	CRect m_wndRect;
	pFrame->GetClientRect(&m_wndRect);
	dc.MoveTo(0,m_headerHeight);
	dc.LineTo(max(rcClient.Width(),GetColumnsWidth()),m_headerHeight);

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

}

bool CWfGanttCtrl::ExportDiagramBmp(CString &bmp_f_name)
{
	CPaintDC pDC(this); // device context for painting
	CDC memDC;
	if(!memDC.CreateCompatibleDC(&pDC)) return false;
	CBitmap bm;
	int old_offset=m_nOffset;
	m_nOffset=0;
	int old_m_pixelsInDay=m_pixelsInDay;
	int old_m_nColumnsWidth=m_nColumnsWidth;
	old_m_nColumnsWidth=m_col_days*m_pixelsInDay;
	AutoResizeDiagram(true,false);

	CFont *pFont = CFont::FromHandle((HFONT)GetStockObject(SYSTEM_FONT));
	LOGFONT logfont;
	pFont->GetLogFont( &logfont );
	m_project_id_width=logfont.lfWidth*m_max_id_length;

	bm.CreateCompatibleBitmap(&pDC,m_pixelsInDay*m_col_days+4+m_project_id_width,m_headerHeight+m_items.GetSize()*m_blockHeight);
	CBitmap *old = memDC.SelectObject(&bm);
	memDC.FloodFill(0,0,RGB(255,255,255));
	PaintDiagram(memDC,APL_MODE_SAVE);
	m_nOffset=old_offset;
	m_pixelsInDay=old_m_pixelsInDay;
	m_nColumnsWidth=old_m_nColumnsWidth;
	bool result=SaveBitmapAs(bm,bmp_f_name);
	memDC.SelectObject(old);
	memDC.DeleteDC();
	return result;
}

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

void CWfGanttCtrl::AutoResizeDiagram(bool bReduce,bool bInvalidate)
{
	COleDateTimeSpan dt_span;
	dt_span=m_max_calendar_dt-m_min_calendar_dt;
	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 CWfGanttCtrl::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 CWfGanttCtrl::SetPixelsInDay(int pixelsInDay)
{
	CheckSetPixelsInDay(pixelsInDay);
	RecalcColumnsWidth();
	((CWfGanttView*)GetParent())->ResetScrollBar();
	if(((CWfGanttView*)GetParent())->m_bShrinkToFit) AutoResizeDiagram(false,false);
	((CWfGanttView*)GetParent())->Invalidate();
	return true;
}



int CWfGanttCtrl::GetFirstDays(LPCTSTR date_begin)
{
	CString date_begin_s=date_begin;
	COleDateTime dt,dt_begin;
	if(date_begin_s!=_T("")) 
	{
		aplString2Date(date_begin_s,dt);
		dt_begin.SetDateTime(dt.GetYear(),dt.GetMonth(),dt.GetDay(),0,0,0);
	}
	else 
		dt_begin.SetDateTime(m_min_calendar_dt.GetYear(),m_min_calendar_dt.GetMonth(),m_min_calendar_dt.GetDay(),0,0,0);
	COleDateTimeSpan dt_span1=dt_begin-m_min_calendar_dt;
	int first_days=0;
	if(dt_span1.GetStatus()==COleDateTimeSpan::valid) first_days=dt_span1.GetDays()+1;
	return first_days;

}

int CWfGanttCtrl::GetDlitDays(LPCTSTR date_begin, LPCTSTR date_end)
{
	CString date_begin_s=date_begin;
	CString date_end_s=date_end;
	COleDateTime dt,dt_begin,dt_end;
	COleDateTimeSpan dt_span1,dt_span2;
	if(date_begin_s!=_T("")) 
	{
		aplString2Date(date_begin_s,dt);
		dt_begin.SetDateTime(dt.GetYear(),dt.GetMonth(),dt.GetDay(),0,0,0);
	}
	else 
		dt_begin.SetDateTime(m_min_calendar_dt.GetYear(),m_min_calendar_dt.GetMonth(),m_min_calendar_dt.GetDay(),0,0,0);
	
	if(date_end_s!=_T("")) 
	{
		aplString2Date(date_end_s,dt);
		dt_end.SetDateTime(dt.GetYear(),dt.GetMonth(),dt.GetDay(),0,0,0);
	}
	else 
		dt_end.SetDateTime(m_max_calendar_dt.GetYear(),m_max_calendar_dt.GetMonth(),m_max_calendar_dt.GetDay(),0,0,0);
	
	dt_span2=dt_end-dt_begin;
	int dlit_days=0;
	if(dt_span2.GetStatus()==COleDateTimeSpan::valid) dlit_days=dt_span2.GetDays()+1;
	return dlit_days;
}

bool CWfGanttCtrl::PointToVal(CPoint *point, CGanttItem &gItem, HTREEITEM &hItem,CaplInstance **inst)
{
	int height=m_headerHeight;
	int top=m_headerHeight+1;
	CRect actual_rect,gantt_rect,persentage_rect;
	point->x+=-m_nOffset;
	for(int i=0;i<m_items.GetSize();i++)
	{
		height+=m_blockHeight;
		gItem=m_items[i];
		hItem=m_items[i].hTreeItem;
		*inst=(CaplInstance*)m_items[i].itemData;
		if(m_items[i].act_date_begin!=_T("") || m_items[i].act_date_end!=_T(""))
		{
			GetActualRect(m_items[i],actual_rect,top,height);
		}
		if(actual_rect.PtInRect(*point)) return true;
		
		GetPlannedRect(m_items[i],gantt_rect,top,height);
		if(gantt_rect.PtInRect(*point)) return true;

		top+=m_blockHeight;
	}
	return false;
}

void CWfGanttCtrl::OnLButtonDblClk(UINT nFlags, CPoint point) 
{
	// TODO: Add your message handler code here and/or call default
	CaplInstance *sel_project=0;
	HTREEITEM hItem;
	CGanttItem gItem;
	if(false==PointToVal(&point,gItem,hItem,&sel_project)) return;
	if(!sel_project) return;
	if(!hItem) return;

	HideToolTip();
	
	CWnd::OnLButtonDblClk(nFlags, point);
}

void CWfGanttCtrl::OnLButtonDown(UINT nFlags, CPoint point) 
{	
	CaplInstance *sel_project=0;
	HTREEITEM hItem;
	CGanttItem gItem;
	if(false==PointToVal(&point,gItem,hItem,&sel_project)) return;
	//if(!sel_project) return;
	if(!hItem) return;
	((CWfGanttView*)GetParent())->m_tree_view->m_tree.SelectItem(hItem);
	((CWfGanttView*)GetParent())->Update(false);
	
	CWnd::OnLButtonDown(nFlags, point);
}

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

	CWnd::OnMouseMove(nFlags,point); 

	if(PointToVal(&new_point,gItem,hItem,&sel_project))
		DisplayToolTip(point,gItem);

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

void CWfGanttCtrl::DisplayToolTip(CPoint point,CGanttItem &gItem)
{
	CString buf;
	COleDateTime dt;
	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!=_T("") || gItem.pl_date_end!=_T(""))
	{
		tooltip_text+=APL_T("План: ");
		aplString2Date(gItem.pl_date_begin,dt);
		if(dt.GetStatus()==COleDateTime::valid)	
		{
			buf=dt.Format(_T("%d.%m.%Y"));
			tooltip_text+=APL_T("начало:")+buf+_T("   ");
		}
		aplString2Date(gItem.pl_date_end,dt);
		if(dt.GetStatus()==COleDateTime::valid)	
		{
			buf=dt.Format(_T("%d.%m.%Y"));
			tooltip_text+=APL_T("окончание: ")+buf;
		}
		tooltip_text+=_T("\n");
	}
	
	if(gItem.act_date_begin!=_T("") || gItem.act_date_end!=_T("") || gItem.act_date_end_prognoz!=_T(""))
	{
		tooltip_text+=APL_T("Факт: ");
		aplString2Date(gItem.act_date_begin,dt);
		if(dt.GetStatus()==COleDateTime::valid)	
		{
			buf=dt.Format(_T("%d.%m.%Y"));
			tooltip_text+=APL_T("начало: ")+buf+_T("   ");
		}
		aplString2Date(gItem.act_date_end,dt);
		if(dt.GetStatus()==COleDateTime::valid)	
		{
			buf=dt.Format(_T("%d.%m.%Y"));
			tooltip_text+=APL_T("окончание:")+buf;
		}
		if(gItem.act_date_end_prognoz!=_T(""))
		{
			aplString2Date(gItem.act_date_end_prognoz,dt);
			if(dt.GetStatus()==COleDateTime::valid)	
			{
				buf=dt.Format(_T("%d.%m.%Y"));
				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);
	/*CRect rect;
	rect.right=0;
	rect.bottom=0;
	rect.top=point.y;
	rect.left=point.x+10;
	ClientToScreen(&rect);*/
	m_ToolTip.Show(pnt.x, pnt.y, tooltip_text,480);}

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

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

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

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

void CWfGanttCtrl::GetPlannedRect(CGanttItem &item,CRect &rect,int top,int height)
{
	int first_planned=GetFirstDays(item.pl_date_begin);
	int dlit_planned=GetDlitDays(item.pl_date_begin,item.pl_date_end);

	rect.left=m_pixelsInDay*first_planned-m_pixelsInDay+2;
	rect.top=top+1;
	rect.bottom=height-1;
	rect.right=rect.left+m_pixelsInDay*dlit_planned;
}

void CWfGanttCtrl::GetActualRect(CGanttItem &item,CRect &rect,int top,int height, int *xPosPrognoz)
{
	int first_actual=GetFirstDays(item.act_date_begin);
	int dlit_actual=GetDlitDays(item.act_date_begin,item.act_date_end);	

	rect.left=m_pixelsInDay*first_actual-m_pixelsInDay+2;
	rect.top=top+1+int((height-top)/3);
	rect.bottom=height-1-int((height-top)/3);
	rect.right=rect.left+m_pixelsInDay*dlit_actual;

	if(0!=xPosPrognoz)
	{
		if(item.act_date_end_prognoz==_T("")) *xPosPrognoz=0;
		else
		{
			int tmp=GetFirstDays(item.act_date_end_prognoz);
			*xPosPrognoz=m_pixelsInDay*tmp-m_pixelsInDay+2;
		}
	}
}
