// TaskTimesDialog.cpp : implementation file
//

#include "stdafx.h"
#include <apl_api.h>
#include "aplWorkFlowManager.h"
#include "TaskTimesDialog.h"

#include "wfganttView.h"


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

/////////////////////////////////////////////////////////////////////////////
// CTaskTimesDialog dialog


CTaskTimesDialog::CTaskTimesDialog(CWnd* pParent /*=NULL*/)
	: CaplResizableDialog(CTaskTimesDialog::IDD, pParent)
{
	//{{AFX_DATA_INIT(CTaskTimesDialog)
	m_codtEndDate = COleDateTime::GetCurrentTime();

	m_codtStartDate = m_codtEndDate-COleDateTimeSpan(92,0,0,0);
	m_codtStartDate.SetDate(m_codtStartDate.GetYear(),m_codtStartDate.GetMonth(),1);
	m_csPerformer = _T("");
	//}}AFX_DATA_INIT

	m_pApi			=NULL;

	m_ciSelTempl	=NULL;
	m_ciSelAct		=NULL;

	m_wf_mgr		=NULL;

	m_csEngStates.Add(_T("inactive"));
	m_csEngStates.Add(_T("active"));
	m_csEngStates.Add(_T("work"));
	m_csEngStates.Add(_T("suspend"));
	m_csEngStates.Add(_T("cancel"));
	m_csEngStates.Add(_T("complete"));

	m_csRusStates.Add(APL_T("Не выполняется"));
	m_csRusStates.Add(APL_T("Выдано"));
	m_csRusStates.Add(APL_T("Выполняется"));
	m_csRusStates.Add(APL_T("Остановлено"));
	m_csRusStates.Add(APL_T("Отозвано"));
	m_csRusStates.Add(APL_T("Выполнено"));

	m_ciPerformer	=NULL;


	m_tree_view=0;
	m_gantt_view=0;
	m_splitter=0;

}


void CTaskTimesDialog::DoDataExchange(CDataExchange* pDX)
{
	CaplResizableDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CTaskTimesDialog)
	DDX_Control(pDX, IDC_TREE_BORDER, m_tree_border_ctrl);
	DDX_Control(pDX, IDC_VIEW_MODE, m_view_mode_ctrl);
	DDX_Control(pDX, IDC_ZOOMOUT, m_zoomout_btn);
	DDX_Control(pDX, IDC_ZOOMIN, m_zoomin_btn);
	DDX_Control(pDX, IDC_GANTT_BORDER, m_gantt_border_ctrl);
	DDX_Control(pDX, IDCANCEL, m_Cancel);
	DDX_Control(pDX, IDC_B_SHOW, m_bShow);
	DDX_Control(pDX, IDC_B_SELECT_PERFORMER, m_bSelect);
	DDX_Control(pDX, IDC_B_SAVE, m_bSave);
	DDX_Control(pDX, IDC_B_HEADER, m_bHeader);

	DDX_Control(pDX, IDC_CB_ACTIVITIES, m_cbActivities);
	DDX_Control(pDX, IDC_CB_STATES, m_cbStates);
	DDX_Control(pDX, IDC_CB_TEMPLATES, m_cbTemplates);
	DDX_DateTimeCtrl(pDX, IDC_DT_END_DATE, m_codtEndDate);
	DDX_DateTimeCtrl(pDX, IDC_DT_START_DATE, m_codtStartDate);
	DDX_Text(pDX, IDC_E_PERFORMER, m_csPerformer);
	//}}AFX_DATA_MAP
	//	DDX_Control(pDX, IDC_LC_RESULTS, m_lcResults);
	DDX_Control(pDX, IDC_EXECUTE_LEN, m_execute_len_ctrl);
	DDX_Control(pDX, IDC_OVERDUE, m_overdue_ctrl);
	DDX_Control(pDX, IDC_DEADLINE, m_dl_ctrl);
	DDX_Control(pDX, ID_SHOW_COLOR_LEGEND, m_show_color_legend_btn);
	DDX_Control(pDX, IDC_SHOW_NUM_ITERATION, m_bShowNumIterationBtn);
	DDX_Control(pDX, IDC_TMPL_FILTER, m_tmpl_filter_ctrl);
}


BEGIN_MESSAGE_MAP(CTaskTimesDialog, CaplResizableDialog)
	//{{AFX_MSG_MAP(CTaskTimesDialog)
	ON_BN_CLICKED(IDC_B_SELECT_PERFORMER, OnBSelectPerformer)
	ON_BN_CLICKED(IDC_B_SHOW, OnBShow)
	ON_BN_CLICKED(IDC_B_SAVE, OnBSave)
	ON_BN_CLICKED(IDC_B_HEADER, OnBHeader)
	ON_CBN_SELCHANGE(IDC_CB_TEMPLATES, OnSelchangeCbTemplates)
	ON_WM_DESTROY()
	ON_BN_CLICKED(IDC_B_CLEAR_PERFORMER, OnBClearPerformer)
	ON_NOTIFY(DTN_DROPDOWN, IDC_DT_START_DATE, OnDropdownDtStartDate)
	ON_NOTIFY(DTN_DROPDOWN, IDC_DT_END_DATE, OnDropdownDtEndDate)
	ON_NOTIFY(DTN_DATETIMECHANGE, IDC_DT_START_DATE, OnDatetimechangeDtStartDate)
	ON_NOTIFY(DTN_DATETIMECHANGE, IDC_DT_END_DATE, OnDatetimechangeDtEndDate)
	ON_CBN_SELCHANGE(IDC_VIEW_MODE, OnSelchangeViewMode)
	ON_BN_CLICKED(IDC_ZOOMIN, OnZoomin)
	ON_BN_CLICKED(IDC_ZOOMOUT, OnZoomout)
	ON_WM_VSCROLL()
	ON_WM_SIZE()
	ON_COMMAND(WM_SELCHANGE,OnSelChanged)
	//}}AFX_MSG_MAP
	ON_BN_CLICKED(ID_SHOW_COLOR_LEGEND, &CTaskTimesDialog::OnBnClickedShowColorLegend)
	ON_BN_CLICKED(ID_TMPL_FILTER_APPLY, &CTaskTimesDialog::OnBnClickedTmplFilterApply)
END_MESSAGE_MAP()

void CTaskTimesDialog::GetEngState(CString& csRusState)
{
	CMapStringToString	st;

	CString				cst;

	int					i;

	for(i=0;i<m_csRusStates.GetSize();i++)
		st.SetAt(m_csRusStates[i],m_csEngStates[i]);

	if(TRUE==st.Lookup(csRusState,cst))
		csRusState=cst;
}

void CTaskTimesDialog::GetRusState(CString& csEngState)
{
	CMapStringToString	st;

	CString				cst;

	int					i;

	for(i=0;i<m_csRusStates.GetSize();i++)
		st.SetAt(m_csEngStates[i],m_csRusStates[i]);

	if(TRUE==st.Lookup(csEngState,cst))
		csEngState=cst;
}

void CTaskTimesDialog::GetParamsForQuery(aplExtent& ciTemplate,aplExtent& ciActivity,
										 CaplInstance*& ciPerformer,CStringArray& csState,
										 CString& csStartDate,CString& csEndDate)
{
	CString*	cspState	=NULL;

	ciPerformer=m_ciPerformer;

	ciTemplate.Clear();ciActivity.Clear();csState.RemoveAll();

	CaplInstance* cit= NULL;

	if(m_cbTemplates.GetCheck(0) == TRUE)
	{
		if(m_sTemplatesFilter!=_T("")) // Показаны не все шаблоны
		{
			for(int i=0; i<m_TemplatesMap.GetSize(); i++)
			{
				cit=(CaplInstance*)(m_TemplatesMap[i].out);
				if(cit)	ciTemplate.Add(cit);
			}
		}
	}
	else
	{
		for(int i=1; i<m_cbTemplates.GetCount(); ++i)
		{
			if(m_cbTemplates.GetCheck(i))
			{
				cit=(CaplInstance*)m_TemplatesMap.QGetPointerByIn(i);
				if(cit)
					ciTemplate.Add(cit);
			}
		}	
	}
	if(m_cbActivities.GetCheck(0) == FALSE)
	{
		for(int i=1; i<m_cbActivities.GetCount(); ++i)
		{
			if(m_cbActivities.GetCheck(i))
			{
				cit=(CaplInstance*)m_ActivitiesMap.QGetPointerByIn(i);
				if(cit)
					ciActivity.Add(cit);
			}
		}	
	}
	if(m_cbStates.GetCheck(0) == FALSE)
	{
		int i,j;
		CString buf;
		for(i=1; i<m_cbStates.GetCount(); ++i)
		{
			if(m_cbStates.GetCheck(i))
			{
				m_cbStates.GetLBText(i,buf);
				j=m_StatesMap.Get(buf);
				if(j>=0)
					csState.Add(m_csEngStates[j]);
			}
		}	
	}

	aplDate2String(m_codtStartDate,csStartDate);
	aplDate2String(m_codtEndDate,csEndDate);
}

BOOL CTaskTimesDialog::ExecuteQuery(aplExtent& ciTemplate, aplExtent& ciActivity,
									CaplInstance* ciPerformer,CStringArray& csState,
									CString& csStartDate,CString& csEndDate,
									aplExtent& aeOutRes, bool bShowMsg)
{
	CString			csQ,cst;
	
	int i;

	aeOutRes.Clear();

	// task-of_process_of_process_template or
	// task-of_activity-of_process_template

	csQ=_T("SELECT\n Ext_0\n FROM\n ");

	int ipos4NewExt=csQ.GetLength();
	
	if(ciTemplate.GetSize())
	{
		csQ+=_T(" Ext_a{");
		for(i= 0; i<ciTemplate.GetSize(); i++)
		{
			cst.Format(_T("#%i"), ciTemplate[i]->GetId());
			if(i)csQ+=_T(", ");
			csQ+=cst;
		}
		csQ+=_T("} \n ");
	}
	if(ciActivity.GetSize())
	{
		csQ+=_T(" Ext_b{");
		for(i= 0; i<ciActivity.GetSize(); i++)
		{
			cst.Format(_T("#%i"), ciActivity[i]->GetId());
			if(i)csQ+=_T(", ");
			csQ+=cst;
		}
		csQ+=_T("} \n ");
	}

	csQ+=_T(" Ext_0 {apl_task(");

	//	template
	//	вставляем, когда template!="все" и activity=="все"
	if(ciTemplate.GetSize() && !ciActivity.GetSize())
	{
		csQ+=_T("(.of_process->apl_process.of_process_template->apl_process_template .# IN #Ext_a)");
	}

	// activity
	if(ciActivity.GetSize())
	{
		csQ+=_T(".of_activity->apl_activity .# IN #Ext_b");
	}

	if((ciTemplate.GetSize() && !ciActivity.GetSize()) || ciActivity.GetSize())
	{
		cst=_T(" AND ");
		csQ+=cst;
	}

	//	performer
	if(NULL!=ciPerformer)
	{
		if(m_pApi->m_data.IsKindOf(ciPerformer,m_pApi->m_appr_mgr.e_org))
		{
			aplExtent ext_pers, ext_rel;
			m_pApi->m_appr_mgr.GetAllSubPerson(ciPerformer,ext_pers,ext_rel);
			int i;
			// Чистим от посторонних объектов
			for(i=0;i<ext_pers.GetSize();i++)
			{
				if(!m_pApi->m_data.IsKindOf(ext_pers[i],m_pApi->m_appr_mgr.e_person))
				{
					ext_pers.Remove(i);
					i--;
				}
			}
			// формируем запрос
			if(0==ext_pers.GetSize())
			{
				AfxMessageBox(APL_T("В выбранной группе нет ни одного сотрудника!"),MB_OK|MB_ICONWARNING);
				return FALSE;
			}
			CString buf;
			cst=_T("( ");
			for(i=0;i<ext_pers.GetSize();i++)
			{
				if(i>0) cst+=_T(" OR ");
				buf.Format(_T(".performer=#%d "),ext_pers[i]->GetId());	
				cst+=buf;
			}
			cst+=_T(" ) AND ");

			/* ЯАИ: Илья сказал что с OR-ами будет быстрее
			CString sExt;
			sExt+=_T(" Ext_performer{");
			for(i= 0; i<ext_pers.GetSize(); i++)
			{
				cst.Format(_T("#%i"), ext_pers[i]->GetId());
				if(i)sExt+=_T(", ");
				sExt+=cst;
			}
			sExt+=_T("} \n ");

			csQ.Insert(ipos4NewExt,sExt);
			cst.Format(_T("(.performer IN #Ext_performer) AND "),m_ciPerformer->GetId());
			*/
		}
		else
		{
			cst.Format(_T(".performer=#%d AND "),m_ciPerformer->GetId());
		}
		csQ+=cst;
	}

	//	state
	if(csState.GetSize())
	{
		csQ+=_T("(");
		for(i=0; i<csState.GetSize();i++)
		{
			cst.Format(_T(".state='%s' "),csState[i]);
			if(i) csQ+=_T(" OR ");
			csQ+=cst;
		}
		csQ+=_T(") AND ");
	}
	
	//	start_date
	cst.Format(_T(".start_date >'%s'"),csStartDate);
	csQ+=cst;

	//	end_date
	cst.Format(_T(" AND .start_date <'%s'"),csEndDate);
	csQ+=cst;

	csQ+=_T(")}\nEND_SELECT");

	if(!m_pApi->m_data.NET_QueryEditParse(csQ,false)) return FALSE;

	bool bret;

	bret=m_pApi->m_data.NET_QueryExecute(aeOutRes,APL_T("Поиск..."));
	//TRACE(_T("found %d\n"),aeOutRes.GetSize());
	if(!bret)return FALSE;

	if(bShowMsg && (aeOutRes.GetSize()>1000))
	{
		CString buf;
		buf.Format(APL_T("Найдено %i работ. Рекомендуется изменить условие поиска. Показать данные?"),aeOutRes.GetSize());
		if(IDYES!=AfxMessageBox(buf,MB_YESNO)) return FALSE;
	}

	m_wf_mgr->LoadTaskInfo(aeOutRes);

	//Фильтруем по просроченным

	bool bCheckExecuteLen=false;
	bool bCheckOverdue=false;
	bool bCheckDeadLine=false;
	CString sExecuteLen,sOverdue,sDeadLine;
	COleDateTimeSpan span_overdue, span_execute_len, span_dl_len;

	m_execute_len_ctrl.GetWindowText(sExecuteLen);
	m_overdue_ctrl.GetWindowText(sOverdue);
	m_dl_ctrl.GetWindowText(sDeadLine);

	if(sExecuteLen!=_T("")){bCheckExecuteLen=true; span_execute_len.SetDateTimeSpan(_atoi(sExecuteLen),0,0,0);}
	if(sOverdue!=_T("")){bCheckOverdue=true; span_overdue.SetDateTimeSpan(_atoi(sOverdue),0,0,0);}
	if(sDeadLine!=_T("")){bCheckDeadLine=true; span_dl_len.SetDateTimeSpan(_atoi(sDeadLine),0,0,0);}

	if(!(bCheckExecuteLen || bCheckOverdue || bCheckDeadLine)) return TRUE;  // нечего фильтровть
	

	CString sStartDate,sFinishDate, sEndDate;
	COleDateTime odt_current=COleDateTime::GetCurrentTime();
	COleDateTime odt_start,odt_finish,odt_end;
	COleDateTimeSpan dt_span;

	for(i=0; i< aeOutRes.GetSize();i++)
	{
		CaplInstance *task=aeOutRes[i];

		m_pApi->m_data.GetAttr(task, m_wf_mgr->a_act_inst_start_date,sStartDate);
		if(sStartDate==_T("")) continue;
		aplString2Date(sStartDate,odt_start);

		m_pApi->m_data.GetAttr(task, m_wf_mgr->a_act_inst_end_date,sEndDate);
		if(sEndDate==_T("")) continue;
		aplString2Date(sEndDate,odt_end);

		m_pApi->m_data.GetAttr(task, m_wf_mgr->a_act_inst_finish_date,sFinishDate); //Фактическая дата завершения
		if(sFinishDate!=_T("")) aplString2Date(sFinishDate,odt_finish);
		else odt_finish=odt_current;

		bool b1=false; 
		if(span_execute_len)
		{
			dt_span=odt_finish-odt_start;
			if(dt_span<span_execute_len) b1=true; // выполняется дольше
		}

		bool b2=false; 	
		if(bCheckOverdue)
		{
			dt_span=odt_finish-odt_end;
			if(dt_span<span_overdue) b2=true;  //просрочено более
		}
		bool b3=false; 
		if(bCheckDeadLine)
		{
			dt_span=odt_current-odt_end;
			if(dt_span<span_dl_len && sFinishDate==_T("")) b3=true; // до завершения осталось
		}
		if(b1&&b2&&b3) continue;

		aeOutRes.Remove(i);
		i--;
	}
	return TRUE;
}

void CTaskTimesDialog::SortAndReadData(aplExtent& aeData,TaskArray& taTasksOut,
									   BOOL bReadIterations)
{
	CaplInstance*		cit1	=NULL;
	CaplInstance*		cit2	=NULL;

	COleDateTime		codtStart,codt;
	COleDateTimeSpan	codtspan;

	CString				cst;

	_task_info*			pinfo	=NULL;

	int					i;

	for(i=0;i<taTasksOut.GetSize();i++)
	{
		pinfo=taTasksOut.GetAt(i);
		delete pinfo;pinfo=NULL;
	}

	taTasksOut.RemoveAll();
	
	//m_wf_mgr->LoadTaskInfo(aeData); // ЯАИЖ: Перенесено в выполнение запроса

	for(i=0;i<aeData.GetSize();i++)
	{
		pinfo=new _task_info;

		//	task
		cit1=aeData.GetAt(i);
		pinfo->ciTask=cit1;
		pinfo->iIteration= 1;

		//	проект
		m_pApi->m_data.GetAttr(cit1,m_wf_mgr->a_task_proc,cit2);
		if(!cit2){delete pinfo;	continue;}
		pinfo->ciProc=cit2;

		//	template - getitemname
		m_pApi->m_data.GetAttr(pinfo->ciProc,m_wf_mgr->a_proc_of_tmpl,cit2);
		if(!cit2){delete pinfo;	continue;}
		pinfo->ciTemplate=cit2;

		//	task - of activity - getitemname
		m_pApi->m_data.GetAttr(pinfo->ciTask,m_wf_mgr->a_task_activity,cit2);
		if(!cit2){delete pinfo;	continue;}
		pinfo->ciActivity=cit2;

		//	состояние
		m_pApi->m_data.GetAttr(pinfo->ciTask,m_wf_mgr->a_task_state,cst);
		pinfo->csState=cst;cst=_T("");

		//	итерация - в конце
		//	исполнитель
		m_pApi->m_data.GetAttr(pinfo->ciTask,m_wf_mgr->a_task_performer,cit2);
		pinfo->ciPerformer=cit2;
		//	треб. длит.
		m_pApi->m_data.GetAttr(pinfo->ciTask,m_wf_mgr->a_act_inst_finish_date,cst);
		if(cst!=_T(""))aplString2Date(cst,codt);
		else codt=COleDateTime::GetCurrentTime();
			cst=_T("");

		m_pApi->m_data.GetAttr(pinfo->ciTask,m_wf_mgr->a_act_inst_start_date,cst);
		aplString2Date(cst,codtStart);
		codtspan=codt-codtStart;

		pinfo->codtNeedTime=codtspan;
		pinfo->codtStartDate=codtStart;cst=_T("");

		//	факт. длит.
		m_pApi->m_data.GetAttr(pinfo->ciTask,m_wf_mgr->a_act_inst_end_date,cst);
		if(cst!=_T(""))
		{
			aplString2Date(cst,codt);
			codtspan=codt-codtStart;
			
			pinfo->codtEndDate=codt;
			pinfo->codtRealTime=codtspan;
		}
		else
		{
			pinfo->codtEndDate.m_status= COleDateTime::invalid;
			pinfo->codtRealTime.m_status=COleDateTimeSpan::invalid;
		}
// 		else codt=COleDateTime::GetCurrentTime();
// 		cst=_T("");

		
		m_pApi->m_data.GetAttr(pinfo->ciTask,m_wf_mgr->a_act_inst_finish_date,cst);
		if(cst!=_T(""))
		{
			aplString2Date(cst,codt);
			pinfo->codtEndDateF=codt;
		}
		else
		{
			pinfo->codtEndDateF.m_status= COleDateTime::invalid;
		}

		taTasksOut.Add(pinfo);
	}

	if(TRUE==bReadIterations && (m_bShowNumIterationBtn.GetCheck()>0))
		SetIterations();
}

void CTaskTimesDialog::_Split(TaskArray& taIn,SortMap& mapOut)
{
	CaplInstance*	cit1	=NULL;
	CaplInstance*	cit2	=NULL;

	SortMap*		iter2	=NULL;
	TaskArray*		pArr	=NULL;

	_task_info*		pinfo	=NULL;

	int				i;
	//	разбиваем по process и activity
	for(i=0;i<taIn.GetSize();i++)
	{
		pinfo=taIn.GetAt(i);
		cit1=pinfo->ciProc;
		cit2=pinfo->ciActivity;

		if(FALSE==mapOut.Lookup(cit1->GetId(),(void*&)iter2))
		{
			//	еще нет такого процесса - добавляем Map на Activity
			iter2=new SortMap;
			mapOut.SetAt(cit1->GetId(),iter2);
		}

		if(FALSE==iter2->Lookup(cit2->GetId(),(void*&)pArr))
		{
			//	если нет такого Activity - добавляем
			pArr=new TaskArray;
			iter2->SetAt(cit2->GetId(),pArr);
		}

		pArr->Add(pinfo);
	}
}

void CTaskTimesDialog::_Sort(SortMap& mapIn)
{
	SortMap*	iter2	=NULL;
	TaskArray*	pArr	=NULL;

	POSITION	pos1,pos2;

	long		lt;

	//	сортируем каждый массив по дате (start_date)
	pos1=mapIn.GetStartPosition();
	while(pos1!=NULL)
	{
		mapIn.GetNextAssoc(pos1,lt,(void*&)iter2);
		pos2=iter2->GetStartPosition();
		while(pos2!=NULL)
		{
			iter2->GetNextAssoc(pos2,lt,(void*&)pArr);
			qsort(pArr->GetData(),pArr->GetSize(),sizeof(_task_info*),Compare);
		}
	}
}

void CTaskTimesDialog::_SetIter(SortMap& mapIn)
{
	SortMap*	iter2	=NULL;
	TaskArray*	pArr	=NULL;

	_task_info*	pinfo	=NULL;

	POSITION	pos1,pos2;

	long		lt;

	int			i;

	//	получаем итерацию
	pos1=mapIn.GetStartPosition();
	while(pos1!=NULL)
	{
		mapIn.GetNextAssoc(pos1,lt,(void*&)iter2);
		pos2=iter2->GetStartPosition();
		while(pos2!=NULL)
		{
			iter2->GetNextAssoc(pos2,lt,(void*&)pArr);
			for(i=0;i<pArr->GetSize();i++)
			{
				pinfo=pArr->GetAt(i);
				pinfo->iIteration=i+1;
			}
		}
	}
}

void CTaskTimesDialog::_ClearMap(SortMap& mapIn,BOOL bDelInfo)
{
	SortMap*	iter2	=NULL;
	TaskArray*	pArr	=NULL;
	_task_info*	pinfo	=NULL;

	POSITION	pos1,pos2;

	long		lt;

	int			i;

	//	очистка
	pos1=mapIn.GetStartPosition();
	while(pos1!=NULL)
	{
		mapIn.GetNextAssoc(pos1,lt,(void*&)iter2);
		pos2=iter2->GetStartPosition();
		while(pos2!=NULL)
		{
			iter2->GetNextAssoc(pos2,lt,(void*&)pArr);
			if(TRUE==bDelInfo)
				for(i=0;i<pArr->GetSize();i++)
				{
					pinfo=pArr->GetAt(i);
					delete pinfo;pinfo=NULL;
				}
			pArr->RemoveAll();
			delete pArr;
		}
		iter2->RemoveAll();
		delete iter2;
	}
	mapIn.RemoveAll();
}

void CTaskTimesDialog::SetIterations(void)
{
	//	vars for needed tasks
	SortMap			iter1N;
	SortMap*		iter2N	=NULL;
	TaskArray*		pArrN	=NULL;
	_task_info*		pinfoN	=NULL;

	POSITION		pos1N,pos2N;

	long			lProcId,lActId;

	//	vars for all tasks
	SortMap			iter1A;
	SortMap*		iter2A	=NULL;
	TaskArray*		pArrA	=NULL;
	_task_info*		pinfoA	=NULL;

	TaskArray		taAllTasks;

	int				i,j;

	//	получаем tasks более полно
	{
		aplExtent	ciTemplate;
		aplExtent	ciActivity;
		CaplInstance*	ciPerformer	=NULL;

		aplExtent		aeRes;

		COleDateTime	codt;

		CString			csStartDate,csEndDate;
		CStringArray	csState;

		GetParamsForQuery(ciTemplate,ciActivity,ciPerformer,csState,csStartDate,csEndDate);
		//	сбрасываем csState,ciPerformer,csStartDate,csEndDate - для большей полноты
		ciPerformer=NULL;
		codt.SetDateTime(1900,1,1,0,0,0);aplDate2String(codt,csStartDate);
		codt=COleDateTime::GetCurrentTime();aplDate2String(codt,csEndDate);

		ExecuteQuery(ciTemplate,ciActivity,ciPerformer,csState,csStartDate,csEndDate,aeRes,false);
		SortAndReadData(aeRes,taAllTasks,FALSE);

		//	разбиваем по process и activity
		_Split(taAllTasks,iter1A);
		//	сортируем каждый массив по дате (start_date)
		_Sort(iter1A);
		//	получаем итерацию
		_SetIter(iter1A);
	}

	//	разбиваем по process и activity
	_Split(m_caTasks,iter1N);

	//	получаем итерации из более полного списка
	pos1N=iter1N.GetStartPosition();
	while(NULL!=pos1N)
	{
		iter1N.GetNextAssoc(pos1N,lProcId,(void*&)iter2N);
		pos2N=iter2N->GetStartPosition();
		while(NULL!=pos2N)
		{
			iter2N->GetNextAssoc(pos2N,lActId,(void*&)pArrN);

			iter1A.Lookup(lProcId,(void*&)iter2A);
			iter2A->Lookup(lActId,(void*&)pArrA);

			for(i=0;i<pArrN->GetSize();i++)
			{
				pinfoN=pArrN->GetAt(i);
				for(j=0;j<pArrA->GetSize();j++)
				{
					pinfoA=pArrA->GetAt(j);
					//	сравниваем. должны совпадать все обнуленные переменные
					if(pinfoN->csState==pinfoA->csState && 
					   pinfoN->ciPerformer==pinfoA->ciPerformer &&
					   pinfoN->codtStartDate==pinfoA->codtStartDate &&
					   pinfoN->codtEndDate==pinfoA->codtEndDate)
					{
						pinfoN->iIteration=pinfoA->iIteration;
						break;
					}
				}
			}
		}
	}

	//	очистка
	_ClearMap(iter1N,FALSE);
	_ClearMap(iter1A,TRUE);
}

int __cdecl CTaskTimesDialog::Compare(const void* pstr1, const void* pstr2)
{
	_task_info*		p1		=NULL;
	_task_info*		p2		=NULL;

	CString			t1;
	CString			t2;

	p1=*(_task_info**)pstr1;
	p2=*(_task_info**)pstr2;

	aplDate2String(p1->codtStartDate,t1);
	aplDate2String(p2->codtStartDate,t2);

	return t1.Compare(t2);
}

void CTaskTimesDialog::FillTemplates(void)
{
	aplExtent		aet;
	CaplInstance*	cit		=NULL;
	CString			cst,buf,sTemplatesFilter;;
	int				i,pos;

	m_cbTemplates.ResetContent();
	m_TemplatesMap.Clear();

	pos=m_cbTemplates.AddString(APL_T("Все"));
	m_cbTemplates.SetItemData(pos,(DWORD)NULL);
	m_cbTemplates.SetItemDataPtr(pos,(void*)NULL);
	m_cbTemplates.SetUseSpecialFirstString(true);
	m_cbTemplates.SetAllCategoriesString(APL_T("Все"));	

	m_pApi->m_data.GetEntityExtent(m_wf_mgr->e_proc_tmpl,aet);


	aplQSortByAttr(&(m_pApi->m_data),aet,0,aet.GetSize()-1,m_wf_mgr->a_action_id);

	bool bFilter=false;
	if(m_sTemplatesFilter!=_T(""))
	{
		bFilter=true;
		sTemplatesFilter=m_sTemplatesFilter;
		sTemplatesFilter.MakeLower();
	}
	
	for(i=0;i<aet.GetSize();i++)
	{
		cit=NULL;cst=_T("");

		cit=aet.GetAt(i);
		m_pApi->GetItemName(cit,cst);

		if(bFilter)
		{
			buf=cst; buf.MakeLower();
			if(buf.Find(sTemplatesFilter)<0) continue;
		}

		pos=m_cbTemplates.AddString(cst);
		//pos = i + 1;

		if(m_ciSelTempl==cit)
			m_cbTemplates.SetCheck(pos, true);
		m_TemplatesMap.Add(pos, (long)cit);
	}
	if(!m_ciSelTempl)
		m_cbTemplates.SelectAllCategoriesByFirstString();
	else  
		m_cbTemplates.GetDefaultDropRectHeight(); // ЯАИ: Без этого поле пропадает при ресайзе
}

void CTaskTimesDialog::FillActivities(CaplInstance* ciTemplate)
{
	aplExtent		aet;

	CaplInstance*	cit		=NULL;

	CString			cst;

	int				i,pos;

	m_cbActivities.ResetContent();
	m_ActivitiesMap.Clear();

	pos=m_cbActivities.AddString(APL_T("Все"));

	if(NULL==ciTemplate)
	{
		m_cbActivities.SelectString(-1,APL_T("Все"));
		m_cbActivities.EnableWindow(FALSE);
		return;
	}

	m_cbActivities.SetUseSpecialFirstString(true);
	m_cbActivities.SetAllCategoriesString(APL_T("Все"));

	m_wf_mgr->GetProcessComponents(ciTemplate,aet);

	for(i=0;i<aet.GetSize();i++)
	{
		cit=NULL;cst=_T("");

		cit=aet.GetAt(i);

		if(!m_pApi->m_data.IsKindOf(cit,m_wf_mgr->e_activity))
			continue;

		m_pApi->GetItemName(cit,cst);
		m_cbActivities.AddString(cst);
		m_ActivitiesMap.Add(i+1, (long)cit);
	}

	m_cbActivities.SelectAllCategoriesByFirstString();
	m_cbActivities.EnableWindow(TRUE);
}

void CTaskTimesDialog::FillStates(void)
{
	CString    buf;
	int			i,pos;
	pos=m_cbStates.AddString(APL_T("Все"));

	m_cbStates.SetUseSpecialFirstString(true);
	m_cbStates.SetAllCategoriesString(APL_T("Все"));

	for(i=0;i<m_csRusStates.GetSize();i++)
	{
		pos=m_cbStates.AddString(m_csRusStates[i]);
		m_StatesMap.Add(m_csRusStates[i],i);
	}

	m_cbStates.SelectAllCategoriesByFirstString();
}

void CTaskTimesDialog::ListSetColumns(int mode)
{
	//mode: 0= инициализация, 1-установкаб 2-сохранение
	#define max_columns_count 11
	CString csCN[max_columns_count]={APL_T("Шаблон"),APL_T("Процесс"),APL_T("Работа"),APL_T("Итерация"),APL_T("Состояние"),APL_T("Исполнитель"),APL_T("Треб. длит."),APL_T("Факт. длит."),APL_T("Дата начала"), APL_T("Факт. дата завершения"),APL_T("Треб. дата завершения")};
	int		iSz[max_columns_count]={100,100,100,100,100,100,80,80,100,100,100};

	int		i, j(0);
	if(0==mode) // Инициализация
	{
		// Читаем ширины столбцов

		CWinApp *app=AfxGetApp(); // При вызове из ActiveX возвращает 0
		if(0!=app)
		{
			CString name;
			int w;
			for(i=0;i<sizeof(csCN)/sizeof(CString);i++)
			{
				name=csCN[i];
				name+=_T("_with");
				w=app->GetProfileInt(_T("Workflow\\CTaskTimesDialog\\Columns"),name,0);
				if(w>0) m_iSz[i]=w;
				else m_iSz[i]=iSz[i];
			}
		}
	}

	if(2==mode) // Сохранение
	{
		// Сохраняем флаг отображения столбцов
		for(i=0;i<sizeof(csCN)/sizeof(CString);i++)
		{
			CWinApp *app=AfxGetApp(); // При вызове из ActiveX возвращает 0
			int iIndex= m_amHeader.QFindByIn(i);
			if(iIndex>=0 &&0!=app)
				app->WriteProfileInt(_T("Workflow\\CTaskTimesDialog\\Columns"),csCN[i],m_amHeader[iIndex].out);
		}

		// Сохраняем ширины столбцов
		int w;
		CString name,buf;
		TCHAR *pBuf = new TCHAR[1024];
		HDITEM hdItem;
		hdItem.mask = HDI_TEXT|HDI_WIDTH|HDI_LPARAM;
		hdItem.pszText = pBuf;
		hdItem.cchTextMax = 1024;

		CaplTreeListHeaderCtrl &Header =m_tree_view->m_tree.m_wndHeader;
		int n_coumns=Header.GetItemCount();
		for(i=0;i<n_coumns;i++)
		{
			Header.GetItem(i,&hdItem);
			w=hdItem.cxy;
			name=hdItem.pszText;

			if(w>0 && name!=_T(""))
			{
				for(j=0;j<max_columns_count;j++)
				{
					if(name!=csCN[j]) continue;
					name+=_T("_with");
					CWinApp *app=AfxGetApp(); // При вызове из ActiveX возвращает 0
					if(0!=app) app->WriteProfileInt(_T("Workflow\\CTaskTimesDialog\\Columns"),name,w);
					 m_iSz[j]=w;
					break;
				}
			}
		}
		delete pBuf;

		return;
	}
	
	CWinApp *app=AfxGetApp(); // При вызове из ActiveX возвращает 0

	for(i=0;i<sizeof(csCN)/sizeof(CString);i++)
	{
		int iShow=1;
		if(0==mode && 0!=app) iShow=app->GetProfileInt(_T("Workflow\\CTaskTimesDialog\\Columns"),csCN[i],1);


		//m_lcResults.InsertColumn(i,csCN[i],LVCFMT_LEFT,iSz[i]);
		int iIndex= m_amHeader.QFindByIn(i);
		if(-1==iIndex)
			iIndex= m_amHeader.Add(i, iShow);
		
		if(1==m_amHeader[iIndex].out)
			m_tree_view->m_tree.InsertColumn(j,csCN[i],LVCFMT_LEFT,m_iSz[i]);
		j++;

	}
}

void CTaskTimesDialog::SetItemText(HTREEITEM iPos, int iIndex, int &iColumn, CString& sText)
{
	if(0!=m_amHeader.QGetByIn(iIndex))
	{
		m_tree_view->m_tree.SetItemText(iPos,iColumn,sText);
		iColumn++;
	}
}

void CTaskTimesDialog::ListFillData(void)
{
	CaplInstance*		cit1	=NULL;
	CaplInstance*		cit2	=NULL;

	COleDateTime		codtStart,codt;
	COleDateTimeSpan	codtspan;


	int				i,j(0);//,pos;
	HTREEITEM pos;
	CString buf,sdt;

	_task_info*		pinfo		=NULL;

	//m_lcResults.DeleteAllItems();

	m_tree_view->m_tree.SetRedraw(FALSE);

	m_tree_view->m_tree.DeleteAllItems();
	m_gantt_view->m_gantt.RemoveAllItems();

	m_tree_view->m_tree.DeleteAllColumns();
	ListSetColumns(1);

	for(i=0;i<m_caTasks.GetSize();i++)
	{
		j= 0;
		CString			cst,sTempl,sPrc,sAct;

		pinfo=m_caTasks.GetAt(i);
		//pos=m_lcResults.InsertItem(i,_T(""));
		pos=m_tree_view->m_tree.InsertItem(_T(""));
		m_tree_view->m_tree.SetItemData(pos,(long)pinfo);


		//	шаблон
		m_pApi->GetItemName(pinfo->ciTemplate,sTempl);
		SetItemText(pos, 0, j,sTempl);

		//	процесс
		m_pApi->GetItemName(pinfo->ciProc,sPrc);
		SetItemText(pos, 1, j,sPrc);

		//	работа
		m_pApi->GetItemName(pinfo->ciActivity,sAct);
		SetItemText(pos, 2, j, sAct);

		//	итерация
		cst.Format(_T("%d"),pinfo->iIteration);
		SetItemText(pos, 3, j, cst);
		if(0!=m_amHeader.QGetByIn(3))

		cst=_T("");
		
		//	состояние
		cst=pinfo->csState;
		GetRusState(cst);
		SetItemText(pos, 4, j, cst);
		cst=_T("");

		//	исполнитель
		m_pApi->GetItemName(pinfo->ciPerformer,cst);
		SetItemText(pos, 5, j, cst);
		cst=_T("");

		//	треб. длит.
		if(pinfo->codtNeedTime.m_status!=COleDateTimeSpan::invalid)
		{
			cst=pinfo->codtNeedTime.Format(APL_T("%D дней %H часов %M минут"));
		}
		SetItemText(pos, 6, j, cst);
		cst=_T("");

		//	факт. длит.
		if(pinfo->codtRealTime.m_status!=COleDateTimeSpan::invalid)
		{
			cst=pinfo->codtRealTime.Format(APL_T("%D дней %H часов %M минут"));
		}
		SetItemText(pos, 7, j, cst);
		cst=_T("");

		//	дата начала
		cst=pinfo->codtStartDate.Format(_T("%d/%m/%Y  %H:%M:%S"));
		SetItemText(pos, 8, j, cst);
		//m_lcResults.SetItemText(pos,8,cst);
		cst=_T("");
		//aplDate2String(pinfo->codtStartDate,buf);
		//gi.pl_date_begin=buf;
		//gi.act_date_begin=buf;
		
		//	дата завершения
		if(pinfo->codtEndDate.m_status!=COleDateTime::invalid)
		{
			cst=pinfo->codtEndDate.Format(_T("%d/%m/%Y  %H:%M:%S"));
		}
		SetItemText(pos, 9, j, cst);
		//m_lcResults.SetItemText(pos,9,cst);
		cst=_T("");
		
		//	дата завершения
		if(pinfo->codtEndDateF.m_status!=COleDateTime::invalid)
		{
			cst=pinfo->codtEndDateF.Format(_T("%d/%m/%Y  %H:%M:%S"));
		}
		SetItemText(pos, 10, j, cst);
		//m_lcResults.SetItemText(pos,9,cst);
		cst=_T("");
	}
	m_tree_view->m_tree.SetRedraw(TRUE);
	UpdateGanttView(true);
}

void CTaskTimesDialog::SetAnchors(void)
{
		AddAnchor(ID_TMPL_FILTER_APPLY,TOP_RIGHT);
		AddAnchor(IDC_TMPL_FILTER,TOP_LEFT,TOP_RIGHT);
	//AddAnchor(IDC_GRP_PARAMS,TOP_LEFT,TOP_RIGHT);
		AddAnchor(IDC_T_TEMPLATE,TOP_LEFT);
		AddAnchor(IDC_CB_TEMPLATES,TOP_LEFT,TOP_RIGHT);
		
		AddAnchor(IDC_T_ACTIVITY,TOP_LEFT);
		AddAnchor(IDC_CB_ACTIVITIES,TOP_LEFT,TOP_RIGHT);
		
		AddAnchor(IDC_T_STATE,TOP_LEFT);
		AddAnchor(IDC_CB_STATES,TOP_LEFT,TOP_RIGHT);
		
		AddAnchor(IDC_T_PERFORMER,TOP_LEFT);
		AddAnchor(IDC_E_PERFORMER,TOP_LEFT,TOP_RIGHT);
		AddAnchor(IDC_B_SELECT_PERFORMER,TOP_RIGHT);
		AddAnchor(IDC_B_CLEAR_PERFORMER,TOP_RIGHT);
		
		AddAnchor(IDC_T_DATES,TOP_LEFT);
		AddAnchor(IDC_DT_START_DATE,TOP_LEFT);
		//AddAnchor(IDC_T_DATES_START,TOP_LEFT);
		AddAnchor(IDC_DT_END_DATE,TOP_LEFT);
		AddAnchor(IDC_T_DATES_END,TOP_LEFT);

		AddAnchor(IDC_EXECUTE_LEN,TOP_RIGHT);
		AddAnchor(IDC_ST_EXECUTE_LEN_1,TOP_RIGHT);
		AddAnchor(IDC_ST_EXECUTE_LEN_2,TOP_RIGHT);

		AddAnchor(IDC_OVERDUE,TOP_RIGHT);
		AddAnchor(IDC_ST_OVERDUE_1,TOP_RIGHT);
		AddAnchor(IDC_ST_OVERDUE_2,TOP_RIGHT);
		AddAnchor(IDC_DEADLINE,TOP_RIGHT);
		AddAnchor(IDC_ST_OVERDUE_3,TOP_RIGHT);
		AddAnchor(IDC_ST_OVERDUE_4,TOP_RIGHT);
		AddAnchor(IDC_SHOW_NUM_ITERATION,TOP_RIGHT);

	AddAnchor(IDC_B_SHOW,TOP_LEFT);
	AddAnchor(IDC_B_HEADER,TOP_LEFT);
	AddAnchor(IDC_B_SAVE,BOTTOM_LEFT);
	AddAnchor(IDCANCEL,BOTTOM_RIGHT);
	AddAnchor(ID_SHOW_COLOR_LEGEND,BOTTOM_RIGHT);

	AddAnchor(IDC_TREE_VIEW,TOP_LEFT,BOTTOM_RIGHT);
	AddAnchor(IDC_SPLITTER_BAR,TOP_RIGHT,BOTTOM_RIGHT);
	AddAnchor(IDC_GANTT_VIEW,TOP_RIGHT,BOTTOM_RIGHT);
	
	AddAnchor(IDC_VIEW_MODE,TOP_RIGHT);
	AddAnchor(IDC_ZOOMIN,TOP_RIGHT);
	AddAnchor(IDC_ZOOMOUT,TOP_RIGHT);

}
/////////////////////////////////////////////////////////////////////////////
// CTaskTimesDialog message handlers

BOOL CTaskTimesDialog::OnInitDialog() 
{
	CaplResizableDialog::OnInitDialog();

	m_view_mode_ctrl.ResetContent();
	m_view_mode_ctrl.InsertString(0,APL_T("Годы"));
	m_view_mode_ctrl.InsertString(1,APL_T("Месяцы"));
	m_view_mode_ctrl.InsertString(2,APL_T("Недели"));
	m_view_mode_ctrl.SetCurSel(0);

	m_bShow.SetIcon(GetAplStdIco16(APLSTDICO_PLAY));
	m_bShow.SetFlat(FALSE);

	m_bSave.SetIcon(GetAplTableIco(APL_TABLE_SAVE));
	m_bSave.SetFlat(FALSE);

	m_bHeader.SetIcon(GetAplTableIco(APL_TABLE_FILTER));
	m_bHeader.SetFlat(FALSE);

	m_Cancel.SetIcon(GetAplStdIco16(APLSTDICO_CANCEL));
	m_Cancel.SetFlat(FALSE);

	m_show_color_legend_btn.SetIcon(IDI_SHOW_COLORS);
	m_show_color_legend_btn.SetFlat(FALSE);

	// Создаем диаграмму Ганта

	CRect rect;
	m_tree_border_ctrl.GetWindowRect(&rect);
	ScreenToClient(&rect); 

	m_tree_view = (CaplTreeListCtrlView*)(RUNTIME_CLASS(CaplTreeListCtrlView)->CreateObject());
	ASSERT(m_tree_view);
	m_tree_view->Create(0,0,WS_BORDER|WS_VISIBLE|WS_CHILD|AFX_WS_DEFAULT_VIEW,rect,this,IDC_TREE_VIEW);
	//m_tree_view->m_cImageList.Create(IDR_PROJECT_ICON,20,2,RGB(255,0,255));
	m_tree_view->m_bBreakTooltips=true;
	m_tree_view->OnInitialUpdate();
	m_tree_view->m_tree.m_dlg=(CaplResizableDialog *)this;
	m_tree_view->MoveWindow(&rect);

	//m_tree_view->n_bNoParentNotify=true;
	

	RECT rect0;
	m_gantt_border_ctrl.GetWindowRect(&rect0);
	ScreenToClient(&rect0);
	m_gantt_view = (CWfGanttView*)(RUNTIME_CLASS(CWfGanttView)->CreateObject());
	ASSERT(m_gantt_view);
	m_gantt_view->Create(0,0,WS_BORDER|WS_VISIBLE|WS_CHILD|AFX_WS_DEFAULT_VIEW,rect0,this,IDC_GANTT_VIEW);
	m_gantt_view->m_tree_view=m_tree_view;
	m_gantt_view->m_gantt.m_api=m_pApi;
	m_gantt_view->m_gantt.m_dlg=this;
	m_gantt_view->OnInitialUpdate();
	m_gantt_view->MoveWindow(&rect0);

	m_splitter = new CaplSplitterBar;
	CRect r;
	r.top=rect0.top;
	r.bottom = rect0.bottom;
	r.left = rect.right;
	r.right = rect0.left;
	m_splitter->Create(WS_VISIBLE|WS_CHILD,r,this,IDC_SPLITTER_BAR);
	m_splitter->SetPanes(m_tree_view,m_gantt_view);
	m_splitter->ShowWindow(SW_SHOW);

	SetAnchors();

	m_zoomin_btn.SetFlat(FALSE);
	m_zoomout_btn.SetFlat(FALSE);
	m_zoomin_btn.SetIcon(GetAplStdIco16(APLSTDICO_ZOOM_IN));
	m_zoomout_btn.SetIcon(GetAplStdIco16(APLSTDICO_ZOOM_OUT));
	m_zoomin_btn.SetTooltipText(APL_T("Увеличить масштаб"));
	m_zoomout_btn.SetTooltipText(APL_T("Уменьшить масштаб"));

	FillTemplates();
	FillStates();

	OnSelchangeCbTemplates();

	ListSetColumns(0);
	
	UpdateData(FALSE);

	m_view_mode_ctrl.SetCurSel(1);

	m_gantt_view->m_gantt.m_blockHeight=14;//m_lcResults.

	return TRUE;
}

void CTaskTimesDialog::OnDestroy() 
{
	ListSetColumns(2);
	m_tree_view->m_tree.DeleteAllItems();
	m_gantt_view->m_gantt.RemoveAllItems();
	
	CString*	pcst	=NULL;
	_task_info*	pinfo	=NULL;

	int	i;

	if(0!=m_splitter) delete m_splitter;

	for(i=0;i<m_caTasks.GetSize();i++)
	{
		pinfo=m_caTasks.GetAt(i);
		delete pinfo;pinfo=NULL;
	}

	m_caTasks.RemoveAll();
		
	CaplResizableDialog::OnDestroy();
}

void CTaskTimesDialog::OnBSelectPerformer() 
{
	aplExtent	aet;

	m_ciPerformer=m_pApi->m_appr_mgr.SelectPersonOrOrganization(APL_MODE_SELECT_PERSON|APL_MODE_SELECT_ORG,aet,APL_T("Выберите исполнителя"), _T(""));
	m_pApi->GetItemName(m_ciPerformer,m_csPerformer);
	UpdateData(FALSE);
}

void CTaskTimesDialog::OnBClearPerformer() 
{
	m_ciPerformer=NULL;
	m_csPerformer=_T("");
	UpdateData(FALSE);
}

void CTaskTimesDialog::OnBShow() 
{
	aplExtent	ciTemplate;
	aplExtent	ciActivity;
	CaplInstance*	ciPerformer	=NULL;

	aplExtent		aeRes;

	CStringArray			csState;
	CString			csStartDate,csEndDate;

	UpdateData(TRUE);

	GetParamsForQuery(ciTemplate,ciActivity,ciPerformer,csState,csStartDate,csEndDate);

	if(TRUE==ExecuteQuery(ciTemplate,ciActivity,ciPerformer,csState,csStartDate,csEndDate,aeRes,true))
	{
		SortAndReadData(aeRes,m_caTasks,TRUE);
		ListFillData();
	}
}

void CTaskTimesDialog::OnBSave() 
{
	/*if(apl_SaveListCtrlToFile(&m_lcResults,NULL))
	{
		AfxMessageBox(APL_T("Готово!!!"));
	}*/
	m_tree_view->SaveListDoc();
}

void CTaskTimesDialog::OnBHeader() 
{
	CaplMenu menu;
	menu.CreatePopupMenu();
	
	CString csCN[11]={APL_T("Шаблон"),APL_T("Процесс"),APL_T("Работа"),APL_T("Итерация"),APL_T("Состояние"),APL_T("Исполнитель"),APL_T("Треб. длит."),APL_T("Факт. длит."),APL_T("Дата начала"), APL_T("Факт. дата завершения"), APL_T("Треб. дата завершения")};

	for(int i=0; i<m_amHeader.Size; ++i)
	{
		UINT uiFlag= MF_STRING;
		if(1==m_amHeader[i].out)
			uiFlag|=MF_CHECKED;
		menu.AppendMenu(uiFlag, i+1, csCN[i]);	
	}

	CRect btnRect;
	m_bHeader.GetWindowRect(btnRect);

	int iRes = menu.TrackPopupMenu(TPM_LEFTALIGN | TPM_LEFTBUTTON | TPM_RETURNCMD,
		btnRect.left, btnRect.bottom, this);

	if(0 == iRes)
		return;


	(m_amHeader.Data[iRes-1].out)=1-m_amHeader[iRes-1].out;

	ListSetColumns(2);
	ListFillData();
}

void CTaskTimesDialog::OnSelchangeCbTemplates() 
{
	CaplInstance*	cit		=NULL;
	CString sName;
	aplExtent tasksExt;

	if(m_cbTemplates.GetCheck(0) == TRUE)
	{
		cit= NULL;
	}
	else
	{
		for(int i=1; i<m_cbTemplates.GetCount(); ++i)
		{
			if(m_cbTemplates.GetCheck(i))
			{
				cit=(CaplInstance*)m_TemplatesMap.QGetPointerByIn(i);
				if(cit)
					tasksExt.Add(cit);
			}
		}
	}

	if(tasksExt.GetSize()==1)
		cit= tasksExt[0];

	FillActivities(cit);
}

void CTaskTimesDialog::OnDropdownDtStartDate(NMHDR* pNMHDR, LRESULT* pResult) 
{
	CDateTimeCtrl*	pDTCtrl	=NULL;
	CMonthCalCtrl*	pMCCtrl	=NULL;

	UpdateData(TRUE);

	pDTCtrl=(CDateTimeCtrl*)GetDlgItem(IDC_DT_START_DATE);
	if(NULL==pDTCtrl)
		return;
	pMCCtrl=pDTCtrl->GetMonthCalCtrl();
	if(NULL==pMCCtrl)
		return;

	pMCCtrl->SetRange(NULL,&m_codtEndDate);
	
	*pResult = 0;
}

void CTaskTimesDialog::OnDropdownDtEndDate(NMHDR* pNMHDR, LRESULT* pResult) 
{
	CDateTimeCtrl*	pDTCtrl	=NULL;
	CMonthCalCtrl*	pMCCtrl	=NULL;

	UpdateData(TRUE);

	pDTCtrl=(CDateTimeCtrl*)GetDlgItem(IDC_DT_END_DATE);
	if(NULL==pDTCtrl)
		return;
	pMCCtrl=pDTCtrl->GetMonthCalCtrl();
	if(NULL==pMCCtrl)
		return;

	pMCCtrl->SetRange(&m_codtStartDate,NULL);
	
	*pResult = 0;
}

void CTaskTimesDialog::OnDatetimechangeDtStartDate(NMHDR* pNMHDR, LRESULT* pResult) 
{
	UpdateData(TRUE);

	if(m_codtStartDate>m_codtEndDate)
	{
		m_codtStartDate=m_codtEndDate;
		UpdateData(FALSE);
	}
	
	*pResult = 0;
}

void CTaskTimesDialog::OnDatetimechangeDtEndDate(NMHDR* pNMHDR, LRESULT* pResult) 
{
	UpdateData(TRUE);

	if(m_codtEndDate<m_codtStartDate)
	{
		m_codtEndDate=m_codtStartDate;
		UpdateData(FALSE);
	}
	
	*pResult = 0;
}

void CTaskTimesDialog::OnSelchangeViewMode() 
{
	int view_mode;	
	int cur_sel=m_view_mode_ctrl.GetCurSel();
	if(cur_sel==0) view_mode=APL_MODE_YEARS;
	else if(cur_sel==1) view_mode=APL_MODE_MONTHS;
	else view_mode=APL_MODE_WEEKS;
	m_gantt_view->m_gantt.m_view_mode=view_mode;
	if(view_mode==APL_MODE_YEARS) m_gantt_view->m_gantt.SetPixelsInDay(3);
	else if(view_mode==APL_MODE_MONTHS) m_gantt_view->m_gantt.SetPixelsInDay(6);
	else if(view_mode==APL_MODE_WEEKS) m_gantt_view->m_gantt.SetPixelsInDay(18);
	m_gantt_view->Update(true);
}

void CTaskTimesDialog::OnZoomin() 
{
	if(m_gantt_view->ZoomIn()) m_zoomout_btn.EnableWindow(true);
	else m_zoomin_btn.EnableWindow(false);	
}

void CTaskTimesDialog::OnZoomout() 
{
	if(m_gantt_view->ZoomOut())m_zoomin_btn.EnableWindow(true);
	else m_zoomout_btn.EnableWindow(false);	
}




void CTaskTimesDialog::UpdateGanttView(bool bUpdateCalendar)
{
	if(m_tree_view==0) return;
	
	m_gantt_view->m_gantt.RemoveAllItems();

	HTREEITEM hItem = m_tree_view->m_tree.GetFirstVisibleItem();

	CString sAct, sdt;
	
	int n = m_tree_view->m_tree.GetVisibleCount();

	COleDateTime odt_finish,odt_end;

	CString buf;
	while(hItem!=NULL && n>=0)
	{
		_task_info *pinfo = (_task_info*)m_tree_view->m_tree.GetItemData(hItem);
		if(pinfo==0) continue;

		CGanttItem gi;
		m_pApi->GetItemName(pinfo->ciActivity,sAct);
		gi.name=/*sTempl+ _T(" // ") + sPrc + _T(" // ") +*/ sAct;
		
		m_pApi->m_data.GetAttr(pinfo->ciTask,m_wf_mgr->a_act_inst_start_date,sdt);
		//aplString2Date(sdt,gi.pl_date_begin);
		gi.pl_date_begin=sdt;
		gi.act_date_begin=sdt;

		//aplString2Date(sdt,gi.pl_date_end);
		m_pApi->m_data.GetAttr(pinfo->ciTask,m_wf_mgr->a_act_inst_finish_date, sdt);
		gi.pl_date_end=sdt;

		aplString2Date(sdt,odt_finish);

		m_pApi->m_data.GetAttr(pinfo->ciTask,m_wf_mgr->a_act_inst_end_date,sdt);
		gi.act_date_end=sdt;
		
	
		m_pApi->m_data.GetAttr(pinfo->ciTask,m_wf_mgr->a_act_inst_end_date,sdt);
		gi.pl_date_end=sdt;

		m_pApi->m_data.GetAttr(pinfo->ciTask,m_wf_mgr->a_act_inst_percent,gi.percentage);

		gi.hTreeItem=hItem;

		COLORREF color0=gi.color; // Голубой в ганте
		COLORREF color1=gi.color;
		m_wf_mgr->GetItemColor(pinfo->ciTask,color1);

		if(color1!=RGB(0,0,0))
		{
			gi.color=aplColor_GetHilightColor(color1,50);
		}

		m_gantt_view->m_gantt.m_items.Add(gi);

		if(color0!=gi.color) //
			m_tree_view->m_tree.SetItemColor(hItem,color1,false);

		hItem = m_tree_view->m_tree.GetNextVisibleItem(hItem);
		n--;
	}
	m_gantt_view->m_gantt.UpdateCalendar(true);
	m_gantt_view->Update(bUpdateCalendar);
}


void CTaskTimesDialog::Sort(int nCol)
{
	UpdateGanttView();
}



void CTaskTimesDialog::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar) 
{
	// TODO: Add your message handler code here and/or call default
	
	//CaplResizableDialog::OnVScroll(nSBCode, nPos, pScrollBar);
	UpdateGanttView(false);
}

void CTaskTimesDialog::OnSize(UINT nType, int cx, int cy) 
{
	CaplResizableDialog::OnSize(nType, cx, cy);
	
	// TODO: Add your message handler code here

	UpdateGanttView(false);

	if(m_cbTemplates.GetSafeHwnd())
		m_cbTemplates.SetDropDownHeight();

	if(m_cbActivities.GetSafeHwnd() && m_cbActivities.IsWindowEnabled())
		m_cbActivities.SetDropDownHeight();			

	if(m_cbStates.GetSafeHwnd())
		m_cbStates.SetDropDownHeight();

	if(0!=m_splitter) m_splitter->UpdatePanesLimits();
}


void CTaskTimesDialog::OnSelChanged()
{
	if(m_tree_view!=0) m_gantt_view->Update(false);
}


void CTaskTimesDialog::OnBnClickedShowColorLegend()
{
	m_wf_mgr->ShowColorLegend();
}


void CTaskTimesDialog::OnBnClickedTmplFilterApply()
{
	CString buf;
	m_tmpl_filter_ctrl.GetWindowText(buf);
	buf.TrimLeft(); buf.TrimRight();

	if(m_sTemplatesFilter==buf) return;

	m_sTemplatesFilter=buf;
	FillTemplates();
	OnSelchangeCbTemplates();
}
