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 
CPWL_ListCtrl()13 CPWL_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 
~CPWL_ListCtrl()22 CPWL_ListCtrl::~CPWL_ListCtrl()
23 {
24 }
25 
SetScrollPos(const CPDF_Point & point)26 void 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 
GetScrollPos() const43 CPDF_Point CPWL_ListCtrl::GetScrollPos() const
44 {
45 	return m_ptScroll;
46 }
47 
GetScrollArea() const48 CPDF_Rect CPWL_ListCtrl::GetScrollArea() const
49 {
50 	return m_rcContent;
51 }
52 
ResetFace()53 void CPWL_ListCtrl::ResetFace()
54 {
55 	ResetAll(FALSE, 0);
56 }
57 
ResetContent(FX_INT32 nStart)58 void 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 
GetContentsHeight(FX_FLOAT fLimitWidth)66 FX_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 
ResetAll(FX_BOOL bMove,FX_INT32 nStart)94 void 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 
SetItemSpace(FX_FLOAT fSpace)142 void CPWL_ListCtrl::SetItemSpace(FX_FLOAT fSpace)
143 {
144 	m_fItemSpace = fSpace;
145 }
146 
SetTopSpace(FX_FLOAT fSpace)147 void CPWL_ListCtrl::SetTopSpace(FX_FLOAT fSpace)
148 {
149 	m_fTopSpace = fSpace;
150 }
151 
SetBottomSpace(FX_FLOAT fSpace)152 void CPWL_ListCtrl::SetBottomSpace(FX_FLOAT fSpace)
153 {
154 	m_fBottomSpace = fSpace;
155 }
156 
RePosChildWnd()157 void CPWL_ListCtrl::RePosChildWnd()
158 {
159 	ResetFace();
160 }
161 
DrawChildAppearance(CFX_RenderDevice * pDevice,CPDF_Matrix * pUser2Device)162 void 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 
GetItemIndex(CPWL_Wnd * pItem)199 FX_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 
InToOut(const CPDF_Point & point) const210 CPDF_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 
OutToIn(const CPDF_Point & point) const218 CPDF_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 
InToOut(const CPDF_Rect & rect) const226 CPDF_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 
OutToIn(const CPDF_Rect & rect) const236 CPDF_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