1// Copyright 2014 PDFium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6
7#include "../../include/pdfwindow/PDFWindow.h"
8#include "../../include/pdfwindow/PWL_Wnd.h"
9#include "../../include/pdfwindow/PWL_ListCtrl.h"
10
11/* ---------------------------- CPWL_ListCtrl ---------------------------- */
12
13CPWL_ListCtrl::CPWL_ListCtrl() :
14	m_rcContent(0,0,0,0),
15	m_ptScroll(0,0),
16	m_fItemSpace(0.0f),
17	m_fTopSpace(0.0f),
18	m_fBottomSpace(0.0f)
19{
20}
21
22CPWL_ListCtrl::~CPWL_ListCtrl()
23{
24}
25
26void CPWL_ListCtrl::SetScrollPos(const CPDF_Point& point)
27{
28	m_ptScroll = point;
29
30	if (m_ptScroll.x < m_rcContent.left)
31		m_ptScroll.x = m_rcContent.left;
32
33	if (m_ptScroll.x > m_rcContent.right)
34		m_ptScroll.x = m_rcContent.right;
35
36	if (m_ptScroll.y > m_rcContent.top)
37		m_ptScroll.y = m_rcContent.top;
38
39	if (m_ptScroll.y < m_rcContent.bottom)
40		m_ptScroll.y = m_rcContent.bottom;
41}
42
43CPDF_Point CPWL_ListCtrl::GetScrollPos() const
44{
45	return m_ptScroll;
46}
47
48CPDF_Rect CPWL_ListCtrl::GetScrollArea() const
49{
50	return m_rcContent;
51}
52
53void CPWL_ListCtrl::ResetFace()
54{
55	ResetAll(FALSE, 0);
56}
57
58void CPWL_ListCtrl::ResetContent(FX_INT32 nStart)
59{
60	if (nStart < 0)
61		nStart = 0;
62	if (nStart >= 0 && nStart < m_aChildren.GetSize())
63		ResetAll(TRUE, nStart);
64}
65
66FX_FLOAT CPWL_ListCtrl::GetContentsHeight(FX_FLOAT fLimitWidth)
67{
68	FX_FLOAT fRet = m_fTopSpace;
69
70	FX_FLOAT fBorderWidth = (FX_FLOAT)this->GetBorderWidth();
71
72	if (fLimitWidth > fBorderWidth* 2)
73	{
74		for (FX_INT32 i=0,sz=m_aChildren.GetSize(); i<sz; i++)
75		{
76			if (CPWL_Wnd* pChild = m_aChildren.GetAt(i))
77			{
78				FX_FLOAT fLeft = pChild->GetItemLeftMargin();
79				FX_FLOAT fRight = pChild->GetItemRightMargin();
80
81				fRet += pChild->GetItemHeight(fLimitWidth - fBorderWidth* 2 - fLeft - fRight);
82				fRet += m_fItemSpace;
83			}
84		}
85
86		fRet -= m_fItemSpace;
87	}
88
89	fRet += m_fBottomSpace;
90
91	return fRet;
92}
93
94void CPWL_ListCtrl::ResetAll(FX_BOOL bMove, FX_INT32 nStart)
95{
96	CPDF_Rect rcClient = GetClientRect();
97
98	FX_FLOAT fWidth = rcClient.Width();
99
100	FX_FLOAT fy = 0.0f - m_fTopSpace;
101
102	if (nStart-1 >= 0 && nStart-1 < m_aChildren.GetSize())
103		if (CPWL_Wnd* pChild = m_aChildren.GetAt(nStart-1))
104			fy = pChild->GetWindowRect().bottom - m_fItemSpace;
105
106	for (FX_INT32 i=nStart,sz=m_aChildren.GetSize(); i<sz; i++)
107	{
108		if (CPWL_Wnd* pChild = m_aChildren.GetAt(i))
109		{
110			FX_FLOAT fLeft = pChild->GetItemLeftMargin();
111			FX_FLOAT fRight = pChild->GetItemRightMargin();
112
113			pChild->SetChildMatrix(
114				CPDF_Matrix(1,0,0,1,
115				rcClient.left - m_ptScroll.x,
116				rcClient.top - m_ptScroll.y)
117				);
118
119			if (bMove)
120			{
121				FX_FLOAT fItemHeight = pChild->GetItemHeight(fWidth - fLeft - fRight);
122				pChild->Move(CPDF_Rect(fLeft, fy-fItemHeight, fWidth - fRight, fy), TRUE, FALSE);
123				fy -= fItemHeight;
124				fy -= m_fItemSpace;
125			}
126		}
127	}
128
129	fy += m_fItemSpace;
130
131	fy -= m_fBottomSpace;
132
133	if (bMove)
134	{
135		m_rcContent.left = 0;
136		m_rcContent.top = 0;
137		m_rcContent.right = fWidth;
138		m_rcContent.bottom = fy;
139	}
140}
141
142void CPWL_ListCtrl::SetItemSpace(FX_FLOAT fSpace)
143{
144	m_fItemSpace = fSpace;
145}
146
147void CPWL_ListCtrl::SetTopSpace(FX_FLOAT fSpace)
148{
149	m_fTopSpace = fSpace;
150}
151
152void CPWL_ListCtrl::SetBottomSpace(FX_FLOAT fSpace)
153{
154	m_fBottomSpace = fSpace;
155}
156
157void CPWL_ListCtrl::RePosChildWnd()
158{
159	ResetFace();
160}
161
162void CPWL_ListCtrl::DrawChildAppearance(CFX_RenderDevice* pDevice, CPDF_Matrix* pUser2Device)
163{
164	pDevice->SaveState();
165	CPDF_Rect rcClient = GetClientRect();
166	CPDF_Rect rcTemp = rcClient;
167	pUser2Device->TransformRect(rcTemp);
168	FX_RECT rcClip((FX_INT32)rcTemp.left,
169		(FX_INT32)rcTemp.bottom,
170		(FX_INT32)rcTemp.right,
171		(FX_INT32)rcTemp.top);
172
173	pDevice->SetClip_Rect(&rcClip);
174
175	for (FX_INT32 i=0,sz=m_aChildren.GetSize(); i<sz; i++)
176	{
177		if (CPWL_Wnd * pChild = m_aChildren.GetAt(i))
178		{
179			CPDF_Rect rcChild = pChild->ChildToParent(pChild->GetWindowRect());
180			if (!(rcChild.top < rcClient.bottom || rcChild.bottom > rcClient.top))
181			{
182				CPDF_Matrix mt = pChild->GetChildMatrix();
183				if (mt.IsIdentity())
184				{
185					pChild->DrawAppearance(pDevice,pUser2Device);
186				}
187				else
188				{
189					mt.Concat(*pUser2Device);
190					pChild->DrawAppearance(pDevice,&mt);
191				}
192			}
193		}
194	}
195
196	pDevice->RestoreState();
197}
198
199FX_INT32 CPWL_ListCtrl::GetItemIndex(CPWL_Wnd* pItem)
200{
201	for (FX_INT32 i=0, sz=m_aChildren.GetSize(); i<sz; i++)
202	{
203		if (pItem == m_aChildren.GetAt(i))
204			return i;
205	}
206
207	return -1;
208}
209
210CPDF_Point CPWL_ListCtrl::InToOut(const CPDF_Point& point) const
211{
212	CPDF_Rect rcClient = GetClientRect();
213
214	return CPDF_Point(point.x + rcClient.left - m_ptScroll.x,
215		point.y + rcClient.top - m_ptScroll.y);
216}
217
218CPDF_Point CPWL_ListCtrl::OutToIn(const CPDF_Point& point) const
219{
220	CPDF_Rect rcClient = GetClientRect();
221
222	return CPDF_Point(point.x - rcClient.left + m_ptScroll.x,
223		point.y - rcClient.top + m_ptScroll.y);
224}
225
226CPDF_Rect CPWL_ListCtrl::InToOut(const CPDF_Rect& rect) const
227{
228	CPDF_Rect rcClient = GetClientRect();
229
230	return CPDF_Rect(rect.left + rcClient.left - m_ptScroll.x,
231		rect.bottom + rcClient.top - m_ptScroll.y,
232		rect.right + rcClient.left - m_ptScroll.x,
233		rect.top + rcClient.top - m_ptScroll.y);
234}
235
236CPDF_Rect CPWL_ListCtrl::OutToIn(const CPDF_Rect& rect) const
237{
238	CPDF_Rect rcClient = GetClientRect();
239
240	return CPDF_Rect(rect.left - rcClient.left + m_ptScroll.x,
241		rect.bottom - rcClient.top + m_ptScroll.y,
242		rect.right - rcClient.left + m_ptScroll.x,
243		rect.top - rcClient.top + m_ptScroll.y);
244}
245
246