#include "stdafx.h"
#include "aplFolderTreeItem.h"
#include "aplDocTreeItem.h"
#include "TreeProductItem.h"
#include "aplFolderTreeItem.h"
#include "CaplRequirementTreeItem.h"
#include "aplTreeCharacteristicItem.h"
#include "aplCharacteristicGroupTreeItem.h"

CaplRequirementTreeItem::CaplRequirementTreeItem(CTreeCtrl *tree, CPSMDoc *doc,
												 CaplInstance *ciReq, CaplInstance *ciParent, 
												 CaplInstance *ciRootParent, CaplInstance *ciAssoc)
{
	m_type = APL_TREE_ITEM_REQUIREMENT;
	m_tree = tree;
	m_doc = doc;
	m_ciReq = ciReq;
	m_ciParent = ciParent;
	m_ciRoot = ciRootParent;	
	m_ciAssoc = ciAssoc;
	
	if(doc!=0) doc->m_items.Add(this);
}

CaplRequirementTreeItem::~CaplRequirementTreeItem(void)
{
}

bool CaplRequirementTreeItem::GetName( CString &name )
{
	name=_T("???");
	_APL_TREE_ITEM_CHEK_PARAM_BOOL

	if(m_ciReq)
		m_doc->m_api.GetItemName(m_ciReq, name);			

	return true;
}

bool CaplRequirementTreeItem::RefreshItem()
{
	_APL_TREE_ITEM_CHEK_PARAM_BOOL

	UINT ico= ICON_REQUIMENT;
	CString buf, state;
	int ico_rel=-1;
	aplExtent ext;

	GetMainInstances(ext);
	if(ext.GetSize())
		ico = m_doc->m_api.GetInstIco(ext[0]);

	// имя элемента
	GetName(buf);

	// главная иконка
	SetItemImage(ico, IDX_IL_TREE_ITEM);

	// иконка состояния
	m_doc->m_api.m_data.GetAttr(m_ciReq, m_doc->m_api.m_req_mgr.a_req_wf_state, state);
	SetItemImage(aplState2Ico(state,-1), IDX_IL_TREE_STATE);

	m_tree->SetItemText(m_item, buf);	

	Sort();
	m_tree->RedrawWindow();

	if(m_doc->m_tab_view->m_item_old==this) m_doc->ChangeItem(this);
	return true;
}

void CaplRequirementTreeItem::GetAccessedInstances( aplExtent &ext )
{
	ext.Clear();

	if(m_ciReq) 
		if(m_ciReq->GetType()!=0) 
			ext.Add(m_ciReq);	
}

bool CaplRequirementTreeItem::CreateTreeItem( HTREEITEM parent_item )
{
	_APL_TREE_ITEM_CHEK_PARAM_BOOL

	CString buf;
	aplExtent ext;
	UINT ico = NULL;
	int ico_rel = -1;

	InsetItem(_T("1"), ico, parent_item);
	m_fictive_item = m_tree->InsertItem(_T("fictive"), 0, 0, m_item);

	RefreshItem();
	m_expanded=false;

	return true;
}

bool CaplRequirementTreeItem::Expand( UINT action )
{
	_APL_TREE_ITEM_CHEK_PARAM_BOOL

	if(action==2)
	{
		if(m_expanded) return true;
		if(m_hasSubItem) Expand(1);
		if(m_fictive_item!=0)
		{
			m_tree->DeleteItem(m_fictive_item);
			m_fictive_item = 0;
		}
		m_hasSubItem = true;

		bool old = m_bShowNoFoundMessage;
		m_bShowNoFoundMessage = old;
		m_ExecMyExpand = true;

		if(m_doc->m_auto_expand_items.m_showintree_requirement&APL_SHOW_DOC)
			ShowAllDocs(false,false);

		if(m_doc->m_auto_expand_items.m_showintree_requirement&APL_SHOW_CHARACT)
			ShowAllCharacteristic(false);

		if(m_doc->m_auto_expand_items.m_showintree_requirement&APL_SHOW_APPROVAL)
			ShowAllApproval(false);

		// показываем дочерние требования
		if(m_ShowContentsOnExpand) 
			ShowChildItems();

		// с недавних пор требования раскрываются и на папки. типа как группы
		ShowChildFolders();

		m_bShowNoFoundMessage = old;
		m_ExecMyExpand = true;
		Sort();

		m_expanded= true;		
	}
	else if(action==1)
	{
		CollapseItem();

		m_child_items.Clear();
	}
	return true;
}

bool CaplRequirementTreeItem::ShowChildFolders()
{
	aplExtent aeExt, aeItems;
	GetMainInstances(aeExt);
	if (aeExt.Size <= 0) 
		return false;

	CaplInstance *cit = aeExt[0];
	if (cit == 0) return false;
	if (cit->GetType() == 0) return false;
	if (cit->GetAccessmode() > aplRO)
		if (m_bShowNoFoundMessage) { aplErrorMessage(S::NoAccessRight(), cit); return false; }
	if (-1 != m_child_items.Find(aeExt[0])) return false;

	StartBusy();
	m_tree->SetRedraw(FALSE);

	if (m_doc_data.IsKindOf(cit, m_doc->m_api.m_req_mgr.e_requirement))
	{
		CString sSql;
		sSql.Format(_T("SELECT Ext_1 FROM Ext_1 { apl_folder.parent = #%d } END_SELECT"), cit->GetId());
		if (m_doc_data.NET_QueryEditParse(sSql))
			m_doc_data.NET_QueryExecute(aeItems);

		m_doc->m_api.LoadExtentInfo(aeItems);
		for (int i = 0; i < aeItems.Size; i++)
		{
			if (!aeItems[i]) continue;
			if (-1 != m_child_items.Find(aeItems[i])) continue;

			if (m_doc_data.IsKindOf(aeItems[i], m_doc->m_api.m_folder_mgr.e_folder))
			{
				CreateFolderItem(aeItems[i]);
				m_child_items.Add(aeItems[i]);
			}			
		}
	}

	m_tree->SetRedraw(TRUE);
	StopBusy();

	return true;
}

bool CaplRequirementTreeItem::ShowChildItems()
{
	aplExtent aeExt, aeItems;
	GetMainInstances(aeExt);
	if(aeExt.Size<=0) return false;

	CaplInstance *cit = aeExt[0];
	if(cit == 0) return false;
	if(cit->GetType()==0) return false;
	if(cit->GetAccessmode() > aplRO)
	if(m_bShowNoFoundMessage) { aplErrorMessage(S::NoAccessRight(),cit);return false; }
	if(-1 != m_child_items.Find(aeExt[0])) return false;

	StartBusy();
	m_tree->SetRedraw(FALSE);

	if(m_doc_data.IsKindOf(cit, m_doc->m_api.m_req_mgr.e_requirement))
	{
		CString sSql;
		sSql.Format(_T("SELECT Ext_1 FROM Ext_1 { apl_requirement.parent = #%d } END_SELECT"), cit->GetId());
		if(m_doc_data.NET_QueryEditParse(sSql))
			m_doc_data.NET_QueryExecute(aeItems);		
			
		m_doc->m_api.LoadExtentInfo(aeItems);
		for(int i=0; i<aeItems.Size; i++)
		{
			if(!aeItems[i]) continue;			
			if(-1 != m_child_items.Find(aeItems[i])) continue;

			if(m_doc_data.IsKindOf(cit, m_doc->m_api.m_req_mgr.e_requirement))
			{
				CaplRequirementTreeItem *pItem = new CaplRequirementTreeItem(m_tree, m_doc, aeItems[i], cit);
				pItem->CreateTreeItem(m_item);		
			}

			m_child_items.Add(aeItems[i]);
		}				
	}	

	m_tree->SetRedraw(TRUE);
	StopBusy();

	return true;
}

bool CaplRequirementTreeItem::SelectChildItemByInst( CaplInstance *ciRequirement )
{
	HTREEITEM hChild = m_tree->GetChildItem(m_item);
	while(hChild)
	{
		CaplRequirementTreeItem *pItem = (CaplRequirementTreeItem*)m_tree->GetItemData(hChild);
		if(pItem)
		{
			if(pItem->m_ciReq == ciRequirement)
			{
				m_tree->SelectItem(hChild);				
				return true;
			}
		}

		hChild = m_tree->GetNextSiblingItem(hChild);
	}

	return false;
}

void CaplRequirementTreeItem::ShowProperties()
{
	if(!m_ciReq) return;
	if(!m_doc->m_api.m_req_mgr.ShowProperties(m_ciReq)) return;

	m_doc->RefreshAllItemsByType(APL_TREE_ITEM_REQUIREMENT);
}

bool CaplRequirementTreeItem::CreateFolderItem(CaplInstance *folder)
{
	if (m_ciReq && folder)
	{
		CaplFolderTreeItem *folderItem = new CaplFolderTreeItem(m_tree, m_doc, this, folder);
		folderItem->CreateTreeItem(m_item);
		folderItem->ShowContents();
		folderItem->m_sub_folders.Add(folder);

		MyExpand();
		return true;
	}

	return false;
}

bool CaplRequirementTreeItem::TrackPopupMenu( CWnd *wnd, CPoint &point, UINT view_mode/* = APLICM_NORMALE */ )
{
	CMenu menu;  gSetPsmResourceHandle();
	HTREEITEM parent = 0;
	CString wf_state;
	CMenu* pPopup= NULL;
	aplExtent aeRootItems;
	CaplTreeItem *parent_item = 0;
	CaplInstance *ciNewReq = 0;
	CaplInstance *folder = 0;

	if(m_doc->m_api.m_data.IsKindOf(m_ciReq, m_doc->m_api.m_req_mgr.e_requirement))
	{
		VERIFY(menu.LoadMenu(IDR_TREE_CONTEXT_MENU));
		
		CaplMenu::Install(wnd); 
		pPopup = menu.GetSubMenu(INDEX_REQUIREMENT);
		pPopup->EnableMenuItem(ID_DELETE_FROM_REQUIREMENT, MF_BYCOMMAND | MF_GRAYED);

		// получаем родительский элемент
		parent = m_tree->GetNextItem(m_item, TVGN_PARENT);
		if(parent)
		{
			parent_item = (CaplTreeItem*)m_tree->GetItemData(parent);
			if(parent_item)
			{
				// от типа родительского элемента зависит вид меню
				if(parent_item->m_type == APL_TREE_ITEM_FOLDER)
				{
					pPopup->EnableMenuItem(ID_DELETE_ASSOC, MF_BYCOMMAND | MF_GRAYED);
				}
				else if(parent_item->m_type == APL_TREE_ITEM_PRODUCT)
				{
					pPopup->EnableMenuItem(ID_DELETE_FROM_FOLDER, MF_BYCOMMAND | MF_GRAYED);
				}
				else if(parent_item->m_type == APL_TREE_ITEM_REQUIREMENT)
				{
					pPopup->EnableMenuItem(ID_DELETE_FROM_REQUIREMENT, MF_BYCOMMAND | MF_ENABLED);
				}
				else
				{
					pPopup->EnableMenuItem(ID_DELETE_ASSOC, MF_BYCOMMAND | MF_GRAYED);
					pPopup->EnableMenuItem(ID_DELETE_FROM_FOLDER, MF_BYCOMMAND | MF_GRAYED);
				}
			}
		}
		// родителського элемента нет (открыто в новом окне). некоторые пункты дизаблим
		else
		{
			pPopup->EnableMenuItem(ID_DELETE_ASSOC, MF_BYCOMMAND | MF_GRAYED);
			pPopup->EnableMenuItem(ID_DELETE_FROM_FOLDER, MF_BYCOMMAND | MF_GRAYED);
		}
		
		AppendAddIn((CMenu*)pPopup);
	}
	else
	{
		return false;
	}   

	ASSERT(pPopup != NULL);
	if(pPopup==0) return false;

	UpdateMenu((CMenu**)&pPopup, view_mode);

	BOOL res = pPopup->TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON | TPM_RETURNCMD,
		point.x, point.y, wnd);

	switch (res)
	{
		case ID_CREATE_GROUP:

			if (m_ciReq != 0)
			{
				if (m_ciReq->GetAccessmode()>aplRW)
				{ 
					AfxMessageBox(ID_NO_ACCESS_RIGHT, MB_OK | MB_ICONSTOP); 
					return false; 
				}
			}

			folder = m_doc->m_api.m_folder_mgr.CreateFolder(m_ciReq, 0, 0);
			CreateFolderItem(folder);
			break;


		case ID_CREATE_CHILD_REQ:
			
			ciNewReq = m_doc->m_api.m_req_mgr.CreateRequirement(m_ciReq);
			if(ciNewReq)
			{
				RefreshItem();
				ShowChildItems();
				Expand(TVE_EXPAND);
				SelectChildItemByInst(ciNewReq);				
			}
			break;

		case ID_IMPORT_REQ_FROM_XML:

			m_doc->m_api.m_req_mgr.ImportRequirementsFromXMLword2003(aeRootItems, _T(""), m_ciReq);

			if(aeRootItems.Size) 
			{
				ShowChildItems();
				Expand(TVE_EXPAND);
			}
			
			break;

		case ID_IMPORT_REQ_FROM_TXT:

			m_doc->m_api.m_req_mgr.ImportAP25FromTxt(aeRootItems, m_ciReq);
			if(aeRootItems.Size) 
			{
				ShowChildItems();
				Expand(TVE_EXPAND);
			}

			break;

		case ID_SHOW_WHERE_USED:

			ShowWhereUsed();
			break;

		case ID_SHOW_ASSOC:

			ShowAssoc();
			break;

		case ID_CREATE_DOC:

			CreateDoc();
			break;

		case ID_WFS_CHANGE: 

			if(m_doc->m_api.m_doc_mgr.ChangeWFState(m_ciReq, _T("")))
				m_doc->RefreshAllItemsByType(APL_TREE_ITEM_REQUIREMENT);

			break;

		case ID_WFS_HISTORY: 
			
			m_doc->m_api.m_doc_mgr.ShowWFStateHistory(m_ciReq);
			break;
				
		case ID_SHOW_PROPERTIES:

			ShowProperties();
			break;
		
		case ID_SET_INST_ACCSESS: 

			SetInstancesAccess();	
			break;

		case ID_SET_INST_OWNER:	
			
			SetInstancesOwner();
			break;

		case ID_FREZEE_INST:

			FrezeInstances();
			break;

		case ID_DELETE_FROM_FOLDER:

			if(MessageBox(0,  APL_T("Удалить требование из папки?"),  APL_T("Подтверждение удаления"), MB_ICONQUESTION|MB_YESNO) == IDYES)
				if(m_doc->m_api.m_folder_mgr.RemoveFromFolder( ((CaplFolderTreeItem*)parent_item)->m_inst, m_ciReq ))
					m_doc->m_items.Remove(m_doc->m_items.Find(this));
			
			break;

		case ID_DELETE_FROM_REQUIREMENT:

			if(MessageBox(0,  APL_T("Удалить связь требования с родительским?"),  APL_T("Подтверждение удаления связи"), MB_ICONQUESTION|MB_YESNO) == IDYES)
			{
				CaplInstance *nullInst = 0;
				m_doc->m_api.m_data.PutAttr(m_ciReq, m_doc->m_api.m_req_mgr.a_req_parent, nullInst);
				m_doc->m_api.SaveChanges();
				m_doc->m_items.Remove(m_doc->m_items.Find(this));
			}
			break;

		case ID_DELETE_ASSOC:

			if(MessageBox(0,  APL_T("Удалить связь?"),  APL_T("Подтверждение удаления"), MB_ICONQUESTION|MB_YESNO) == IDYES)
				if(RemoveAssociation())
					m_doc->m_items.Remove(m_doc->m_items.Find(this));

			break;

		case ID_DELETE:
			// удаляем это требование во всех папках
			if(m_doc->m_api.m_req_mgr.DeleteRequirement(m_ciReq))
			{
				for(int i=0;i<m_doc->m_items.Size;i++)
				{
					if(m_doc->m_items[i] != this)
					{
						if(m_doc->m_items[i]->m_type==m_type)
						{
							CaplRequirementTreeItem *item1=
								(CaplRequirementTreeItem*)m_doc->m_items[i];
							{
								if(item1->m_ciReq==m_ciReq)
								{
									m_doc->m_items.Remove(i); 
									i--;
								}
							}
						}
					}
				}

				m_doc->m_items.Remove(m_doc->m_items.Find(this));
			}

			break;

		case ID_EDIT_COPY: 
			
			((CNavigatorView*)m_tree)->OnCopy(); 
			break;

		case ID_EDIT_PASTE: 

			((CNavigatorView*)m_tree)->OnPaste(); 			
			break;
		

		case ID_CREATE_CHARACTERISTIC: CreateCharacteristic(m_ciReq); break;
		case ID_CREATE_CHARACTERISTIC_GROUP: CreateCharacteristicGroup(m_ciReq);break;

		default: PrepareContextMenu(res); 	break;
	}

	return true;
}

bool CaplRequirementTreeItem::CopyItem( CaplTreeItem *moved_item, CPoint *point )
{
	_APL_TREE_ITEM_CHEK_PARAM_BOOL;
	if(moved_item==0 ) return false;
	if(moved_item->m_type != APL_TREE_ITEM_REQUIREMENT) return false;
	
	if(! m_doc->m_api.m_categ_mgr.GetCurrentPerson()) 
	{ 
		AfxMessageBox( APL_T("Для пользователя не задан сотрудник. Работа с требованием невозможна."), MB_ICONSTOP); 
		return false;
	}

	// предыдущий родитель, новый родитель
	CaplInstance* inst_moved = ((CaplRequirementTreeItem*)moved_item)->m_ciReq;
	if (inst_moved == 0) return false;
	if(inst_moved == m_ciReq) return false;

	aplExtent aeChild;

	// самое первое требование
	CaplInstance *ciNewRoot = m_doc->m_api.m_req_mgr.CreateRequirementCopy(inst_moved);
	m_doc->m_api.m_req_mgr.AddChild(m_ciReq, ciNewRoot);

	// все дочерние рекурсивно вниз
	m_doc->m_api.m_req_mgr.CopyRequirementsRecursive(inst_moved, ciNewRoot, inst_moved);	

	// сохранение
	m_doc_data.NET_SaveChanges();	

	m_expanded = false;
	Expand(TVE_EXPAND);
	m_tree->Expand(m_item, TVE_EXPAND);
	m_expanded = true;

	RefreshItem();

	return true;
}

bool CaplRequirementTreeItem::MoveItem(CaplTreeItem *moved_item, CPoint *point)
{
	_APL_TREE_ITEM_CHEK_PARAM_BOOL;
	if(moved_item==0 ) return false;

	// требование
	if(moved_item->m_type == APL_TREE_ITEM_REQUIREMENT)
	{
		int i;

		// предыдущий родитель, новый родитель
		CaplInstance* inst_moved = ((CaplRequirementTreeItem*)moved_item)->m_ciReq;
		if (inst_moved == 0) return false;

		CaplTreeItem *parent_item = 0;
		HTREEITEM parent = m_tree->GetNextItem(moved_item->m_item, TVGN_PARENT);

		if(parent)
			parent_item = (CaplTreeItem*)m_tree->GetItemData(parent);

		// переносить в себя нельзя
		if(parent_item == this) return false;
		if(inst_moved == m_ciReq) return false;

		// переносим требование
		if(moved_item->m_type==APL_TREE_ITEM_REQUIREMENT)
		{
			m_doc->m_api.m_data.PutAttr(inst_moved, m_doc->m_api.m_req_mgr.a_req_vs, _T(""));
			if(!m_doc->m_api.m_req_mgr.MoveRequirement(inst_moved, m_ciReq))
				return false;
		}

		// переносим из папки
		if(parent_item)
		{
			if(parent_item->m_type == APL_TREE_ITEM_FOLDER)
				if(!m_doc->m_api.m_folder_mgr.RemoveFromFolder( ((CaplFolderTreeItem*)parent_item)->m_inst, inst_moved ) )
					return false;
		}

		//////////////////   сохранение - обязательно до перерисовки! Иначе рисуется старое состояние!
		m_doc_data.NET_SaveChanges();	

		//////////////////   перерисовка item-ов
		i = m_doc->m_items.Find(moved_item);
		if (i != -1) m_doc->m_items.Remove(i);
		if(parent_item) parent_item->RefreshItem();
	}

	m_expanded = false;
	Expand(TVE_EXPAND);
	m_tree->Expand(m_item, TVE_EXPAND);
	m_expanded = true;

	RefreshItem();

	return true;
}
//****************************************************************
bool CaplRequirementTreeItem::PasteFile(LPCTSTR file, CPoint *point)
{
	if(file==0) return false;
	if(m_ciReq!=0) CreateDoc(m_ciReq,file);
	return true;
}
//****************************************************************
bool CaplRequirementTreeItem::PasteItem( CaplTreeItem *moved_item, CPoint *point/* =0 */ )
{
	CMenu menu;  gSetPsmResourceHandle();
	CMenu *pPopup=0;
	VERIFY(menu.LoadMenu(IDR_PASTE_ITEM_MENU));
	CaplMenu::Install(m_tree); 

	pPopup = menu.GetSubMenu(15);
	if(!pPopup) return false;

	CPoint pnt;
	if(point==0)
	{
		RECT rect;
		m_tree->GetItemRect(m_item,&rect,TRUE);
		m_tree->ClientToScreen(&rect);
		pnt.x=rect.right;
		pnt.y=rect.bottom;
	}
	else
	{
		pnt.x=point->x;
		pnt.y=point->y;
	}

	if(moved_item->m_type == APL_TREE_ITEM_REQUIREMENT)
	{
		pPopup = menu.GetSubMenu(INDEX_REQ_PASTE_MENU);
	}
	else if(moved_item->m_type == APL_TREE_ITEM_DOCUMENT)
	{
		pPopup = menu.GetSubMenu(INDEX_DOCUMENT_MENU);
		pPopup->EnableMenuItem(ID_DOCUMENT_INITIAL, MF_BYCOMMAND | MF_GRAYED);
	}
	else if(moved_item->m_type == APL_TREE_ITEM_CHARACTERISTIC)
		pPopup = menu.GetSubMenu(INDEX_CHARACTERISTIC_MENU);
	else if(moved_item->m_type == APL_TREE_ITEM_CHARACTERISTICGROUP)
		pPopup = menu.GetSubMenu(INDEX_CHARACTERISTIC_MENU);
	else
	{
		return false;
	}

	BOOL res = pPopup->TrackPopupMenu(TPM_LEFTALIGN|
		TPM_RIGHTBUTTON|TPM_RETURNCMD, pnt.x, pnt.y, m_tree);

	switch(res)
	{
		case ID_REQUIREMENT_MOVE : return MoveItem(moved_item, point);
		case ID_REQUIREMENT_COPY : return CopyItem(moved_item, point);
	
		case ID_DOCUMENT_COPY :
		{
			// Вставка документа
			CaplInstance *inst;
			CaplInstance *i_doc=((CaplDocTreeItem *)moved_item)->m_inst;
			inst = m_ciReq;

			HTREEITEM ht = m_tree->GetNextItem(moved_item->m_item, TVGN_PARENT);
			CaplTreeItem *Item = (CaplTreeItem*)m_tree->GetItemData(ht);
			aplAccessModeType access =aplOWN;

			if(Item)
			{
				aplExtent instances;
				Item->GetAccessedInstances(instances);
				access = instances.GetAt(0)->GetAccessmode();
			}

			if(m_ciReq->GetAccessmode()>aplRW || access>aplRO)
			{
				AfxMessageBox( APL_T("Нет доступа к объекту"));
				return false;
			}

			if(CaplDocTreeItem::InsertDoc(m_doc,this,&m_all_documents,i_doc,inst, false))
				ShowCmd(ID_SHOW_ALL_DOCS);

			break;			
		}

		case ID_DOCUMENT_BYDOT :
		{			
			//создание по образцу			
			CaplInstance *inst;
			CaplInstance *i_doc = ((CaplDocTreeItem *)moved_item)->m_inst;
			inst = m_ciReq;

			aplExtent instances;
			GetAccessedInstances(instances);
			if(m_doc->m_api.m_doc_mgr.CreateDocumentByDot(i_doc,instances[0]))
				ShowCmd(ID_SHOW_ALL_DOCS);

			break;
			
		}

		case ID_DOCUMENT_MOVE :
		{
			//премещение документа
			CaplDocTreeItem *d_item = (CaplDocTreeItem*)moved_item;
			HTREEITEM parent = m_tree->GetNextItem(d_item->m_item,TVGN_PARENT);
			CaplTreeItem *parent_item = (CaplTreeItem*)m_tree->GetItemData(parent);

			CaplDocTreeItem::MoveDocument(m_doc, d_item, parent_item, this);
			break;
		}
		// Вставка характеристики
		case ID_CHARACTERISTIC_COPY:
		{
			if(moved_item->m_type == APL_TREE_ITEM_CHARACTERISTIC)
			{
				CaplInstance *i_val=((CaplCharacteristicTreeItem *)moved_item)->m_val;
				CreateCharacteristic(m_ciReq,i_val);
			}
			else if(moved_item->m_type == APL_TREE_ITEM_CHARACTERISTICGROUP)
			{
				CreateCharacteristicGroup(m_ciReq,((CaplCharacteristicGroupTreeItem*)moved_item)->m_group);
			}
		}
	}	

	return false;
}

bool CaplRequirementTreeItem::ShowInListCtrl( CListCtrl *list )
{
	if(list==0) return false;
	CHECK_SHOW_LIST_CTRL(m_ciReq);
	if(m_doc==0)return false;

	int nIndex;
	CString strParam;
	aplExtent aeItems;
	CaplInstance *cit = 0;
	CStringArray saComment;
	CaplInstance *ciParent, *ciRoot;

	aeItems.Unique = false;
	
	// пользовательские атрибуты
	aeItems.Add(m_ciReq);
	saComment.Add( APL_T("Требование"));

	nIndex = list->InsertItem(list->GetItemCount(),  APL_T("Обозначение:"));
	m_doc_data.GetAttr(m_ciReq, m_doc->m_api.m_req_mgr.a_req_id, strParam);
	list->SetItemText(nIndex, 1, strParam);

	nIndex = list->InsertItem(list->GetItemCount(),  APL_T("Обозначение родительского требования:"));
	m_doc_data.GetAttr(m_ciReq, m_doc->m_api.m_req_mgr.a_req_parent, ciParent);
	if(ciParent)
	{
		aeItems.Add(ciParent);
		saComment.Add( APL_T("Родительское требование"));

		m_doc_data.GetAttr(ciParent, m_doc->m_api.m_req_mgr.a_req_id, strParam);
		list->SetItemText(nIndex, 1, strParam);
	}

	nIndex = list->InsertItem(list->GetItemCount(),  APL_T("Обозначение корневого требования:"));
	m_doc_data.GetAttr(m_ciReq, m_doc->m_api.m_req_mgr.a_req_root_parent, ciRoot);
	if(ciRoot)
	{
		aeItems.Add(ciRoot);
		saComment.Add( APL_T("Корневое требование"));

		m_doc_data.GetAttr(ciRoot, m_doc->m_api.m_req_mgr.a_req_id, strParam);
		list->SetItemText(nIndex, 1, strParam);
	}

	nIndex = list->InsertItem(list->GetItemCount(),  APL_T("Обозначение источника:"));
	m_doc_data.GetAttr(m_ciReq, m_doc->m_api.m_req_mgr.a_req_source, cit);
	if(cit)
	{
		aeItems.Add(cit);
		saComment.Add( APL_T("Источник"));

		m_doc_data.GetAttr(cit, m_doc->m_api.m_req_mgr.a_req_id, strParam);
		list->SetItemText(nIndex, 1, strParam);
	}

	nIndex = list->InsertItem(list->GetItemCount(),  APL_T("Методика определения соответствия:"));
	m_doc_data.GetAttr(m_ciReq, m_doc->m_api.m_req_mgr.a_req_mos, strParam);
	list->SetItemText(nIndex, 1, strParam);

	nIndex = list->InsertItem(list->GetItemCount(), _T(""));

	// системные атрибуты
	ShowInstanceInfoInListCtrl(aeItems, list, &saComment);

	return true;
}

BOOL CaplRequirementTreeItem::ShowToolBarButton(CCmdUI* pCmdUI)
{
	switch(pCmdUI->m_nID)
	{
	case ID_CREATE_DOC:
	case ID_CREATE_APPROVAL:
	case ID_CREATE_CHARACTERISTIC:
	case ID_SHOW_ALL_DOCS:
	case ID_SET_INST_ACCSESS:
	case ID_SHOW_ALL_APPROVAL:
	case ID_SHOW_ALL_CHARACTERISTIC:

		pCmdUI->Enable(TRUE); return TRUE; break;
	}

	return FALSE;
}

void CaplRequirementTreeItem::ShowCmd( long cmd )
{
	_APL_TREE_ITEM_CHEK_PARAM_VOID

	if(m_ciReq==0) return;
	if(m_ciReq->GetId()==0) return;
	if(m_ciReq->GetType()==0) return;

	switch (cmd)
	{
		case ID_EXPAND_ALL: {int i=1; ExpandAll(i);} break;

		case ID_SHOW_CHILDS: 
			m_expanded=false; 
			m_hasSubItem=false; 

			Expand(TVE_EXPAND); 
			m_tree->Expand(m_item, TVE_EXPAND);

			break; 

		case ID_CREATE_CHARACTERISTIC: CreateCharacteristic(m_ciReq); break;

		case ID_SHOW_ALL_DOCS:
		default: PrepareContextMenu(cmd);break;

	}

	RefreshItem();
}

void CaplRequirementTreeItem::Sort(bool bRefreshParent)
{
	if(m_tree==0) return;
	if(m_item==0) return;

	/*if(bRefreshParent)
	{
		if (m_tree->ItemHasChildren(m_item))
		{
			HTREEITEM hChildItem = m_tree->GetChildItem(m_item);

			while (hChildItem != NULL)
			{
				CaplTreeItem *item=(CaplTreeItem*)m_tree->GetItemData(hChildItem);
				if(item!=0)item->RefreshItem();
				hChildItem = m_tree->GetNextItem(hChildItem, TVGN_NEXT);
			}
		}
	}*/

	TVSORTCB sortcb;
	sortcb.hParent=m_item;
	sortcb.lpfnCompare=CompareHtreeItem;
	sortcb.lParam=1;
	m_tree->SortChildrenCB(&sortcb);
}

int CALLBACK CaplRequirementTreeItem::CompareHtreeItem(LPARAM lParam1, LPARAM lParam2,LPARAM lParamSort)
{
	if(lParam1==0) return 0;
	if(lParam2==0) return 0;
	CTreeCtrl *tree=((CaplTreeItem*)lParam1)->m_tree;
	if(tree==0) return 0;
	HTREEITEM item1=((CaplTreeItem*)lParam1)->m_item;
	HTREEITEM item2=((CaplTreeItem*)lParam2)->m_item;
	int img1,img2,img0;

	tree->GetItemImage(item1, img1, img0);
	tree->GetItemImage(item2, img2, img0);

	CaplAPI* api = &((CaplTreeItem*)lParam2)->m_doc->m_api;

	int rel1=0,rel2=0;
	int eff1=0,eff2=0;
	int state1=0,state2=0;

	CaplTreeItemData *itemdata1=(CaplTreeItemData*) tree->GetItemData(item1);
	if(itemdata1!=0)
	{
		if(itemdata1->icons[IDX_IL_TREE_ITEM]>0)
			img1=itemdata1->icons[IDX_IL_TREE_ITEM];
		if(itemdata1->icons[IDX_IL_TREE_REL_TYPE]>=0)
			rel1=itemdata1->icons[IDX_IL_TREE_REL_TYPE];		
	}

	CaplTreeItemData *itemdata2=(CaplTreeItemData*) tree->GetItemData(item2);
	if(itemdata2!=0)
	{
		if(itemdata2->icons[IDX_IL_TREE_ITEM]>0)
			img2=itemdata2->icons[IDX_IL_TREE_ITEM];
		if(itemdata2->icons[IDX_IL_TREE_REL_TYPE]>=0)
			rel2=itemdata2->icons[IDX_IL_TREE_REL_TYPE];		
	}

	int compare = api->aplCompareItemsImage(img1, img2);

	//if(compare==0)
	{
		if((itemdata1!=0) && (itemdata2!=0))
		{
			CaplTreeItem *treeitem1=(CaplTreeItem*)itemdata1;
			CaplTreeItem *treeitem2=(CaplTreeItem*)itemdata2;

			if((treeitem1->m_type==_T("Requirement")) && (treeitem2->m_type==_T("Requirement")))
			{
				// сравниваем 2 требования
				CString id1, id2;

				api->m_data.GetAttrBN(((CaplRequirementTreeItem*)treeitem1)->m_ciReq, _T("id"), id1);
				api->m_data.GetAttrBN(((CaplRequirementTreeItem*)treeitem2)->m_ciReq, _T("id"), id2);

				// добавляем нули в строку, чтобы сортировалось как цифра
				id1 = api->m_req_mgr.ConvertForRequirementSort(id1);
				id2 = api->m_req_mgr.ConvertForRequirementSort(id2);

				return id1.Compare(id2);
			}
		}

		if(rel1<rel2) return -1;
		if(rel1>rel2) return  1;
		if(eff1>eff2) return 1;
		if(eff1<eff2) return -1;
		if(state1<state2) return -1;
		if(state1>state2) return 1;
		return (tree->GetItemText(item1)).Compare(tree->GetItemText(item2));
	}
	/*else
	{
		return compare;
	}*/
} 

bool CaplRequirementTreeItem::ShowWhereUsed()
{
	CaplInstance *ciSource = NULL;

	m_doc->m_api.m_data.GetAttr(m_ciReq, m_doc->m_api.m_req_mgr.a_req_source, ciSource);
	if(!ciSource) 
	{
		AfxMessageBox( APL_T("Требование не имеет источника."), MB_ICONINFORMATION);
		return false;
	}

	if(ciSource->attrs == 0) m_doc->m_api.m_req_mgr.LoadReqInfo(ciSource);
	CaplRequirementTreeItem *pItem = new CaplRequirementTreeItem(m_tree, m_doc, ciSource);
	pItem->CreateTreeItem(m_item);

	pItem->SetItemImage(ICO_REL_WHERE_USED, IDX_IL_TREE_REL_TYPE, false);
	MyExpand(false);

	return true;
}

bool CaplRequirementTreeItem::ShowAssoc()
{
	CaplAttrValue val;
	aplExtent aeAssoc, ext;
	CaplInstance *ciPrd, *ciItem;
	CaplAPI *api = &m_doc->m_api;

	api->m_req_mgr.FindAssociatedItems(m_ciReq, ext, aeAssoc);
	for(int i=0; i<aeAssoc.Size; ++i)
	{
		api->m_data.GetAttr(aeAssoc[i], api->m_req_mgr.a_req_assoc_item, ciItem);
		if(!api->m_data.IsKindOf(ciItem, api->m_prd_mgr.e_pdf)) continue;

		api->m_data.GetAttr(ciItem, api->m_prd_mgr.a_pdf_prd, ciPrd);
		CaplProductTreeItem *pItem = new CaplProductTreeItem(m_tree, m_doc, ciPrd, ciItem);

		pItem->CreateTreeItem(m_item);
		pItem->SetItemImage(ICO_REL_WHERE_USED, IDX_IL_TREE_REL_TYPE, false);
	}

	MyExpand(false);
	return true;
}

bool CaplRequirementTreeItem::RemoveAssociation()
{
	if(m_ciAssoc == 0) return  false;
	if(m_ciAssoc->GetId() == 0) return false;
	if(m_ciAssoc->GetAccessmode() > aplRO)
	{
		AfxMessageBox(ID_NO_ACCESS_RIGHT,MB_OK|MB_ICONSTOP);
		return false;
	}

	m_doc_data.DeleteInstance(m_ciAssoc);
	return true;
}