// SelectPecipientsDlg.cpp : implementation file
//

#include "stdafx.h"
#include "icons_defines.h"
#include "SelectPecipientsDlg.h"
#include "apl_api.h"
#include "aplOrgStructHelper.h"
#include "OrganizationPropDlg.h"
#include "PersonPropDlg.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
int CALLBACK CSelectRecipientsDlg::CompareTreeItems(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
{
	if(lParam1==0) return 0;
	if(lParam2==0) return 0;

	CaplAutorizationManager *m_autMgr=(CaplAutorizationManager*)lParamSort;
	if(m_autMgr==0) return 0;
	CaplNetStepData *data= m_autMgr->m_data;
	if(data==0) return 0;
	
	CaplInstance* inst1= (CaplInstance* )lParam1;
	CaplInstance* inst2= (CaplInstance* )lParam2;

	int type1= 0, type2= 0;
	if(data->IsKindOf(inst1, m_autMgr->e_org)) type1=2;
	else if(data->IsKindOf(inst1, m_autMgr->e_official)) type1=1;
	if(data->IsKindOf(inst2, m_autMgr->e_org)) type2=2;
	else if(data->IsKindOf(inst2, m_autMgr->e_official)) type2=1;

	if(type1<type2) return 1;
	else if(type1>type2) return  -1;
	
	CString name1, name2;
	if(type1==2)
	{
		data->GetAttr(inst1, m_autMgr->a_org_name, name1);
		data->GetAttr(inst2, m_autMgr->a_org_name, name2);
	}
	else if(type1==1)
	{
		data->GetAttr(inst1, m_autMgr->a_official_id, name1);
		data->GetAttr(inst2, m_autMgr->a_official_id, name2);
	}
	else
	{
		if(data->IsKindOf(inst1, m_autMgr->e_pers_org))
			data->GetAttr(inst1, m_autMgr->a_po_the_pers, inst1);
		data->GetAttr(inst1, m_autMgr->a_pers_last_name, name1);
		
		if(data->IsKindOf(inst2, m_autMgr->e_pers_org))
			data->GetAttr(inst2, m_autMgr->a_po_the_pers, inst2);
		data->GetAttr(inst2, m_autMgr->a_pers_last_name, name2);
	}	
	return name1.Compare(name2);
}
///////////////////////////////////////////////////////////////////////////////////////////
int CALLBACK CompareListItems(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
{
	if(lParam1==0) return 0;
	if(lParam2==0) return 0;
	CaplAutorizationManager *m_autMgr=(CaplAutorizationManager*)lParamSort;
	if(m_autMgr==0) return 0;
	CaplNetStepData *data= m_autMgr->m_data;
	if(data==0) return 0;
	
	CaplInstance* inst1= (CaplInstance* )lParam1;
	CaplInstance* inst2= (CaplInstance* )lParam2;
	

	int type1= 0, type2= 0;

	if(data->IsKindOf(inst1, m_autMgr->e_org)) type1=2;
	else if(data->IsKindOf(inst1, m_autMgr->e_official)) type1=1;
	if(data->IsKindOf(inst2, m_autMgr->e_org)) type2=2;
	else if(data->IsKindOf(inst2, m_autMgr->e_official)) type2=1;

	if(type1<type2) return 1;
	else if(type1>type2) return  -1;

	CString name1, name2;
	if(type1==2)
	{
		data->GetAttr(inst1, m_autMgr->a_org_name, name1);
		data->GetAttr(inst2, m_autMgr->a_org_name, name2);
	}
	else if(type1==1)
	{
		data->GetAttr(inst1, m_autMgr->a_official_id, name1);
		data->GetAttr(inst2, m_autMgr->a_official_id, name2);
	}
	else
	{
		if(data->IsKindOf(inst1, m_autMgr->e_pers_org))
			data->GetAttr(inst1, m_autMgr->a_po_the_pers, inst1);
		data->GetAttr(inst1, m_autMgr->a_pers_last_name, name1);
		
		if(data->IsKindOf(inst2, m_autMgr->e_pers_org))
			data->GetAttr(inst2, m_autMgr->a_po_the_pers, inst2);
		data->GetAttr(inst2, m_autMgr->a_pers_last_name, name2);
	}	
	return name1.Compare(name2);
}

/////////////////////////////////////////////////////////////////////////////
// CSelectRecipientsDlg dialog


CSelectRecipientsDlg::CSelectRecipientsDlg(CWnd* pParent /*=NULL*/)
	: CResizableDialog(CSelectRecipientsDlg::IDD, pParent)
{
	//{{AFX_DATA_INIT(CSelectRecipientsDlg)
	m_sTreeTitle = _T("");
	//}}AFX_DATA_INIT
	
	m_allGroups= 0;
	m_myGroups= 0;
	
	m_api=NULL;
	m_curPerson= NULL;
	m_inst= NULL;
	
	m_bShowPerWG= true;
	m_bResized= false;
	m_bTraverseTree= true;
	m_bSingleSelect= false;
	m_bDblCl= false;
	m_bExpand= false;
	
	m_mode= APL_MODE_SELECT_PERSON;//person'ы для Сообщений

	m_sTitle= _T("");

	m_helper = new CaplOrgStructHelper;
}

CSelectRecipientsDlg::~CSelectRecipientsDlg()
{
	if(m_helper) delete m_helper;
}

void CSelectRecipientsDlg::DoDataExchange(CDataExchange* pDX)
{
	CResizableDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CSelectRecipientsDlg)
	DDX_Control(pDX, IDC_BUTTON4_FBEG, m_btnFBegin);
	DDX_Control(pDX, IDC_BUTTON3_FBACK, m_btnFBack);
	DDX_Control(pDX, IDC_BUTTON2_FFORW, m_btnFForward);
	DDX_Control(pDX, IDC_EDIT1_FVAL, m_edFindStr);
	DDX_Control(pDX, IDC_MAIN_STATIC, m_mainStatic);
	DDX_Control(pDX, IDC_POS_STATIC, m_poStatic);
	DDX_Control(pDX, IDC_RECIPIENTS_LIST, m_listCtrl);
	DDX_Control(pDX, IDC_PERSON_ORG_TREE, m_treeCtrl);
	DDX_Control(pDX, IDCANCEL, m_cancelBtn);
	DDX_Control(pDX, IDOK, m_okBtn);
	DDX_Control(pDX, IDC_REC_DELETE_BUTTON, m_deleteBtn);
	DDX_Control(pDX, IDC_REC_ADD_BUTTON, m_addBtn);
	DDX_Control(pDX, IDC_REC_FIND_BUTTON, m_findBtn);
	DDX_Text(pDX, IDC_TREE_STATIC, m_sTreeTitle);
	//}}AFX_DATA_MAP
}


BEGIN_MESSAGE_MAP(CSelectRecipientsDlg, CResizableDialog)
	//{{AFX_MSG_MAP(CSelectRecipientsDlg)
	ON_BN_CLICKED(IDC_REC_ADD_BUTTON, OnAddButton)
	ON_BN_CLICKED(IDC_REC_DELETE_BUTTON, OnDeleteButton)
	ON_NOTIFY(TVN_ITEMEXPANDED, IDC_PERSON_ORG_TREE, OnItemexpandedPersonOrgTree)
	ON_BN_CLICKED(IDC_REC_FIND_BUTTON, OnRecFindButton)
	ON_NOTIFY(NM_DBLCLK, IDC_PERSON_ORG_TREE, OnDblclkPersonOrgTree)
	ON_NOTIFY(TVN_ITEMEXPANDING, IDC_PERSON_ORG_TREE, OnItemexpandingPersonOrgTree)
	ON_NOTIFY(TVN_SELCHANGED, IDC_PERSON_ORG_TREE, OnSelchangedPersonOrgTree)
	ON_BN_CLICKED(IDC_BUTTON2_FFORW, OnFindForward)
	ON_BN_CLICKED(IDC_BUTTON3_FBACK, OnFindBack)
	ON_BN_CLICKED(IDC_BUTTON4_FBEG, OnButton4Beg)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CSelectPecipientsDlg message handlers

void CSelectRecipientsDlg::SetAnchors()
{
	AddAnchor(IDOK, BOTTOM_RIGHT);
	AddAnchor(IDCANCEL, BOTTOM_RIGHT);
	
	AddAnchor(IDC_MAIN_STATIC, TOP_LEFT, BOTTOM_RIGHT);		
	
	if(m_bSingleSelect)
	{
		AddAnchor(IDC_PERSON_ORG_TREE, TOP_LEFT, BOTTOM_RIGHT);		
		AddAnchor(IDC_POS_STATIC, TOP_RIGHT);

		AddAnchor(IDC_STATIC_FCAP,BOTTOM_LEFT);
		AddAnchor(IDC_EDIT1_FVAL,BOTTOM_LEFT,BOTTOM_RIGHT);
		AddAnchor(IDC_BUTTON2_FFORW,BOTTOM_RIGHT);
		AddAnchor(IDC_BUTTON3_FBACK,BOTTOM_RIGHT);
		AddAnchor(IDC_BUTTON4_FBEG,BOTTOM_RIGHT);
	}
	else
	{
		AddAnchor(IDC_RECIPIENTS_LIST, TOP_CENTER, BOTTOM_RIGHT);
		AddAnchor(IDC_REC_ADD_BUTTON, MIDDLE_CENTER);
		AddAnchor(IDC_REC_DELETE_BUTTON, MIDDLE_CENTER);
		AddAnchor(IDC_POS_STATIC, TOP_CENTER);
		AddAnchor(IDC_PERSON_ORG_TREE, TOP_LEFT, BOTTOM_CENTER);

		AddAnchor(IDC_STATIC_FCAP,BOTTOM_LEFT);
		AddAnchor(IDC_EDIT1_FVAL,BOTTOM_LEFT,BOTTOM_CENTER);
		AddAnchor(IDC_BUTTON2_FFORW,BOTTOM_CENTER);
		AddAnchor(IDC_BUTTON3_FBACK,BOTTOM_CENTER);
		AddAnchor(IDC_BUTTON4_FBEG,BOTTOM_CENTER);
	
	}
}

BOOL CSelectRecipientsDlg::OnInitDialog() 
{
	int cx=278;
	RECT rect;

	if(m_bSingleSelect)
	{
		GetWindowRect(&rect);
		rect.right-=cx;
		SetWindowPos(&wndTop, rect.left, rect.top, 
			rect.right-rect.left, rect.bottom-rect.top, NULL);
	}

	CResizableDialog::OnInitDialog();
	ModifyStyleEx(0, WS_EX_DLGMODALFRAME | WS_EX_WINDOWEDGE | WS_EX_CONTROLPARENT);   
	ModifyStyle(0, WS_MAXIMIZEBOX);   

	
	
	m_cancelBtn.SetIcon(GetAplStdIco16(APLSTDICO_CANCEL));
	m_cancelBtn.SetFlat(FALSE);
	m_okBtn.SetIcon(GetAplStdIco16(APLSTDICO_OK));
	m_okBtn.SetFlat(FALSE);
	m_addBtn.SetIcon(GetAplStdIco16(APLSTDICO_PLAY));
	m_addBtn.SetFlat(FALSE);
	m_deleteBtn.SetIcon(GetAplStdIco16(APLSTDICO_REVERSE_PLAY));
	m_deleteBtn.SetFlat(FALSE);
	m_findBtn.SetAlign(m_findBtn.ST_ALIGN_HORIZ_RIGHT);
	m_findBtn.SetIcon(GetAplTableIco(APL_TABLE_SELECT_DOWN));
	m_findBtn.SetFlat(FALSE);
	
	m_btnFForward.SetIcon(GetAplTableIco(APL_TABLE_BOTTOM));
	m_btnFBack.SetIcon(GetAplTableIco(APL_TABLE_TOP));
	m_btnFBegin.SetIcon(GetAplTableIco(APL_TABLE_RIGHT));

	m_btnFForward.SetFlat(FALSE);
	m_btnFBack.SetFlat(FALSE);
	m_btnFBegin.SetFlat(FALSE);

	m_btnFForward.SetTooltipText( APL_T("Найти следущий (F3)"));
	m_btnFBack.SetTooltipText( APL_T("Найти предыдущий (Ctrl+F3)"));
	m_btnFBegin.SetTooltipText( APL_T("Сначала"));
	
	if(m_api /*&& apidata.IsConnected()*/)
	{
		m_imageListList.Create(aplGetInstImageList());
		m_imageListTree.Create(aplGetInstImageList());
		
//		m_listCtrl.SetImageList(aplGetInstImageList(), LVSIL_SMALL);
//		m_treeCtrl.SetImageList(aplGetInstImageList(), TVSIL_NORMAL);
		m_treeCtrl.SetImageList(&m_imageListTree, TVSIL_NORMAL);
		m_listCtrl.SetImageList(&m_imageListList, LVSIL_SMALL);
		
		if(m_sTitle!=_T("")) SetWindowText(m_sTitle);

		m_helper->SetApi(m_api);
		
		if(m_bSingleSelect)
		{
			m_cancelBtn.GetWindowRect(&rect);
			rect.left-=cx;
			rect.right-=cx;
			ScreenToClient(&rect);
			m_cancelBtn.MoveWindow(&rect);

			m_okBtn.GetWindowRect(&rect);
			rect.left-=cx;
			rect.right-=cx;
			ScreenToClient(&rect);
			m_okBtn.MoveWindow(&rect);
			m_okBtn.EnableWindow(FALSE);
			
			m_mainStatic.GetWindowRect(&rect);
			rect.right-=cx;
			ScreenToClient(&rect);
			m_mainStatic.MoveWindow(&rect);

			m_listCtrl.ShowWindow(SW_HIDE);
			m_poStatic.ShowWindow(SW_HIDE);
			m_addBtn.ShowWindow(SW_HIDE);
			m_deleteBtn.ShowWindow(SW_HIDE);

//			FillTreeForSingleSelection();

			m_allGroups= TVI_ROOT;
			bool bWithPers = ((m_mode & APL_MODE_SELECT_PERSON) != 0);
			bool bWithOffc = ((m_mode&APL_MODE_SELECT_OFFICIAL) != 0);
			bool bPO = ((m_mode&APL_MODE_SELECT_PERSORG) != 0);

			m_helper->FillTree(m_treeCtrl, m_poExt, bWithPers, bWithOffc, false, false, bPO);
		//	FillTree(m_poExt);
			HTREEITEM hi=m_treeCtrl.GetChildItem(TVI_ROOT);
			if(hi!=0) m_treeCtrl.SelectItem(hi);
		}
		else
		{
			bool bWithPers = ((m_mode & APL_MODE_SELECT_PERSON) != 0);
			bool bWithOffc = ((m_mode&APL_MODE_SELECT_OFFICIAL) != 0);
			bool bPO = false;//((m_mode&APL_MODE_SELECT_PERSORG) != 0);
			bool bShowAllWG=true;
			if(m_poExt.Size!=0) bShowAllWG=false;
			m_helper->FillTree(m_treeCtrl, m_poExt, bWithPers, bWithOffc, m_bShowPerWG, bShowAllWG, false);


/*
			if(m_bShowPerWG)
			{
				m_myGroups= m_treeCtrl.InsertItem(APL_T("Мои рабочие группы"), ICON_ORGANIZATION, 
					ICON_ORGANIZATION, 0);
			}
			m_allGroups= m_treeCtrl.InsertItem(APL_T("Все рабочие группы"), ICON_ORGANIZATION, 
				ICON_ORGANIZATION, 0);
			
			FillTree(m_poExt);
*/
			FillRecipientsList();
			HTREEITEM hi=m_treeCtrl.GetChildItem(TVI_ROOT);
			if(hi!=0) m_treeCtrl.SelectItem(hi);
		}

	//	m_treeCtrl.Expand(m_myGroups,TVE_EXPAND);
	//	m_treeCtrl.Expand(m_allGroups,TVE_EXPAND);

		UpdateData(FALSE);
	}

	SetAnchors();	
	
	return TRUE;  // return TRUE unless you set the focus to a control
	              // EXCEPTION: OCX Property Pages should return FALSE
}

void CSelectRecipientsDlg::OnOK() 
{	
	// в зависимости от того, где сейчас фокус ввода
	CWnd *focusWnd = GetFocus();

	if(focusWnd == &m_edFindStr)
	{
		if(::GetKeyState( VK_CONTROL ) < 0 )
		{
			OnAddButton();
			m_edFindStr.SetFocus();
		}
		else
		{
			CString filter;
			m_edFindStr.GetWindowText(filter);

			if(filter.IsEmpty() == false)
				OnFindForward();
		}		

		return;
	}
	else if(focusWnd == &m_treeCtrl)
	{
		OnAddButton();
		return;
	}

	CResizableDialog::OnOK();
}

void CSelectRecipientsDlg::OnCancel() 
{	
	CResizableDialog::OnCancel();
}

void CSelectRecipientsDlg::AddItem(HTREEITEM item, bool bAddAll)
{
	if(item==0) return;
	
	CaplInstance  *inst= (CaplInstance*)m_treeCtrl.GetItemData(item);
	CaplInstance  *addedInst= NULL;
	if(inst)
	{
		if(apidata.IsKindOf(inst, m_api->m_appr_mgr.e_pers_org))
		{
			if((m_mode&APL_MODE_SELECT_PERSORG)!=0){addedInst= inst;}
			else
			{
				apidata.GetAttr(inst, m_api->m_appr_mgr.a_po_the_pers, inst);
				
				if(apidata.IsKindOf(inst, m_api->m_appr_mgr.e_person))
				{
					if((m_mode&APL_MODE_SELECT_PERSON)!=0) addedInst= inst;
				}
				else if(apidata.IsKindOf(inst, m_api->m_appr_mgr.e_official))
				{
					if((m_mode&APL_MODE_SELECT_OFFICIAL)!=0) addedInst= inst;
				}
			}
		}
		else if(apidata.IsKindOf(inst, m_api->m_appr_mgr.e_org))
		{
			if((m_mode&APL_MODE_SELECT_ORG)>0){addedInst= inst;}
		}
		else
		{
			if(apidata.IsKindOf(inst, m_api->m_appr_mgr.e_person))
			{
				if((m_mode&APL_MODE_SELECT_PERSON)!=0) addedInst= inst;
			}
			else if(apidata.IsKindOf(inst, m_api->m_appr_mgr.e_official))
			{
				if((m_mode&APL_MODE_SELECT_OFFICIAL)!=0) addedInst= inst;
			}
		}
		if(addedInst && -1==m_resExt.Find(addedInst))
		{
			m_resExt.Add(addedInst);
		}
	}
	if(bAddAll)
	{
		if (m_treeCtrl.ItemHasChildren(item))
		{
			HTREEITEM hNextItem;
			HTREEITEM hChildItem= m_treeCtrl.GetChildItem(item);

			while(hChildItem!=NULL)
			{
				AddItem(hChildItem,bAddAll);
				hNextItem= m_treeCtrl.GetNextItem(hChildItem, TVGN_NEXT);
				hChildItem= hNextItem;
			}
		}
	}

}
void CSelectRecipientsDlg::OnAddButton() 
{
	HTREEITEM item= m_treeCtrl.GetSelectedItem();
	if(item)
	{
		AddItem(item,m_bTraverseTree);
		FillRecipientsList();
	}
}

void CSelectRecipientsDlg::OnDeleteButton() 
{
	POSITION pos = m_listCtrl.GetFirstSelectedItemPosition();
	if (pos)
	{
		while (pos)
		{
			int nItem = m_listCtrl.GetNextSelectedItem(pos);
			m_resExt.Remove(m_resExt.Find((CaplInstance*)m_listCtrl.GetItemData(nItem)));
		}
	}
	FillRecipientsList();
}

void CSelectRecipientsDlg::FillTree(aplExtent &RootItems)
{
	aplExtent Relationship, Persons, AlongPersons, AlongOfficial, 
		ext_person, //сотрудники
		ext_org; //организации
	aplExtent personWg;
	CArray<HTREEITEM, HTREEITEM> 
		ahRootItems, //
		ahOtherItems, 
		ahRootPerItems,
		ahPerItems;
	CaplInstance* pInst, *pInst1;
	CaplAggr aggr0;
	CString sStr, buf;
	int i, j, n;
	
	bool bIsInPersonGroup;
	
	apidata.GetEntityExtent(m_api->m_appr_mgr.e_org_rel, Relationship);
	apidata.GetEntityExtent(m_api->m_appr_mgr.e_pers_org, Persons);
	apidata.GetEntityExtent(m_api->m_appr_mgr.e_person, AlongPersons);
	apidata.GetEntityExtent(m_api->m_appr_mgr.e_official, AlongOfficial);
	
	m_treeCtrl.SetRedraw(FALSE);
	
	if(!RootItems.GetSize())
	{
		//Определение корневых элементов.
		apidata.GetEntityExtent(m_api->m_appr_mgr.e_org, RootItems);
		for(i= 0; i<RootItems.GetSize(); i++)
		{
			for(j= 0; j<Relationship.GetSize(); j++)
			{
				apidata.GetAttr(Relationship[j], m_api->m_appr_mgr.a_org_rel_related, pInst);
				if(RootItems[i]==pInst)
				{
/*					CString sEndDate;
					apidata.GetAttr(Persons[j], m_api->m_appr_mgr.a_po_end_date, sEndDate);
					if(!sEndDate.IsEmpty()) continue;//сотрудника удалили*/

					RootItems.Remove(i);
					i--;
					break;
				}
			}
		}
		if(!((m_mode&APL_MODE_SELECT_PERSORG)>0))
		{
			for(i= 0; i<AlongPersons.GetSize(); i++)
			{
				for(j= 0; j<Persons.GetSize(); j++)
				{
					apidata.GetAttr(Persons[j], m_api->m_appr_mgr.a_po_the_pers, pInst);
					if(AlongPersons[i]==pInst)
					{
						
						CString sEndDate;
						apidata.GetAttr(Persons[j], m_api->m_appr_mgr.a_po_end_date, sEndDate);
						if(!sEndDate.IsEmpty()) continue;//сотрудника удалили
						AlongPersons.Remove(i);
						i--;
						break;
					}
				}
			}
			for(i= 0; i<AlongOfficial.GetSize(); i++)
			{
				for(j= 0; j<Persons.GetSize(); j++)
				{
					apidata.GetAttr(Persons[j], m_api->m_appr_mgr.a_po_the_pers, pInst);
					if(AlongOfficial[i]==pInst)
					{
						CString sEndDate;
						apidata.GetAttr(Persons[j], m_api->m_appr_mgr.a_po_end_date, sEndDate);
						if(!sEndDate.IsEmpty()) continue;//сотрудника удалили

						AlongOfficial.Remove(i);
						i--;
						break;
					}
				}
			}
			RootItems.Append(AlongPersons);
			RootItems.Append(AlongOfficial);
		}
	}
	
	CaplMap clds_map;
	aplExtent orgs;
	CItemChilds* childs;

	CString sEndDate;

	m_api->m_data.GetEntityExtent(m_api->m_appr_mgr.e_org, orgs);
	for(i= 0; i<orgs.GetSize(); i++)
	{
		childs= new CItemChilds;
		childs->m_inst= orgs[i];
		clds_map.Add((long)orgs[i], (long)childs);
	}
		
	clds_map.SortIn();

	for(i= 0; i<Relationship.GetSize(); i++)
	{
		m_api->m_data.GetAttr(Relationship[i], m_api->m_appr_mgr.a_org_rel_relating, pInst);
		if(0==pInst) continue; 
		childs= (CItemChilds*)clds_map.QGetPointerByIn((long)pInst);
		if(!childs) continue;

		m_api->m_data.GetAttr(Relationship[i], m_api->m_appr_mgr.a_org_rel_related, pInst);
		if(pInst)
		{
			childs->m_childs.Add(pInst);
			childs->m_bRoot= false;
		}
	}

	for(i= 0; i<Persons.GetSize(); i++)
	{
		m_api->m_data.GetAttr(Persons[i], m_api->m_appr_mgr.a_po_the_org, pInst);
		if(0==pInst) continue;
		childs= (CItemChilds*)clds_map.QGetPointerByIn((long)pInst);
		if(!childs) continue;
		
		
		m_api->m_data.GetAttr(Persons[i], m_api->m_appr_mgr.a_po_end_date, sEndDate);
		if(!sEndDate.IsEmpty()) continue;//сотрудника удалили
		
		m_api->m_data.GetAttr(Persons[i], m_api->m_appr_mgr.a_po_the_pers, pInst);
		if(0==pInst) continue;

		if(m_api->m_data.IsKindOf(pInst, m_api->m_appr_mgr.e_person))
		{
			if((m_mode&APL_MODE_SELECT_PERSON)==0 && (m_mode&APL_MODE_SELECT_PERSORG)==0) continue;
		}
		else if(apidata.IsKindOf(pInst ,m_api->m_appr_mgr.e_official))
		{
			if((m_mode&APL_MODE_SELECT_OFFICIAL)==0) continue;
		}
	
		childs->m_childs.Add(pInst);
		childs->m_bRoot= false;
		if(pInst==m_curPerson)
			childs->m_bMyGroup= true;
	}

	//Построение корневых элементов
	for (i= 0; i<RootItems.GetSize(); i++)
	{		
		HTREEITEM hItem, hPerItem;
		int nImage;

		if(RootItems[i]->GetAccessmode()>aplRO) continue;

		if(apidata.IsKindOf(RootItems[i],m_api->m_appr_mgr.e_org))
		{
			nImage= ICON_ORGANIZATION;

//			apidata.GetAttr(RootItems[i], m_api->m_appr_mgr.a_org_name, sStr);
//			m_api->m_appr_mgr.GetItemName(RootItems[i],sStr);
			m_api->GetItemName(RootItems[i],sStr);

			if(!sStr.CompareNoCase( APL_NO_T("Удаленные"))) continue;
		}
		else if(apidata.IsKindOf(RootItems[i],m_api->m_appr_mgr.e_person))
		{
			if((m_mode&APL_MODE_SELECT_PERSON)==0 && (m_mode&APL_MODE_SELECT_PERSORG)==0) continue;
			nImage= ICON_PERSON;
			m_api->m_appr_mgr.GetPersonName(RootItems[i],sStr);
		}
		else if(apidata.IsKindOf(RootItems[i],m_api->m_appr_mgr.e_official))
		{
			if((m_mode&APL_MODE_SELECT_OFFICIAL)==0) continue;
			nImage= ICON_OFFICIAL;
			m_api->m_appr_mgr.GetPersonName(RootItems[i],sStr);
		}
		else
			continue;
		
		hItem= m_treeCtrl.InsertItem(sStr, nImage, nImage, m_allGroups);
		ahRootItems.Add(hItem);
		m_treeCtrl.SetItemData(hItem, (DWORD)RootItems[i]);
		
		bIsInPersonGroup= false;
		ext_person.Clear();

		for(j=0; j<Persons.GetSize(); j++)
		{
			if(Persons[j]->GetAccessmode()>aplRO) continue;

			apidata.GetAttr(Persons[j], m_api->m_appr_mgr.a_po_the_org, pInst);
			if(RootItems[i]==pInst)
			{
				CString sEndDate;
				apidata.GetAttr(Persons[j], m_api->m_appr_mgr.a_po_end_date, sEndDate);
				if(!sEndDate.IsEmpty()) continue;//сотрудника удалили

				int nImage=0;
				CaplInstance* pInst1= NULL;

				apidata.GetAttr(Persons[j], m_api->m_appr_mgr.a_po_the_pers, pInst1);
				if(0==pInst1) continue;

				if(apidata.IsKindOf(pInst1,m_api->m_appr_mgr.e_person))
				{
					if((m_mode&APL_MODE_SELECT_PERSON)==0 && (m_mode&APL_MODE_SELECT_PERSORG)==0) continue;
					m_api->m_appr_mgr.GetPersonName(pInst1,sStr);
					nImage=ICON_PERSON;
					
					if(pInst1==m_curPerson)
						bIsInPersonGroup= true;
				}
				else if(apidata.IsKindOf(pInst1,m_api->m_appr_mgr.e_official))
				{
					if((m_mode&APL_MODE_SELECT_OFFICIAL)==0) continue;
					nImage= ICON_OFFICIAL;
					m_api->m_appr_mgr.GetPersonName(pInst1,sStr);
				}
				else continue;

				ext_person.Add(Persons[j]);
				hPerItem= m_treeCtrl.InsertItem(sStr, nImage, nImage, hItem);
				m_treeCtrl.SetItemData(hPerItem, (DWORD)Persons[j]);
//				Persons.Remove(j);
//				j--;
			}
		}
		
		//входит в группу - помещаем в список Мои рабочие группы
		if(bIsInPersonGroup && m_bShowPerWG && -1==personWg.Find(RootItems[i]))
		{
			personWg.Add(RootItems[i]);


		//	apidata.GetAttr(RootItems[i], m_api->m_appr_mgr.a_org_name, sStr);
		//	m_api->m_appr_mgr.GetItemName(RootItems[i],sStr);
			m_api->GetItemName(RootItems[i],sStr);


			HTREEITEM hPerItem1= m_treeCtrl.InsertItem(sStr, ICON_ORGANIZATION, 
				ICON_ORGANIZATION, m_myGroups);
			m_treeCtrl.SetItemData(hPerItem1, (DWORD)RootItems[i]);
			
			ahRootPerItems.Add(hPerItem1);
			
			for(int n= 0; n<ext_person.GetSize(); n++)
			{
				if(ext_person[n]->GetAccessmode()>aplRO) continue;

				apidata.GetAttr(ext_person[n], m_api->m_appr_mgr.a_po_the_pers, pInst);

				int nImage=0;
				if(apidata.IsKindOf(pInst,m_api->m_appr_mgr.e_person))
				{
					if((m_mode&APL_MODE_SELECT_PERSON)==0 && (m_mode&APL_MODE_SELECT_PERSORG)==0) continue;
					m_api->m_appr_mgr.GetPersonName(pInst,sStr);
					nImage=ICON_PERSON;
				}
				else if(apidata.IsKindOf(pInst,m_api->m_appr_mgr.e_official))
				{
					if((m_mode&APL_MODE_SELECT_OFFICIAL)==0) continue;
					nImage= ICON_OFFICIAL;
					m_api->m_appr_mgr.GetPersonName(pInst,sStr);
				}
				else continue;

				HTREEITEM hItem1= m_treeCtrl.InsertItem(sStr, nImage, nImage, hPerItem1);
				m_treeCtrl.SetItemData(hItem1, (DWORD)ext_person[n]);				
			}
		}
	}//for (i= 0; i<RootItems.GetSize(); i++)

	if(m_bExpand)m_treeCtrl.Expand(m_allGroups, TVE_EXPAND);

	//Построение всех остальных элементов
	while(ahRootItems.GetSize())
	{
		for(i= 0; i<ahRootItems.GetSize(); i++)
		{
			CaplInstance* pInstRoot = (CaplInstance*)m_treeCtrl.GetItemData(ahRootItems[i]);
			
			bIsInPersonGroup= false;
			ext_person.Clear();
			ext_org.Clear();

			for(j= 0; j<Relationship.GetSize(); j++)
			{
				apidata.GetAttr(Relationship[j], m_api->m_appr_mgr.a_org_rel_relating, pInst);
				if (pInstRoot == pInst)
				{
					apidata.GetAttr(Relationship[j], m_api->m_appr_mgr.a_org_rel_related, pInst);
					if(pInst==0) continue;

					if(pInst->GetAccessmode()>aplRO) continue;

					HTREEITEM hItem, hPerItem;
					if(!apidata.IsKindOf(pInst,m_api->m_appr_mgr.e_org)) 
						continue;
					
				//	apidata.GetAttr(pInst, m_api->m_appr_mgr.a_org_name, sStr);
				//	m_api->m_appr_mgr.GetItemName(pInst,sStr);
					m_api->GetItemName(pInst,sStr);

					hItem= m_treeCtrl.InsertItem(sStr, ICON_ORGANIZATION, ICON_ORGANIZATION, ahRootItems[i]);					
					m_treeCtrl.SetItemData(hItem, (DWORD)pInst);
					
					ahOtherItems.Add(hItem);
					
					bIsInPersonGroup= false;
					ext_person.Clear();

					for(n=0; n<Persons.GetSize(); n++)
					{
						apidata.GetAttr(Persons[n], m_api->m_appr_mgr.a_po_the_org, pInst1);
						if(pInst==pInst1)
						{
							CString sEndDate;
							apidata.GetAttr(Persons[n], m_api->m_appr_mgr.a_po_end_date, sEndDate);
							if(!sEndDate.IsEmpty()) 
								continue;//сотрудника удалили
							
							int ico=0;
							CaplInstance* pInst2= NULL;

							apidata.GetAttr(Persons[n], m_api->m_appr_mgr.a_po_the_pers, pInst2);
							if(pInst2==0) continue;

							if(apidata.IsKindOf(pInst2,m_api->m_appr_mgr.e_person))
							{
								if((m_mode&APL_MODE_SELECT_PERSON)==0 && (m_mode&APL_MODE_SELECT_PERSORG)==0) continue;
								m_api->m_appr_mgr.GetPersonName(pInst2,sStr); ico=ICON_PERSON;
								if(pInst2==m_curPerson)
								{
									bIsInPersonGroup= true;
								}
							}
							else if(apidata.IsKindOf(pInst2,m_api->m_appr_mgr.e_official))
							{
								if((m_mode&APL_MODE_SELECT_OFFICIAL)==0) continue;
								m_api->m_appr_mgr.GetPersonName(pInst2,sStr); ico=ICON_OFFICIAL;
							}
							else 
								continue;

							hPerItem= m_treeCtrl.InsertItem(sStr, ico , ico, hItem);
							m_treeCtrl.SetItemData(hPerItem, (DWORD)Persons[n]);
							
							ext_person.Add(Persons[n]);

//							Persons.Remove(n);
//							n--;
						}
					}
					
					//чувак и в эту рабочую группу входит
					if(bIsInPersonGroup && m_bShowPerWG && -1==personWg.Find(pInst))
					{
						personWg.Add(pInst);

					//	apidata.GetAttr(pInst, m_api->m_appr_mgr.a_org_name, sStr);
					//	m_api->m_appr_mgr.GetItemName(pInst,sStr);
						m_api->GetItemName(pInst,sStr);


						HTREEITEM hPerItem1= m_treeCtrl.InsertItem(sStr, ICON_ORGANIZATION, 
							ICON_ORGANIZATION, m_myGroups);
						m_treeCtrl.SetItemData(hPerItem1, (DWORD)pInst);
						
						ahPerItems.Add(hPerItem1);
						
						for(int n= 0; n<ext_person.GetSize(); n++)
						{
							CaplInstance* pInst2= NULL;
							int ico=0;

							apidata.GetAttr(ext_person[n], m_api->m_appr_mgr.a_po_the_pers, pInst2);
							if(apidata.IsKindOf(pInst2,m_api->m_appr_mgr.e_person))
							{
								if((m_mode&APL_MODE_SELECT_PERSON)==0 && (m_mode&APL_MODE_SELECT_PERSORG)==0) continue;
								m_api->m_appr_mgr.GetPersonName(pInst2,sStr);ico=ICON_PERSON;
							}
							else if(apidata.IsKindOf(pInst2,m_api->m_appr_mgr.e_official))
							{
								if((m_mode&APL_MODE_SELECT_OFFICIAL)==0) continue;
								m_api->m_appr_mgr.GetPersonName(pInst2,sStr); ico=ICON_OFFICIAL;
							}
							else continue;

							HTREEITEM hItem1= m_treeCtrl.InsertItem(sStr, ico, ico, hPerItem1);
							m_treeCtrl.SetItemData(hItem1, (DWORD)ext_person[n]);	
						}

						if(m_bExpand)m_treeCtrl.Expand(hPerItem1, TVE_EXPAND);
					}
					
					//добавление рабочей группы в группу(ы) папки Мои раб. группы
					for(n= 0; n<ahRootPerItems.GetSize(); n++)
					{
						CaplInstance* perItem= (CaplInstance*)m_treeCtrl.GetItemData(ahRootPerItems[n]);
						if(pInstRoot==perItem)
						{

						//	apidata.GetAttr(pInst, m_api->m_appr_mgr.a_org_name, sStr);
						//	m_api->m_appr_mgr.GetItemName(pInst,sStr);
							m_api->GetItemName(pInst,sStr);


							HTREEITEM hPerItem1= m_treeCtrl.InsertItem(sStr, ICON_ORGANIZATION, 
								ICON_ORGANIZATION, ahRootPerItems[n]);
							m_treeCtrl.SetItemData(hPerItem1, (DWORD)pInst);
							
							ahPerItems.Add(hPerItem1);
							
							for(int n= 0; n<ext_person.GetSize(); n++)
							{
								int ico=0;
								CaplInstance* pInst2= NULL;

								apidata.GetAttr(ext_person[n], m_api->m_appr_mgr.a_po_the_pers, pInst2);
								if(apidata.IsKindOf(pInst2,m_api->m_appr_mgr.e_person))
								{
									if((m_mode&APL_MODE_SELECT_PERSON)==0 && (m_mode&APL_MODE_SELECT_PERSORG)==0) continue;
									m_api->m_appr_mgr.GetPersonName(pInst2,sStr); ico=ICON_PERSON;
								}
								else if(apidata.IsKindOf(pInst2,m_api->m_appr_mgr.e_official))
								{
									if((m_mode&APL_MODE_SELECT_OFFICIAL)==0) continue;
									m_api->m_appr_mgr.GetPersonName(pInst2,sStr); ico=ICON_OFFICIAL;
								}
								else continue;

								HTREEITEM hItem1= m_treeCtrl.InsertItem(sStr, ico, ico, hPerItem1);
								m_treeCtrl.SetItemData(hItem1, (DWORD)ext_person[n]);				
							}														
						}

						if(m_bExpand)m_treeCtrl.Expand(ahRootPerItems[n], TVE_EXPAND);
					}
				}
			}
			
			if(m_bExpand)m_treeCtrl.Expand(ahRootItems[i], TVE_EXPAND);
		}
		
		//перестраиваем элементы Все рабочие группы
		ahRootItems.RemoveAll();
		for (i = 0; i < ahOtherItems.GetSize(); i++)
		{
			ahRootItems.Add(ahOtherItems[i]);
		}		
		ahOtherItems.RemoveAll();
		
		//перестраиваем элементы Мои рабочие группы
		ahRootPerItems.RemoveAll();
		for (i = 0; i < ahPerItems.GetSize(); i++)
		{
			ahRootPerItems.Add(ahPerItems[i]);
		}		
		ahPerItems.RemoveAll();
	}
	
	if(m_bExpand)m_treeCtrl.Expand(m_myGroups, TVE_EXPAND);

	for(i= 0; i<clds_map.Size; i++)
	{
		childs= (CItemChilds*)clds_map[i].out;
		if(childs)
			delete childs;
	}

	TVSORTCB sortcb;
	sortcb.lpfnCompare= CompareTreeItems;
	sortcb.lParam= (LPARAM)(&(m_api->m_appr_mgr));
	sortcb.hParent= TVI_ROOT;
	m_treeCtrl.SortChildrenCB(&sortcb);
	
	m_treeCtrl.SetRedraw(TRUE);
}
//*****************************************************************************
void CSelectRecipientsDlg::FillRecipientsList()
{
	m_listCtrl.DeleteAllItems();
	int n= 0;
	CString sStr, buf;
	CaplAggr aggr0;
	UINT ico;
	CaplInstance* pers, *org;

	for(int i= 0; i<m_resExt.GetSize(); i++)
	{
		CaplInstance* inst= m_resExt.GetAt(i);
		if(!inst) continue;
		if(apidata.IsKindOf(inst, m_api->m_appr_mgr.e_person))
		{
			m_api->m_appr_mgr.GetPersonName(inst,sStr);
			ico= ICON_PERSON;
		}
		else if(apidata.IsKindOf(inst, m_api->m_appr_mgr.e_pers_org))
		{
			apidata.GetAttr(inst, m_api->m_appr_mgr.a_po_the_pers, pers);
			m_api->m_appr_mgr.GetPersonName(pers,sStr);
			//m_api->GetItemName(pers,sStr);
			apidata.GetAttr(inst, m_api->m_appr_mgr.a_po_the_org, org);			
			apidata.GetAttr(org, m_api->m_appr_mgr.a_org_id, buf);
			if(!buf.IsEmpty())sStr+=_T("(")+buf+_T(")");
			
			ico= ICON_PERSON;
		}
		else if(apidata.IsKindOf(inst, m_api->m_appr_mgr.e_org))
		{
			//apidata.GetAttr(inst, m_api->m_appr_mgr.a_org_name, sStr);			
			m_api->GetItemName(inst,sStr);
			ico= ICON_ORGANIZATION;
		}
		else if(apidata.IsKindOf(inst, m_api->m_appr_mgr.e_official))
		{
			m_api->m_appr_mgr.GetPersonName(inst,sStr);
			ico= ICON_OFFICIAL;
		}
		else continue;

		n= m_listCtrl.InsertItem(n, sStr, ico);
		m_listCtrl.SetItemData(n, (DWORD)inst);		
	}
	m_listCtrl.SortItems(CompareListItems, (DWORD)(&(m_api->m_appr_mgr)));
}
//*****************************************************************************
void CSelectRecipientsDlg::OnItemexpandedPersonOrgTree(NMHDR* pNMHDR, LRESULT* pResult) 
{
	NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR;
		
	m_helper->Sort(m_treeCtrl, pNMTreeView->itemNew.hItem);
/*
	TVSORTCB sortcb;
	sortcb.lpfnCompare= CompareTreeItems;
	sortcb.lParam= (LPARAM)(&(m_api->m_appr_mgr));
	sortcb.hParent= pNMTreeView->itemNew.hItem;
	m_treeCtrl.SortChildrenCB(&sortcb);
*/
	*pResult = 0;
}
//*****************************************************************************
void CSelectRecipientsDlg::OnItemexpandingPersonOrgTree(NMHDR* pNMHDR, LRESULT* pResult) 
{
	NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR;
	// TODO: Add your control notification handler code here
	if(m_bDblCl){m_bDblCl= false;*pResult = 1;}
	else {*pResult = 0;}
}
//*****************************************************************************
void CSelectRecipientsDlg::OnDblclkPersonOrgTree(NMHDR* pNMHDR, LRESULT* pResult) 
{
	NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR;
	
	UINT flag= 0;

	if(!m_bSingleSelect)
	{		
		CPoint pt;
		GetCursorPos(&pt);
		
		m_treeCtrl.ScreenToClient(&pt);
		UINT flag= 0;
		HTREEITEM item= m_treeCtrl.HitTest(pt, &flag);
		CString buf;
		
		buf= m_treeCtrl.GetItemText(item);
		if(m_treeCtrl.ItemHasChildren(item)){m_bDblCl= true;}

		AddItem(item, m_bTraverseTree);
		FillRecipientsList();
	}

	*pResult = 0;
}
//*****************************************************************************
void CSelectRecipientsDlg::OnRecFindButton() 
{
	CRect rect;
	GetWindowRect(&rect);
	CRect rectNew(rect);
	if(m_bResized)
	{
		rectNew.bottom-= 140; 
		m_bResized= false;
		m_findBtn.SetIcon(GetAplTableIco(APL_TABLE_SELECT_DOWN));
	}
	else
	{
		rectNew.bottom+= 140; 
		m_bResized= true;
		m_findBtn.SetIcon(GetAplTableIco(APL_TABLE_SELECT_UP));
	}
	
	rectNew.NormalizeRect();
	SetWindowPos(&wndTop, rectNew.left, rectNew.top, 
		rectNew.right-rectNew.left, rectNew.bottom-rectNew.top, NULL);
	
	RedrawWindow();
}
//*****************************************************************************
void CSelectRecipientsDlg::FillTreeForSingleSelection()
{
	m_allGroups= TVI_ROOT;
	FillTree(m_poExt);
	HTREEITEM hi=m_treeCtrl.GetChildItem(TVI_ROOT);
	if(hi!=0) m_treeCtrl.SelectItem(hi);
}
//*****************************************************************************
void CSelectRecipientsDlg::OnSelchangedPersonOrgTree(NMHDR* pNMHDR, LRESULT* pResult) 
{
	NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR;
	// TODO: Add your control notification handler code here
	*pResult = 0;
	if(!m_bSingleSelect) return;
	
	bool bSel= false;
	m_inst= NULL;
	CaplInstance* inst= (CaplInstance*)m_treeCtrl.GetItemData(pNMTreeView->itemNew.hItem);
	if(inst)
	{
		if((m_mode&APL_MODE_SELECT_PERSON)>0)
		{
			if(apidata.IsKindOf(inst, m_api->m_appr_mgr.e_person)) bSel= true;
			else if(apidata.IsKindOf(inst, m_api->m_appr_mgr.e_pers_org))
			{
				apidata.GetAttr(inst, m_api->m_appr_mgr.a_po_the_pers, inst);
				if(apidata.IsKindOf(inst, m_api->m_appr_mgr.e_person)) bSel= true;
			}
		}
		if((m_mode&APL_MODE_SELECT_PERSORG)>0)
		{
			if(apidata.IsKindOf(inst, m_api->m_appr_mgr.e_pers_org)) bSel= true;
		}
		if((m_mode&APL_MODE_SELECT_ORG)>0 && 
			apidata.IsKindOf(inst, m_api->m_appr_mgr.e_org))bSel= true;
			
		if((m_mode&APL_MODE_SELECT_OFFICIAL)>0)
		{
			if(apidata.IsKindOf(inst, m_api->m_appr_mgr.e_official)) bSel= true;
			else if(apidata.IsKindOf(inst, m_api->m_appr_mgr.e_pers_org))
			{
				apidata.GetAttr(inst, m_api->m_appr_mgr.a_po_the_pers, inst);
				if(apidata.IsKindOf(inst, m_api->m_appr_mgr.e_official)) bSel= true;
			}
		}
	}
	if(bSel)
	{
		m_inst= inst;
		if(!m_okBtn.IsWindowEnabled())
			m_okBtn.EnableWindow();
	}
	else 
	{
		m_inst= 0;
		if(m_okBtn.IsWindowEnabled())
			m_okBtn.EnableWindow(FALSE);
	}

	m_treeCtrl.SetFocus();
}

//////////////////////////////////////////////////////////////////////////
// find item in tree functions
// ищем s2 в s1
bool spdStrIncludeBeg(const CString &s1,const CString &s2)
{
	int i,le=s2.GetLength();
	if(le>s1.GetLength())
		return false;

	CString s3(s1,le);
	s3.MakeUpper();

	for (i=0;i<le;i++)
	{
		if(s3[i]!=s2[i])
			return false;
	}
	return true;
}

bool spdStrIncludeBegDD(const CString &s1,const CString &s2, CaplInstance *inst, CaplAPI *api)
{
	if(!inst) return false;
	if(!inst->GetType()) return false;
	int i,le2 = s2.GetLength(), le1 = s1.GetLength();
	if(le2>le1)
		return false;
	if(le2 == 0) return false;

	CString s3(s1,le1);
	s3.MakeUpper();
	
	LPCTSTR buf = s3;
	LPCTSTR buf2 = s2;

	int cur2=0;

	if(api->m_data.IsKindOf(inst, api->m_appr_mgr.e_pers_org))
		api->m_data.GetAttr(inst, api->m_appr_mgr.a_po_the_pers, inst);
	bool bOffc = api->m_data.IsKindOf(inst, api->m_appr_mgr.e_official);

	for (i=0; i<le1; ++i)
	{
		if((buf[i] == _T('(')) && bOffc)
		{
			cur2 = 0;
		}
		else if((buf[i] == _T(' ')) && (i<le1-2))
		{
			if((buf[i+1] == _T(':')) && (buf[i+2] == _T(' ')))
			{
				cur2 = 0;
				i += 2;
			}
		}
		else if((cur2 >= 0) && (buf[i] == buf2[cur2]))
		{
			++cur2;
			if(cur2 == le2) return true;
		}
		else cur2 = -1;
	}
	return false;
}

bool spdStrIncludeAll(CString s1,const CString &s2)
{
	if(s2.GetLength()>s1.GetLength())
		return false;

	s1.MakeUpper();

	if (s1.Find(s2)>=0)
	{
		return true;
	}
	else
	{
		return false;
	}
}

bool spdStrInclude(const CString &s1, const CString &s2, CaplInstance *inst, CaplAPI *api)
{
	//выбери одно из двух:
//	return spdStrIncludeBegDD(s1, s2, inst, api);	//Поиск подстроки в начале строки
	return spdStrIncludeAll(s1, s2);	//Поиск подстроки в строке


}

//----------- find back -----------------------------------------------------

HTREEITEM find_last_child(CTreeCtrl *tree,HTREEITEM from)
{
	HTREEITEM ii,iin,iich;

	ii=from;

	iich=tree->GetChildItem(from);

	while(iich!=NULL)
	{
		ii=iich;

		iin=tree->GetNextSiblingItem(ii);
		while (iin!=NULL)
		{
			ii=iin;
			iin=tree->GetNextSiblingItem(ii);
		}
		iich=tree->GetChildItem(ii);
	}

	return ii;
}

HTREEITEM find_prev_item(CTreeCtrl *tree,HTREEITEM from)
{
	HTREEITEM ii=tree->GetPrevSiblingItem(from);
	if (ii==NULL)
		return tree->GetParentItem(from);		
	else
		return find_last_child(tree,ii);	
}

HTREEITEM find_item_back(CTreeCtrl *tree,CString &val,HTREEITEM from, CaplAPI *api)
{
	HTREEITEM ii;

	ii=find_prev_item(tree,from);
	CaplInstance *inst;

	while (ii!=NULL)
	{
		inst = (CaplInstance *)tree->GetItemData(ii);

		if(spdStrInclude(tree->GetItemText(ii),val, inst, api))
			break;

		ii=find_prev_item(tree,ii);
	}
	return ii;
}

//----------- find forward -----------------------------------------------------

HTREEITEM find_next_item(CTreeCtrl *tree,HTREEITEM from)
{
	HTREEITEM re=NULL;
	
	re=tree->GetChildItem(from);

	if(re==NULL)
		re=tree->GetNextSiblingItem(from);

	if(re==NULL)
	{
		re=NULL;
		while(re==NULL)
		{
			re=tree->GetParentItem(from);
			if(re==NULL)
			{
				break;
			}
			from=re;
			re=tree->GetNextSiblingItem(from);
		}
	}

	return re;
}

HTREEITEM find_item_forw(CTreeCtrl *tree,CString &val,HTREEITEM from, CaplAPI *api)
{
	HTREEITEM ii;

	ii=find_next_item(tree,from);
	CaplInstance *inst;

	while (ii!=NULL)
	{
		inst = (CaplInstance *)tree->GetItemData(ii);

		if(spdStrInclude(tree->GetItemText(ii),val, inst, api))
			break;

		ii=find_next_item(tree,ii);
	}
	return ii;
}
////////////////---------------------------
HTREEITEM find_last_item(CTreeCtrl *tree)
{
	HTREEITEM it,itn;
	if(tree->GetCount()==0)
		return NULL;
	it=tree->GetRootItem();
	itn=tree->GetNextSiblingItem(it);
	while(itn)
	{
		it=itn;
		itn=tree->GetNextSiblingItem(it);
	}
	return find_last_child(tree,it);
}
//-----------------------------------------------------------------------------------

void CSelectRecipientsDlg::OnFindForward()
{
	CString str;
	m_edFindStr.GetWindowText(str);
	str.MakeUpper();

	HTREEITEM re=NULL,item=m_treeCtrl.GetSelectedItem();
	HTREEITEM roo=m_treeCtrl.GetRootItem();
	HTREEITEM olditem=item;
	CaplInstance *inst;

	if(item==NULL)
	{
		inst = (CaplInstance *)m_treeCtrl.GetItemData(roo);
		if(spdStrInclude(m_treeCtrl.GetItemText(roo),str, inst, m_api))
		{
			m_treeCtrl.EnsureVisible(roo);
			m_treeCtrl.SelectItem(roo);
			return;
		}
		else
			olditem=item=roo;
	}
	
	re=find_item_forw(&m_treeCtrl,str,item, m_api);

	if(re!=NULL)
	{	
		m_treeCtrl.SelectItem(re);
		m_treeCtrl.EnsureVisible(re);
	}
	else
	{
		item=roo;
		inst = (CaplInstance *)m_treeCtrl.GetItemData(item);
		if(spdStrInclude(m_treeCtrl.GetItemText(item),str, inst, m_api))
		{
			m_treeCtrl.SelectItem(item);
			m_treeCtrl.EnsureVisible(item);
			if(item==olditem)
				AfxMessageBox( APL_T("Не найдено."));
			return;
		}
		re=find_item_forw(&m_treeCtrl,str,item, m_api);
		if(re!=NULL)
		{	
			m_treeCtrl.SelectItem(re);
			m_treeCtrl.EnsureVisible(re);
			if(re==olditem)
				AfxMessageBox( APL_T("Не найдено."));
		}
		else
			AfxMessageBox( APL_T("Не найдено."));
	}
}

void CSelectRecipientsDlg::OnFindBack()
{
	CString str;
	m_edFindStr.GetWindowText(str);
	str.MakeUpper();
	HTREEITEM re=NULL,item=m_treeCtrl.GetSelectedItem();
	HTREEITEM roo=m_treeCtrl.GetRootItem();
	if(!roo) return;
	HTREEITEM olditem=item;
	CaplInstance *inst;

	if(item==NULL)
	{	
		inst = (CaplInstance *)m_treeCtrl.GetItemData(roo);
		if(spdStrInclude(m_treeCtrl.GetItemText(roo),str, inst, m_api))
		{
			m_treeCtrl.SelectItem(roo);
			m_treeCtrl.EnsureVisible(roo);
			return;
		}
		else
			olditem=item=roo;
	}

	re=find_item_back(&m_treeCtrl,str,item, m_api);
	
	if(re!=NULL)
	{
		m_treeCtrl.SelectItem(re);
		m_treeCtrl.EnsureVisible(re);
	}
	else
	{

		item=find_last_item(&m_treeCtrl);
		inst = (CaplInstance *)m_treeCtrl.GetItemData(item);
		if(spdStrInclude(m_treeCtrl.GetItemText(item),str, inst, m_api))
		{
			m_treeCtrl.SelectItem(item);
			m_treeCtrl.EnsureVisible(item);
			if(item==olditem)
				AfxMessageBox( APL_T("Не найдено."));
			return;
		}
		re=find_item_back(&m_treeCtrl,str,item, m_api);
		if(re!=NULL)
		{	
			m_treeCtrl.SelectItem(re);
			m_treeCtrl.EnsureVisible(re);
			if(re==olditem)
				AfxMessageBox( APL_T("Не найдено."));
		}
		else
			AfxMessageBox( APL_T("Не найдено."));
	}
}

void CSelectRecipientsDlg::OnButton4Beg() 
{
	CString str;
	m_edFindStr.GetWindowText(str);
	str.MakeUpper();
	HTREEITEM re=NULL,item=m_treeCtrl.GetRootItem();
	HTREEITEM roo=m_treeCtrl.GetRootItem();
	if(!roo) return;

	if(item==NULL)
	{
		return;
	}
	CaplInstance *inst = (CaplInstance *)m_treeCtrl.GetItemData(roo);
	if(spdStrInclude(m_treeCtrl.GetItemText(roo),str, inst, m_api))
	{
		m_treeCtrl.SelectItem(roo);
		m_treeCtrl.EnsureVisible(roo);
		return;
	}

	re=find_item_forw(&m_treeCtrl,str,item, m_api);

	if(re!=NULL)
	{
		m_treeCtrl.SelectItem(re);
		m_treeCtrl.EnsureVisible(re);
	}
	else
	{
		m_treeCtrl.SelectItem(roo);
		m_treeCtrl.EnsureVisible(roo);
		AfxMessageBox( APL_T("Не найдено."));
	}
}

bool bCntrlPressed=false;


BOOL CSelectRecipientsDlg::PreTranslateMessage(MSG* pMsg) 
{
	if (pMsg->message==WM_KEYDOWN)
	{
		if(pMsg->wParam==VK_CONTROL)
			bCntrlPressed=true;
		else if(pMsg->wParam==VK_F3)
		{
			if(bCntrlPressed)
				OnFindBack();
			else
				OnFindForward();
		}
	}
	else if (pMsg->message==WM_KEYUP)
	{
		if(pMsg->wParam==VK_CONTROL)
			bCntrlPressed=false;
	}
	else if (pMsg->message==WM_RBUTTONDOWN)
	{
		if(pMsg->hwnd==m_treeCtrl.m_hWnd)
		{
			CPoint p;
			p.x = GET_X_LPARAM(pMsg->lParam); 
			p.y = GET_Y_LPARAM(pMsg->lParam);

			UINT flag=TVHT_ONITEM;
			HTREEITEM hItem=m_treeCtrl.HitTest(p,&flag);
			if(0!=hItem){ TreeContextMenu(hItem,pMsg->pt); return TRUE;}
		}
	}
	
	return CResizableDialog::PreTranslateMessage(pMsg);
}

void CSelectRecipientsDlg::CalcWindowRect(LPRECT lpClientRect, UINT nAdjustType) 
{
	// TODO: Add your specialized code here and/or call the base class
	
	CResizableDialog::CalcWindowRect(lpClientRect, nAdjustType);
}

void CSelectRecipientsDlg::TreeContextMenu(HTREEITEM hitem,POINT point)
{
	if(0==hitem) return;
	CaplInstance *parent=(CaplInstance *)m_treeCtrl.GetItemData(hitem);
	if(0==parent) return;

	bool bIsOrg=m_api->m_data.IsKindOf(parent,m_api->m_appr_mgr.e_org);
	bool bIsPers=m_api->m_data.IsKindOf(parent,m_api->m_appr_mgr.e_person);

	if(!(bIsOrg||bIsPers)) return;

	CMenu menu;
	CMenu *pPopup;
	VERIFY(menu.LoadMenu(IDR_CONTEXT_MENU));
	pPopup = menu.GetSubMenu(13);
	if(!(m_mode & APL_MODE_SELECT_PERSON)) 	pPopup->DeleteMenu(ID_CREATE_PERS,MF_BYCOMMAND);

	if(bIsPers)
	{
		pPopup->DeleteMenu(ID_CREATE_PERS,MF_BYCOMMAND);
		pPopup->DeleteMenu(ID_CREATE_ORG,MF_BYCOMMAND);
	}
	else
	{
		if(!m_api->m_appr_mgr.m_bAllowCreateOrgInSelect)	pPopup->DeleteMenu(ID_CREATE_ORG,MF_BYCOMMAND);
		if(!m_api->m_appr_mgr.m_bAllowCreatePersonInSelect)	pPopup->DeleteMenu(ID_CREATE_PERS,MF_BYCOMMAND);
	}

	BOOL res=pPopup->TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON |TPM_RETURNCMD,	point.x, point.y,this); 
	if(res==ID_CREATE_ORG)
	{
		COrganizationPropDlg org_dlg;
		org_dlg.m_api=m_api;
		org_dlg.DoModal();
		if(0!=org_dlg.inst)
		{
			CaplInstance *rel=m_api->m_data.CreateInstance(m_api->m_appr_mgr.e_org_rel);
			m_api->m_data.PutAttr(rel,m_api->m_appr_mgr.a_org_rel_relating,parent);
			m_api->m_data.PutAttr(rel,m_api->m_appr_mgr.a_org_rel_related,org_dlg.inst);
			m_api->SaveChanges();
			m_helper->InsertItem(m_treeCtrl,org_dlg.inst,hitem);
			m_treeCtrl.Expand(hitem,TVE_COLLAPSE);
			m_treeCtrl.Expand(hitem,TVE_EXPAND);
		}
	}
	else if(res==ID_CREATE_PERS)
	{
		CPersonPropDlg pers_dlg;
		pers_dlg.m_api=m_api;
		pers_dlg.m_bEnableEdit=true;
		pers_dlg.DoModal();

		if(0!=pers_dlg.m_person)
		{
			CaplInstance *rel=m_api->m_data.CreateInstance(m_api->m_appr_mgr.e_pers_org);
			m_api->m_data.PutAttr(rel,m_api->m_appr_mgr.a_po_the_pers,pers_dlg.m_person);
			m_api->m_data.PutAttr(rel,m_api->m_appr_mgr.a_po_the_org,parent);
			CString sDate;
			COleDateTime odt=COleDateTime::GetCurrentTime();
			aplDate2String(odt,sDate);
			m_api->m_data.PutAttr(rel,m_api->m_appr_mgr.a_po_start_date,sDate);
			m_api->SaveChanges();
			m_helper->InsertItem(m_treeCtrl,pers_dlg.m_person,hitem);
			m_treeCtrl.Expand(hitem,TVE_COLLAPSE);
			m_treeCtrl.Expand(hitem,TVE_EXPAND);
		}
	
	}
	else if(res==ID_PROPERTIES)
	{
		if(m_api->m_data.IsKindOf(parent,m_api->m_appr_mgr.e_org))
		{
			COrganizationPropDlg org_dlg;
			org_dlg.m_api=m_api;
			org_dlg.inst=parent;
			if(IDOK==org_dlg.DoModal())
			{
				CString name;
				m_api->GetItemName(parent,name);
				m_treeCtrl.SetItemText(hitem,name);
			}
		}
		else if(m_api->m_data.IsKindOf(parent,m_api->m_appr_mgr.e_person))
		{
			CPersonPropDlg pers_dlg;
			pers_dlg.m_api=m_api;
			pers_dlg.m_person=parent;
			if(IDOK==pers_dlg.DoModal())
			{
				CString name;
				m_api->GetItemName(parent,name);
				m_treeCtrl.SetItemText(hitem,name);
			}
		}
	}

}
