// LineReportElement.cpp: implementation of the CReportElement class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "resource.h"
#include "ReportDict.h"
#include "PropertyDlg.h"
#include "SelectTableDlg.h"
#include <math.h>
#include "Functions.h"

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

//#define GRPZ

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CLineReportElement::CLineReportElement(CaplReportMgr *ReportMgr):CReportElement(ReportMgr, E_LINE)
{
	m_name = APL_T("Линия");
}

CLineReportElement::~CLineReportElement()
{
}

int CLineReportElement::ShowContextMenu(CPoint pt, CWnd * wnd, int mode)
{
	if(wnd == NULL) return false;
	
	HINSTANCE hInst = AfxGetResourceHandle();
	AfxSetResourceHandle(dllInst);
	wnd->ClientToScreen(&pt);

	CMenu menu;
	CMenu *pPopup;
	menu.LoadMenu(IDR_CONTEXT_MENU);
	pPopup = menu.GetSubMenu(5);

	if(m_fixed && mode==0)
		pPopup->ModifyMenu(ID_FIXED,MF_BYCOMMAND|MF_STRING, ID_FIXED,APL_T("Раcфиксировать"));

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

	AfxSetResourceHandle(hInst);
	if(res == 0) return false;

	switch(res)
	{
		case ID_FIXED :
			if(m_fixed>0) m_fixed = 0;
			else m_fixed = 1;
			break;
		case ID_ALIGN :
			Align();
			break;
		default : 
			return ExecuteCmd(res);
	}
	return 0;
}

void CLineReportElement::Update(bool set)
{
	if(set)		
	{
		if(m_inst==0)
			m_inst = m_ReportMgr->m_data->CreateInstance(m_ReportMgr->e_report_line);
		m_ReportMgr->m_data->PutAttr(m_inst, m_ReportMgr->a_elem_name,m_name);
		m_ReportMgr->m_data->PutAttr(m_inst, m_ReportMgr->a_elem_line_width,m_line_width);
		m_ReportMgr->m_data->PutAttr(m_inst, m_ReportMgr->a_elem_fixed,m_fixed);
		
		m_ReportMgr->m_data->PutAttr(m_inst, m_ReportMgr->a_elem_dsfrow, 0);
		m_ReportMgr->m_data->PutAttr(m_inst, m_ReportMgr->a_elem_dsfcol, 0);
		
		m_ReportMgr->m_data->PutAttr(m_inst, m_ReportMgr->a_elem_textcolor, (int)m_color);
		m_ReportMgr->m_data->PutAttr(m_inst, m_ReportMgr->a_elem_backgroundcolor, (int)m_background_color);
		
		m_ReportMgr->PutPoint(m_inst,m_ReportMgr->a_elem_org_pt,m_org_pt);
		m_ReportMgr->PutPoint(m_inst,m_ReportMgr->a_elem_size,m_size);
	}
	else
	{
		if(m_inst==0) return;
		m_ReportMgr->m_data->GetAttr(m_inst,m_ReportMgr->a_elem_name,m_name);
		m_ReportMgr->m_data->GetAttr(m_inst,m_ReportMgr->a_elem_line_width,m_line_width);
		m_ReportMgr->m_data->GetAttr(m_inst,m_ReportMgr->a_elem_fixed,m_fixed);
		
		int tmp;
		m_ReportMgr->m_data->GetAttr(m_inst, m_ReportMgr->a_elem_textcolor, tmp);
		m_color = (COLORREF)tmp;
		m_ReportMgr->m_data->GetAttr(m_inst, m_ReportMgr->a_elem_backgroundcolor, tmp);
		m_background_color= (COLORREF)tmp;
		
		m_ReportMgr->GetPoint(m_inst,m_ReportMgr->a_elem_org_pt,m_org_pt);
		m_ReportMgr->GetPoint(m_inst,m_ReportMgr->a_elem_size,m_size);
	}
}


int CLineReportElement::GetMemSize()
{
	int int_size = sizeof(int);
	int size = 4*int_size;//размер элемента;
	size+=sizeof(TReportElementType);//тип элемента;
	size+=int_size;//толщина линии;
	size+=sizeof(COLORREF);//line_color;
	return size;
}	

void CLineReportElement::CopyToMem(BYTE *pByte, int &ind)
{
	int* pInt = NULL;
	int int_size = sizeof(int);
	
	pInt = (int*)&pByte[ind];
	*pInt = m_type;//записал тип элемента;
	ind+=int_size;
	
	pInt = (int*)&pByte[ind];
	*pInt = m_org_pt.x;//записал x;
	ind+=int_size;
	
	pInt = (int*)&pByte[ind];
	*pInt = m_org_pt.y;//записал y;
	ind+=int_size;
	
	pInt = (int*)&pByte[ind];
	*pInt = m_size.cx;//записал cx;
	ind+=int_size;
	
	pInt = (int*)&pByte[ind];
	*pInt = m_size.cy;//записал cy;
	ind+=int_size;
	
	pInt = (int*)&pByte[ind];
	*pInt = m_line_width;//записал толщину линии;
	ind+=int_size;

	COLORREF *pCR = (COLORREF*)&pByte[ind];
	*pCR = m_color;//записал цвет линии;
	ind+=sizeof(COLORREF);
}

bool CLineReportElement::LoadDataFromMem(BYTE *pByte, int &ind)
{
	int* pInt = NULL;
	int int_size = sizeof(int);
	
	pInt = (int*)&pByte[ind];
	m_org_pt.x = *pInt;
	ind+=int_size;
	
	pInt = (int*)&pByte[ind];
	m_org_pt.y = *pInt;
	ind+=int_size;
	
	pInt = (int*)&pByte[ind];
	m_size.cx = *pInt;//записал cx;
	ind+=int_size;
	
	pInt = (int*)&pByte[ind];
	m_size.cy = *pInt;//записал cy;
	ind+=int_size;
	
	pInt = (int*)&pByte[ind];
	m_line_width = *pInt;//записал толщину линии;
	ind+=int_size;

	COLORREF *pCR = (COLORREF*)&pByte[ind];
	m_color = *pCR;//записал цвет линии;
	ind+=sizeof(COLORREF);
	
	return true;
}


void CLineReportElement::Delete()
{
	if(m_inst==0) return;
	
	CaplInstance* inst;
	//Удаление точек
	m_ReportMgr->m_data->GetAttr(m_inst, m_ReportMgr->a_elem_org_pt, inst);
	if(inst)
		m_ReportMgr->m_data->DeleteInstance(inst);
	m_ReportMgr->m_data->GetAttr(m_inst, m_ReportMgr->a_elem_size, inst);
	if(inst)
		m_ReportMgr->m_data->DeleteInstance(inst);
}

CReportElement* CLineReportElement::CreateClon()
{
	CLineReportElement* elem = new CLineReportElement(m_ReportMgr);
	elem->m_org_pt = m_org_pt;
	elem->m_name = m_name;
	elem->m_size = m_size;
	elem->m_type = m_type;
	elem->m_fixed = m_fixed;
	elem->m_line_width = m_line_width;
	elem->m_color = m_color;
	return elem;
}

BOOL CLineReportElement::Draw(CDC *pDC, double scale, int draw_mode, UINT flag)
{
	if(pDC==NULL) return FALSE;
	if(scale==0) return FALSE;
	CRect rect; 
	GetRect(rect, scale, pDC->IsPrinting()); // получаем координаты прямоугольника 
	CPen m_obj_pen;
	CBrush m_bg_brush;
	m_obj_pen.CreatePen(PS_SOLID | PS_GEOMETRIC, (int)(m_line_width*scale),OBJ_COLOR);
	m_bg_brush.CreateSolidBrush(BG_COLOR);
	
	CPen *old = pDC->SelectObject(&m_obj_pen);
	if(m_line_width>0)
		DrawLine(pDC,rect.TopLeft(), rect.BottomRight());
	else if(draw_mode==0)
	{
		m_obj_pen.DeleteObject();
		m_obj_pen.CreatePen(PS_SOLID|PS_GEOMETRIC,1,::GetSysColor(COLOR_GRAYTEXT));
		pDC->SelectObject(&m_obj_pen);
		DrawLine(pDC,rect.TopLeft(), rect.BottomRight());
	}
	
	if(m_select && !pDC->IsPrinting() && flag&DRAW_SEL) DrawSelPoints(pDC, scale);

	pDC->SelectObject(old);
	m_obj_pen.DeleteObject();
	m_bg_brush.DeleteObject();
	
	return true;
}

int CLineReportElement::GetDragMode(CPoint pt, int &flag, double scale)
{
	int i;
	CRect rect, rect1;
	GetRect(rect, scale);
	PointArray sel_pts;
	GetSelPts(sel_pts,NULL,scale); // получение точек выделения
	
	for(i=0; i < sel_pts.GetSize(); i++)
	{
		if(GetSelPtRect(sel_pts[i]).PtInRect(pt))
		{
			if(m_fixed) return OBJ_FIXED;
			switch(i)
			{				
			case 0: return L_RESIZE;
			case 1: return OBJ_MOVE;
			case 2: return R_RESIZE;
			}
		}
	}
	CRect wr=  rect;
	rect.NormalizeRect();
	if(m_type==E_LINE)
		rect.DeflateRect(CSize(-10,-10));
	if(rect.PtInRect(pt))
	{
		if(m_fixed) return OBJ_FIXED;
		CPoint org_pt;
		org_pt = m_org_pt;
		double dx1, dy1, dx2, dy2;
		dx1 = wr.left - pt.x;
		dy1 = wr.top - pt.y;
		dx2 = wr.right - pt.x;
		dy2 = wr.bottom - pt.y;
		double a = dx1*dx1 + dy1*dy1;
		double b = dx2*dx2 + dy2*dy2;
		double c = m_size.cx*scale*m_size.cx*scale + m_size.cy*scale*m_size.cy*scale;
		double y = (a-b+c)/(2*sqrt(c));
		double x = sqrt(a - y*y);
		if(x<=20)
			return OBJ_MOVE;
	}
	
	return NONE;
}
