// BoundArray.cpp: implementation of the CBoundArray class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "ReportDict.h"

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

CBoundArray::CBoundArray()
{

}

CBoundArray::~CBoundArray()
{
	RemoveAll();
}

void CBoundArray::Add(CBoundRect *br)
{
	m_Data.Add(br);
}

CBoundRect* CBoundArray::GetAt(int ind)
{
	return m_Data.GetAt(ind);
}

void CBoundArray::RemoveAt(int ind)
{
	CBoundRect *br = m_Data.GetAt(ind);
	if(br!=0) delete br;
	m_Data.RemoveAt(ind);
}

int CBoundArray::GetSize()
{
	return m_Data.GetSize();
}

void CBoundArray::RemoveAll()
{
	int i, cnt = m_Data.GetSize();
	CString tst = _T("");
	for(i=0; i<cnt; i++)
	{
		CBoundRect *br = m_Data.GetAt(i);
		tst.Format(_T("Delete %d %d"),i, (DWORD)br);
		if(br!=0) DELETE_OBJECT(br);
	}
	m_Data.RemoveAll();
}

CPoint CBoundArray::GetBottomRight(double scale)
{
	CPoint res;
	int cnt=m_Data.GetSize(); 
	if(cnt==0)
		return CPoint(0, 0);
	CBoundRect *br = m_Data.GetAt(0);
	CRect rect;
	br->GetRect(rect, scale, 1);
	rect.NormalizeRect();
	res = rect.BottomRight();
	for(int i=1; i<cnt;i++)
	{
		br = m_Data.GetAt(i);
		if(br==0)
			continue;
		br->GetRect(rect, scale, 1);
		rect.NormalizeRect();
		res.y = rect.bottom>res.y ? rect.bottom : res.y;
		res.x = rect.right>res.x ? rect.right : res.x;
	}
	return res;
}
CPoint CBoundArray::GetTopLeft(double scale)
{
	CPoint res;
	int cnt=m_Data.GetSize(); 
	if(cnt==0)
		return CPoint(0, 0);
	CBoundRect *br = m_Data.GetAt(0);
	CRect rect;
	br->GetRect(rect, scale, 1);
	rect.NormalizeRect();
	res = rect.TopLeft();
	for(int i=1; i<cnt;i++)
	{
		br = m_Data.GetAt(i);
		if(br==0)
			continue;
		br->GetRect(rect, scale, 1);
		rect.NormalizeRect();
		res.y = rect.top<res.y ? rect.top : res.y;
		res.x = rect.left<res.x ? rect.left : res.x;
	}
	return res;
}
CRect CBoundArray::GetRect(double scale)
{
	CRect rect;
	rect.TopLeft() = GetTopLeft(scale);
	rect.BottomRight() = GetBottomRight(scale);
	rect.NormalizeRect();
	return rect;
}

BOOL CBoundArray::TraceBoundRect(CPoint point, CDC *pDC, double scale, bool TestElems, bool bDraw)
{
	if(m_Data.GetSize()==0) return FALSE;

	CReportSheet *pSheet = m_Data.GetAt(0)->m_owner_sheet;
	//Пересчет в масштаб 1:1
	pSheet->PtLogToSheet(point);
	point.x = (long)((double)(point.x)/scale);
	point.y = (long)((double)(point.y)/scale);
	//непосредственно обрабатываем Trace
	//Проверяем, чтобы элементы не выходили за границы листа
	int i;
	if(m_Data.GetAt(0)->m_elem_drag_mode==OBJ_MOVE && TestElems)
	{
		CRect rect;
		CPoint tl, br, offset;
		CPoint cur_pt = m_Data.GetAt(0)->m_cur_pt;

		UINT flag = 0;
		CPoint pt;

		//проверяем а можно ли вообще двигать объекты?
		//если хоть один зафиксирован, то нельзя!
		for(i=0; i<m_Data.GetSize(); i++)
		{
			if(m_Data[i]->m_work_elem)
			{
				if(m_Data[i]->m_work_elem->m_fixed==1) return TRUE;
			}
		}

		offset = point-cur_pt;
		rect.SetRect(GetTopLeft(), GetBottomRight());
		rect.NormalizeRect();
		rect.OffsetRect(offset);
		tl = rect.TopLeft();
		br = rect.BottomRight();
		
		if(tl.x<0)
			point.x-=tl.x;
		if(tl.y<-pSheet->m_size.cy)
			point.y-=(pSheet->m_size.cy+tl.y);
		if(br.x>pSheet->m_size.cx)
			point.x+=(pSheet->m_size.cx-br.x);
		if(br.y>0)
			point.y-=br.y;

		CReportElement *elem = pSheet->TestMoveRect(m_Data.GetAt(0)->m_work_elem, rect, pt, flag);
		if(elem!=NULL)
		{
			if(flag&STICK_TOP)
				point.y -=pt.y;
			if(flag&STICK_BOTTOM)
				point.y -=pt.y;
			if(flag&STICK_LEFT)
				point.x -=pt.x;
			if(flag&STICK_RIGHT)
				point.x -=pt.x;
		}
	}

	for(i=0; i<m_Data.GetSize();i++)
	{
		CBoundRect *br = m_Data.GetAt(i);
		if(br==0) 
		{
			m_Data.RemoveAt(i);
			i--;
			continue;
		}
		if(br->m_work_elem)
		{
			if(br->m_work_elem->m_fixed==1) continue;
		}
		br->TraceBoundRect(point, pDC, scale, bDraw);
	}

	return TRUE;
}

void CBoundArray::StartObjOper(CReportSheet *pSheet, CReportElement * elem, int drag_mode,CPoint pt, double scale)
{
	if(pSheet==NULL) return;

	pSheet->PtLogToSheet(pt);
	
	pt.x = (long)((double)(pt.x)/scale);
	pt.y = (long)((double)(pt.y)/scale);

	CBoundRect *pBoundRect = new CBoundRect(pSheet, pSheet->m_ReportMgr);
	pBoundRect->StartObjOper(elem, drag_mode, pt);
	m_Data.Add(pBoundRect);
}
