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 <memory>
8 
9 #include "xfa/src/foxitlib.h"
10 
Create()11 CFWL_ListBox* CFWL_ListBox::Create() {
12   return new CFWL_ListBox;
13 }
Initialize(const CFWL_WidgetProperties * pProperties)14 FWL_ERR CFWL_ListBox::Initialize(const CFWL_WidgetProperties* pProperties) {
15   if (m_pIface)
16     return FWL_ERR_Indefinite;
17   if (pProperties) {
18     *m_pProperties = *pProperties;
19   }
20   std::unique_ptr<IFWL_ListBox> pListBox(IFWL_ListBox::Create(
21       m_pProperties->MakeWidgetImpProperties(&m_ListBoxDP), nullptr));
22   FWL_ERR ret = pListBox->Initialize();
23   if (ret != FWL_ERR_Succeeded) {
24     return ret;
25   }
26   m_pIface = pListBox.release();
27   CFWL_Widget::Initialize();
28   return FWL_ERR_Succeeded;
29 }
AddDIBitmap(CFX_DIBitmap * pDIB,FWL_HLISTITEM hItem)30 FWL_ERR CFWL_ListBox::AddDIBitmap(CFX_DIBitmap* pDIB, FWL_HLISTITEM hItem) {
31   reinterpret_cast<CFWL_ListItem*>(hItem)->m_pDIB = pDIB;
32   return FWL_ERR_Succeeded;
33 }
AddString(const CFX_WideStringC & wsAdd,FX_BOOL bSelect)34 FWL_HLISTITEM CFWL_ListBox::AddString(const CFX_WideStringC& wsAdd,
35                                       FX_BOOL bSelect) {
36   CFWL_ListItem* pItem = new CFWL_ListItem;
37   pItem->m_dwStates = 0;
38   pItem->m_wsText = wsAdd;
39   pItem->m_dwStates = bSelect ? FWL_ITEMSTATE_LTB_Selected : 0;
40   m_ListBoxDP.m_arrItem.Add(pItem);
41   return (FWL_HLISTITEM)pItem;
42 }
DeleteString(FWL_HLISTITEM hItem)43 FX_BOOL CFWL_ListBox::DeleteString(FWL_HLISTITEM hItem) {
44   int32_t nIndex = m_ListBoxDP.GetItemIndex(GetWidget(), hItem);
45   if (nIndex < 0 || nIndex >= m_ListBoxDP.m_arrItem.GetSize()) {
46     return FALSE;
47   }
48   CFWL_ListItem* pDelItem =
49       reinterpret_cast<CFWL_ListItem*>(m_ListBoxDP.GetItem(m_pIface, nIndex));
50   int32_t iCount = m_ListBoxDP.CountItems(m_pIface);
51   int32_t iSel = nIndex + 1;
52   if (iSel >= iCount) {
53     iSel = nIndex - 1;
54     if (iSel < 0) {
55       iSel = -1;
56     }
57   }
58   if (iSel >= 0) {
59     CFWL_ListItem* pSel =
60         reinterpret_cast<CFWL_ListItem*>(m_ListBoxDP.GetItem(m_pIface, iSel));
61     pSel->m_dwStates |= FWL_ITEMSTATE_LTB_Selected;
62   }
63   m_ListBoxDP.m_arrItem.RemoveAt(nIndex);
64   delete pDelItem;
65   return TRUE;
66 }
DeleteAll()67 FX_BOOL CFWL_ListBox::DeleteAll() {
68   int32_t iCount = m_ListBoxDP.CountItems(m_pIface);
69   for (int32_t i = 0; i < iCount; i++) {
70     CFWL_ListItem* pItem =
71         reinterpret_cast<CFWL_ListItem*>(m_ListBoxDP.GetItem(m_pIface, i));
72     delete pItem;
73   }
74   m_ListBoxDP.m_arrItem.RemoveAll();
75   return TRUE;
76 }
CountSelItems()77 int32_t CFWL_ListBox::CountSelItems() {
78   if (!m_pIface)
79     return 0;
80   return static_cast<IFWL_ListBox*>(m_pIface)->CountSelItems();
81 }
GetSelItem(int32_t nIndexSel)82 FWL_HLISTITEM CFWL_ListBox::GetSelItem(int32_t nIndexSel) {
83   if (!m_pIface)
84     return NULL;
85   return static_cast<IFWL_ListBox*>(m_pIface)->GetSelItem(nIndexSel);
86 }
GetSelIndex(int32_t nIndex)87 int32_t CFWL_ListBox::GetSelIndex(int32_t nIndex) {
88   if (!m_pIface)
89     return 0;
90   return static_cast<IFWL_ListBox*>(m_pIface)->GetSelIndex(nIndex);
91 }
SetSelItem(FWL_HLISTITEM hItem,FX_BOOL bSelect)92 FWL_ERR CFWL_ListBox::SetSelItem(FWL_HLISTITEM hItem, FX_BOOL bSelect) {
93   if (!m_pIface)
94     return FWL_ERR_Indefinite;
95   return static_cast<IFWL_ListBox*>(m_pIface)->SetSelItem(hItem, bSelect);
96 }
GetItemText(FWL_HLISTITEM hItem,CFX_WideString & wsText)97 FWL_ERR CFWL_ListBox::GetItemText(FWL_HLISTITEM hItem, CFX_WideString& wsText) {
98   if (!m_pIface)
99     return FWL_ERR_Indefinite;
100   return static_cast<IFWL_ListBox*>(m_pIface)->GetItemText(hItem, wsText);
101 }
GetScrollPos(FX_FLOAT & fPos,FX_BOOL bVert)102 FWL_ERR CFWL_ListBox::GetScrollPos(FX_FLOAT& fPos, FX_BOOL bVert) {
103   if (!m_pIface)
104     return FWL_ERR_Indefinite;
105   return static_cast<IFWL_ListBox*>(m_pIface)->GetScrollPos(fPos, bVert);
106 }
SetItemHeight(FX_FLOAT fItemHeight)107 FWL_ERR CFWL_ListBox::SetItemHeight(FX_FLOAT fItemHeight) {
108   m_ListBoxDP.m_fItemHeight = fItemHeight;
109   return FWL_ERR_Succeeded;
110 }
GetFocusItem()111 FWL_HLISTITEM CFWL_ListBox::GetFocusItem() {
112   for (int32_t i = 0; i < m_ListBoxDP.m_arrItem.GetSize(); i++) {
113     CFWL_ListItem* hItem =
114         static_cast<CFWL_ListItem*>(m_ListBoxDP.m_arrItem[i]);
115     if (hItem->m_dwStates & FWL_ITEMSTATE_LTB_Focused) {
116       return (FWL_HLISTITEM)hItem;
117     }
118   }
119   return NULL;
120 }
SetFocusItem(FWL_HLISTITEM hItem)121 FWL_ERR CFWL_ListBox::SetFocusItem(FWL_HLISTITEM hItem) {
122   int32_t nIndex = m_ListBoxDP.GetItemIndex(GetWidget(), hItem);
123   static_cast<CFWL_ListItem*>(m_ListBoxDP.m_arrItem[nIndex])->m_dwStates |=
124       FWL_ITEMSTATE_LTB_Focused;
125   return FWL_ERR_Succeeded;
126 }
Sort(IFWL_ListBoxCompare * pCom)127 FWL_ERR* CFWL_ListBox::Sort(IFWL_ListBoxCompare* pCom) {
128   return static_cast<IFWL_ListBox*>(m_pIface)->Sort(pCom);
129 }
CountItems()130 int32_t CFWL_ListBox::CountItems() {
131   return m_ListBoxDP.m_arrItem.GetSize();
132 }
GetItem(int32_t nIndex)133 FWL_HLISTITEM CFWL_ListBox::GetItem(int32_t nIndex) {
134   int32_t nCount = m_ListBoxDP.m_arrItem.GetSize();
135   if (nIndex > nCount - 1 && nIndex < 0) {
136     return NULL;
137   }
138   return (FWL_HLISTITEM)m_ListBoxDP.m_arrItem[nIndex];
139 }
SetItemString(FWL_HLISTITEM hItem,const CFX_WideStringC & wsText)140 FWL_ERR CFWL_ListBox::SetItemString(FWL_HLISTITEM hItem,
141                                     const CFX_WideStringC& wsText) {
142   if (!hItem)
143     return FWL_ERR_Indefinite;
144   reinterpret_cast<CFWL_ListItem*>(hItem)->m_wsText = wsText;
145   return FWL_ERR_Succeeded;
146 }
GetItemString(FWL_HLISTITEM hItem,CFX_WideString & wsText)147 FWL_ERR CFWL_ListBox::GetItemString(FWL_HLISTITEM hItem,
148                                     CFX_WideString& wsText) {
149   if (!hItem)
150     return FWL_ERR_Indefinite;
151   wsText = reinterpret_cast<CFWL_ListItem*>(hItem)->m_wsText;
152   return FWL_ERR_Succeeded;
153 }
SetItemData(FWL_HLISTITEM hItem,void * pData)154 FWL_ERR CFWL_ListBox::SetItemData(FWL_HLISTITEM hItem, void* pData) {
155   if (!hItem)
156     return FWL_ERR_Indefinite;
157   reinterpret_cast<CFWL_ListItem*>(hItem)->m_pData = pData;
158   return FWL_ERR_Succeeded;
159 }
GetItemData(FWL_HLISTITEM hItem)160 void* CFWL_ListBox::GetItemData(FWL_HLISTITEM hItem) {
161   if (!hItem)
162     return NULL;
163   return reinterpret_cast<CFWL_ListItem*>(hItem)->m_pData;
164 }
GetItemAtPoint(FX_FLOAT fx,FX_FLOAT fy)165 FWL_HLISTITEM CFWL_ListBox::GetItemAtPoint(FX_FLOAT fx, FX_FLOAT fy) {
166   CFX_RectF rtClient;
167   m_pIface->GetClientRect(rtClient);
168   fx -= rtClient.left;
169   fy -= rtClient.top;
170   FX_FLOAT fPosX = 0;
171   FX_FLOAT fPosY = 0;
172   static_cast<IFWL_ListBox*>(m_pIface)->GetScrollPos(fx);
173   static_cast<IFWL_ListBox*>(m_pIface)->GetScrollPos(fy, FALSE);
174   int32_t nCount = m_ListBoxDP.CountItems(NULL);
175   for (int32_t i = 0; i < nCount; i++) {
176     FWL_HLISTITEM hItem = m_ListBoxDP.GetItem(NULL, i);
177     if (!hItem) {
178       continue;
179     }
180     CFX_RectF rtItem;
181     m_ListBoxDP.GetItemRect(NULL, hItem, rtItem);
182     rtItem.Offset(-fPosX, -fPosY);
183     if (rtItem.Contains(fx, fy)) {
184       return hItem;
185     }
186   }
187   return NULL;
188 }
GetItemStates(FWL_HLISTITEM hItem)189 FX_DWORD CFWL_ListBox::GetItemStates(FWL_HLISTITEM hItem) {
190   if (!hItem)
191     return 0;
192   CFWL_ListItem* pItem = reinterpret_cast<CFWL_ListItem*>(hItem);
193   return pItem->m_dwStates | pItem->m_dwCheckState;
194 }
CFWL_ListBox()195 CFWL_ListBox::CFWL_ListBox() {}
~CFWL_ListBox()196 CFWL_ListBox::~CFWL_ListBox() {}
CFWL_ListBoxDP()197 CFWL_ListBox::CFWL_ListBoxDP::CFWL_ListBoxDP() {}
~CFWL_ListBoxDP()198 CFWL_ListBox::CFWL_ListBoxDP::~CFWL_ListBoxDP() {
199   int32_t nCount = m_arrItem.GetSize();
200   for (int32_t i = 0; i < nCount; i++) {
201     delete static_cast<CFWL_ListItem*>(m_arrItem[i]);
202   }
203   m_arrItem.RemoveAll();
204 }
GetCaption(IFWL_Widget * pWidget,CFX_WideString & wsCaption)205 FWL_ERR CFWL_ListBox::CFWL_ListBoxDP::GetCaption(IFWL_Widget* pWidget,
206                                                  CFX_WideString& wsCaption) {
207   wsCaption = m_wsData;
208   return FWL_ERR_Succeeded;
209 }
CountItems(IFWL_Widget * pWidget)210 int32_t CFWL_ListBox::CFWL_ListBoxDP::CountItems(IFWL_Widget* pWidget) {
211   return m_arrItem.GetSize();
212 }
GetItem(IFWL_Widget * pWidget,int32_t nIndex)213 FWL_HLISTITEM CFWL_ListBox::CFWL_ListBoxDP::GetItem(IFWL_Widget* pWidget,
214                                                     int32_t nIndex) {
215   if (nIndex >= m_arrItem.GetSize() || nIndex < 0) {
216     return NULL;
217   } else {
218     return (FWL_HLISTITEM)m_arrItem[nIndex];
219   }
220 }
GetItemIndex(IFWL_Widget * pWidget,FWL_HLISTITEM hItem)221 int32_t CFWL_ListBox::CFWL_ListBoxDP::GetItemIndex(IFWL_Widget* pWidget,
222                                                    FWL_HLISTITEM hItem) {
223   return m_arrItem.Find(hItem);
224 }
SetItemIndex(IFWL_Widget * pWidget,FWL_HLISTITEM hItem,int32_t nIndex)225 FX_BOOL CFWL_ListBox::CFWL_ListBoxDP::SetItemIndex(IFWL_Widget* pWidget,
226                                                    FWL_HLISTITEM hItem,
227                                                    int32_t nIndex) {
228   return m_arrItem.SetAt(nIndex, hItem);
229 }
GetItemStyles(IFWL_Widget * pWidget,FWL_HLISTITEM hItem)230 FX_DWORD CFWL_ListBox::CFWL_ListBoxDP::GetItemStyles(IFWL_Widget* pWidget,
231                                                      FWL_HLISTITEM hItem) {
232   if (!hItem)
233     return -1;
234   return reinterpret_cast<CFWL_ListItem*>(hItem)->m_dwStates;
235 }
GetItemText(IFWL_Widget * pWidget,FWL_HLISTITEM hItem,CFX_WideString & wsText)236 FWL_ERR CFWL_ListBox::CFWL_ListBoxDP::GetItemText(IFWL_Widget* pWidget,
237                                                   FWL_HLISTITEM hItem,
238                                                   CFX_WideString& wsText) {
239   if (!hItem)
240     return FWL_ERR_Indefinite;
241   wsText = reinterpret_cast<CFWL_ListItem*>(hItem)->m_wsText;
242   return FWL_ERR_Succeeded;
243 }
GetItemRect(IFWL_Widget * pWidget,FWL_HLISTITEM hItem,CFX_RectF & rtItem)244 FWL_ERR CFWL_ListBox::CFWL_ListBoxDP::GetItemRect(IFWL_Widget* pWidget,
245                                                   FWL_HLISTITEM hItem,
246                                                   CFX_RectF& rtItem) {
247   if (!hItem)
248     return FWL_ERR_Indefinite;
249   CFWL_ListItem* pItem = reinterpret_cast<CFWL_ListItem*>(hItem);
250   rtItem = pItem->m_rtItem;
251   return FWL_ERR_Succeeded;
252 }
GetItemData(IFWL_Widget * pWidget,FWL_HLISTITEM hItem)253 void* CFWL_ListBox::CFWL_ListBoxDP::GetItemData(IFWL_Widget* pWidget,
254                                                 FWL_HLISTITEM hItem) {
255   if (!hItem)
256     return NULL;
257   CFWL_ListItem* pItem = reinterpret_cast<CFWL_ListItem*>(hItem);
258   return pItem->m_pData;
259 }
SetItemStyles(IFWL_Widget * pWidget,FWL_HLISTITEM hItem,FX_DWORD dwStyle)260 FWL_ERR CFWL_ListBox::CFWL_ListBoxDP::SetItemStyles(IFWL_Widget* pWidget,
261                                                     FWL_HLISTITEM hItem,
262                                                     FX_DWORD dwStyle) {
263   if (!hItem)
264     return FWL_ERR_Indefinite;
265   reinterpret_cast<CFWL_ListItem*>(hItem)->m_dwStates = dwStyle;
266   return FWL_ERR_Succeeded;
267 }
SetItemText(IFWL_Widget * pWidget,FWL_HLISTITEM hItem,const FX_WCHAR * pszText)268 FWL_ERR CFWL_ListBox::CFWL_ListBoxDP::SetItemText(IFWL_Widget* pWidget,
269                                                   FWL_HLISTITEM hItem,
270                                                   const FX_WCHAR* pszText) {
271   if (!hItem)
272     return FWL_ERR_Indefinite;
273   reinterpret_cast<CFWL_ListItem*>(hItem)->m_wsText = pszText;
274   return FWL_ERR_Succeeded;
275 }
SetItemRect(IFWL_Widget * pWidget,FWL_HLISTITEM hItem,const CFX_RectF & rtItem)276 FWL_ERR CFWL_ListBox::CFWL_ListBoxDP::SetItemRect(IFWL_Widget* pWidget,
277                                                   FWL_HLISTITEM hItem,
278                                                   const CFX_RectF& rtItem) {
279   if (!hItem)
280     return FWL_ERR_Indefinite;
281   reinterpret_cast<CFWL_ListItem*>(hItem)->m_rtItem = rtItem;
282   return FWL_ERR_Succeeded;
283 }
GetItemHeight(IFWL_Widget * pWidget)284 FX_FLOAT CFWL_ListBox::CFWL_ListBoxDP::GetItemHeight(IFWL_Widget* pWidget) {
285   return m_fItemHeight;
286 }
GetItemIcon(IFWL_Widget * pWidget,FWL_HLISTITEM hItem)287 CFX_DIBitmap* CFWL_ListBox::CFWL_ListBoxDP::GetItemIcon(IFWL_Widget* pWidget,
288                                                         FWL_HLISTITEM hItem) {
289   return reinterpret_cast<CFWL_ListItem*>(hItem)->m_pDIB;
290 }
GetItemCheckRect(IFWL_Widget * pWidget,FWL_HLISTITEM hItem,CFX_RectF & rtCheck)291 FWL_ERR CFWL_ListBox::CFWL_ListBoxDP::GetItemCheckRect(IFWL_Widget* pWidget,
292                                                        FWL_HLISTITEM hItem,
293                                                        CFX_RectF& rtCheck) {
294   rtCheck = reinterpret_cast<CFWL_ListItem*>(hItem)->m_rtCheckBox;
295   return FWL_ERR_Succeeded;
296 }
SetItemCheckRect(IFWL_Widget * pWidget,FWL_HLISTITEM hItem,const CFX_RectF & rtCheck)297 FWL_ERR CFWL_ListBox::CFWL_ListBoxDP::SetItemCheckRect(
298     IFWL_Widget* pWidget,
299     FWL_HLISTITEM hItem,
300     const CFX_RectF& rtCheck) {
301   reinterpret_cast<CFWL_ListItem*>(hItem)->m_rtCheckBox = rtCheck;
302   return FWL_ERR_Succeeded;
303 }
GetItemCheckState(IFWL_Widget * pWidget,FWL_HLISTITEM hItem)304 FX_DWORD CFWL_ListBox::CFWL_ListBoxDP::GetItemCheckState(IFWL_Widget* pWidget,
305                                                          FWL_HLISTITEM hItem) {
306   return reinterpret_cast<CFWL_ListItem*>(hItem)->m_dwCheckState;
307 }
SetItemCheckState(IFWL_Widget * pWidget,FWL_HLISTITEM hItem,FX_DWORD dwCheckState)308 FWL_ERR CFWL_ListBox::CFWL_ListBoxDP::SetItemCheckState(IFWL_Widget* pWidget,
309                                                         FWL_HLISTITEM hItem,
310                                                         FX_DWORD dwCheckState) {
311   reinterpret_cast<CFWL_ListItem*>(hItem)->m_dwCheckState = dwCheckState;
312   return FWL_ERR_Succeeded;
313 }
314