// Copyright 2014 PDFium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
 
// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com

#include "../../include/pdfwindow/PDFWindow.h"
#include "../../include/pdfwindow/PWL_Wnd.h"
#include "../../include/pdfwindow/PWL_ListCtrl.h"

/* ---------------------------- CPWL_ListCtrl ---------------------------- */

CPWL_ListCtrl::CPWL_ListCtrl() : 
	m_rcContent(0,0,0,0),
	m_ptScroll(0,0), 
	m_fItemSpace(0.0f),
	m_fTopSpace(0.0f),
	m_fBottomSpace(0.0f)
{
}

CPWL_ListCtrl::~CPWL_ListCtrl()
{
}

void CPWL_ListCtrl::SetScrollPos(const CPDF_Point& point)
{
	m_ptScroll = point;

	if (m_ptScroll.x < m_rcContent.left)
		m_ptScroll.x = m_rcContent.left;

	if (m_ptScroll.x > m_rcContent.right)
		m_ptScroll.x = m_rcContent.right;

	if (m_ptScroll.y > m_rcContent.top)
		m_ptScroll.y = m_rcContent.top;

	if (m_ptScroll.y < m_rcContent.bottom)
		m_ptScroll.y = m_rcContent.bottom;	
}

CPDF_Point CPWL_ListCtrl::GetScrollPos() const
{
	return m_ptScroll;
}

CPDF_Rect CPWL_ListCtrl::GetScrollArea() const
{
	return m_rcContent;
}

void CPWL_ListCtrl::ResetFace()
{
	ResetAll(FALSE, 0);
}

void CPWL_ListCtrl::ResetContent(int32_t nStart)
{
	if (nStart < 0)
		nStart = 0;
	if (nStart >= 0 && nStart < m_aChildren.GetSize())
		ResetAll(TRUE, nStart);
}

FX_FLOAT CPWL_ListCtrl::GetContentsHeight(FX_FLOAT fLimitWidth)
{
	FX_FLOAT fRet = m_fTopSpace;

	FX_FLOAT fBorderWidth = (FX_FLOAT)this->GetBorderWidth();

	if (fLimitWidth > fBorderWidth* 2)
	{
		for (int32_t i=0,sz=m_aChildren.GetSize(); i<sz; i++)
		{
			if (CPWL_Wnd* pChild = m_aChildren.GetAt(i))
			{
				FX_FLOAT fLeft = pChild->GetItemLeftMargin();
				FX_FLOAT fRight = pChild->GetItemRightMargin();

				fRet += pChild->GetItemHeight(fLimitWidth - fBorderWidth* 2 - fLeft - fRight);
				fRet += m_fItemSpace;
			}
		}

		fRet -= m_fItemSpace;
	}

	fRet += m_fBottomSpace;

	return fRet;
}

void CPWL_ListCtrl::ResetAll(FX_BOOL bMove, int32_t nStart)
{
	CPDF_Rect rcClient = GetClientRect();

	FX_FLOAT fWidth = rcClient.Width();

	FX_FLOAT fy = 0.0f - m_fTopSpace;

	if (nStart-1 >= 0 && nStart-1 < m_aChildren.GetSize())
		if (CPWL_Wnd* pChild = m_aChildren.GetAt(nStart-1))
			fy = pChild->GetWindowRect().bottom - m_fItemSpace;

	for (int32_t i=nStart,sz=m_aChildren.GetSize(); i<sz; i++)
	{
		if (CPWL_Wnd* pChild = m_aChildren.GetAt(i))
		{
			FX_FLOAT fLeft = pChild->GetItemLeftMargin();
			FX_FLOAT fRight = pChild->GetItemRightMargin();

			pChild->SetChildMatrix(
				CPDF_Matrix(1,0,0,1, 
				rcClient.left - m_ptScroll.x, 
				rcClient.top - m_ptScroll.y)
				);

			if (bMove)
			{
				FX_FLOAT fItemHeight = pChild->GetItemHeight(fWidth - fLeft - fRight);
				pChild->Move(CPDF_Rect(fLeft, fy-fItemHeight, fWidth - fRight, fy), TRUE, FALSE);
				fy -= fItemHeight;
				fy -= m_fItemSpace;
			}
		}
	}

	fy += m_fItemSpace;

	fy -= m_fBottomSpace;

	if (bMove)
	{
		m_rcContent.left = 0;
		m_rcContent.top = 0;
		m_rcContent.right = fWidth;
		m_rcContent.bottom = fy;
	}
}

void CPWL_ListCtrl::SetItemSpace(FX_FLOAT fSpace)
{
	m_fItemSpace = fSpace;
}

void CPWL_ListCtrl::SetTopSpace(FX_FLOAT fSpace)
{
	m_fTopSpace = fSpace;
}

void CPWL_ListCtrl::SetBottomSpace(FX_FLOAT fSpace)
{
	m_fBottomSpace = fSpace;
}

void CPWL_ListCtrl::RePosChildWnd()
{
	ResetFace();
}

void CPWL_ListCtrl::DrawChildAppearance(CFX_RenderDevice* pDevice, CPDF_Matrix* pUser2Device)
{
	pDevice->SaveState();
	CPDF_Rect rcClient = GetClientRect();
	CPDF_Rect rcTemp = rcClient;
	pUser2Device->TransformRect(rcTemp);
	FX_RECT rcClip((int32_t)rcTemp.left,
		(int32_t)rcTemp.bottom,
		(int32_t)rcTemp.right,
		(int32_t)rcTemp.top);

	pDevice->SetClip_Rect(&rcClip);

	for (int32_t i=0,sz=m_aChildren.GetSize(); i<sz; i++)
	{
		if (CPWL_Wnd * pChild = m_aChildren.GetAt(i))
		{
			CPDF_Rect rcChild = pChild->ChildToParent(pChild->GetWindowRect());
			if (!(rcChild.top < rcClient.bottom || rcChild.bottom > rcClient.top))
			{
				CPDF_Matrix mt = pChild->GetChildMatrix();
				if (mt.IsIdentity())
				{
					pChild->DrawAppearance(pDevice,pUser2Device);
				}
				else
				{
					mt.Concat(*pUser2Device);
					pChild->DrawAppearance(pDevice,&mt);
				}
			}
		}
	}
	
	pDevice->RestoreState();
}

int32_t CPWL_ListCtrl::GetItemIndex(CPWL_Wnd* pItem)
{
	for (int32_t i=0, sz=m_aChildren.GetSize(); i<sz; i++)
	{
		if (pItem == m_aChildren.GetAt(i))
			return i;
	}

	return -1;
}

CPDF_Point CPWL_ListCtrl::InToOut(const CPDF_Point& point) const
{
	CPDF_Rect rcClient = GetClientRect();

	return CPDF_Point(point.x + rcClient.left - m_ptScroll.x, 
		point.y + rcClient.top - m_ptScroll.y);
}

CPDF_Point CPWL_ListCtrl::OutToIn(const CPDF_Point& point) const
{
	CPDF_Rect rcClient = GetClientRect();

	return CPDF_Point(point.x - rcClient.left + m_ptScroll.x, 
		point.y - rcClient.top + m_ptScroll.y);
}

CPDF_Rect CPWL_ListCtrl::InToOut(const CPDF_Rect& rect) const
{
	CPDF_Rect rcClient = GetClientRect();

	return CPDF_Rect(rect.left + rcClient.left - m_ptScroll.x,
		rect.bottom + rcClient.top - m_ptScroll.y,
		rect.right + rcClient.left - m_ptScroll.x,
		rect.top + rcClient.top - m_ptScroll.y);
}

CPDF_Rect CPWL_ListCtrl::OutToIn(const CPDF_Rect& rect) const
{
	CPDF_Rect rcClient = GetClientRect();

	return CPDF_Rect(rect.left - rcClient.left + m_ptScroll.x,
		rect.bottom - rcClient.top + m_ptScroll.y,
		rect.right - rcClient.left + m_ptScroll.x,
		rect.top - rcClient.top + m_ptScroll.y);
}

