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 "xfa/src/foxitlib.h"
8 #include "xfa/src/fwl/src/core/include/fwl_targetimp.h"
9 #include "xfa/src/fwl/src/core/include/fwl_noteimp.h"
10 #include "xfa/src/fwl/src/core/include/fwl_widgetimp.h"
11 #include "xfa/src/fwl/src/basewidget/include/fwl_scrollbarimp.h"
12 #include "xfa/src/fwl/src/basewidget/include/fwl_listboximp.h"
13 #include "xfa/src/fwl/src/basewidget/include/fwl_comboboximp.h"
14
15 #define FWL_LISTBOX_ItemTextMargin 2
16
17 // static
Create(const CFWL_WidgetImpProperties & properties,IFWL_Widget * pOuter)18 IFWL_ListBox* IFWL_ListBox::Create(const CFWL_WidgetImpProperties& properties,
19 IFWL_Widget* pOuter) {
20 IFWL_ListBox* pListBox = new IFWL_ListBox;
21 CFWL_ListBoxImp* pListBoxImpl = new CFWL_ListBoxImp(properties, pOuter);
22 pListBox->SetImpl(pListBoxImpl);
23 pListBoxImpl->SetInterface(pListBox);
24 return pListBox;
25 }
26 // static
CreateComboList(const CFWL_WidgetImpProperties & properties,IFWL_Widget * pOuter)27 IFWL_ListBox* IFWL_ListBox::CreateComboList(
28 const CFWL_WidgetImpProperties& properties,
29 IFWL_Widget* pOuter) {
30 IFWL_ListBox* pListBox = new IFWL_ListBox;
31 CFWL_ListBoxImp* pComboListImpl = new CFWL_ComboListImp(properties, pOuter);
32 pListBox->SetImpl(pComboListImpl);
33 pComboListImpl->SetInterface(pListBox);
34 return pListBox;
35 }
IFWL_ListBox()36 IFWL_ListBox::IFWL_ListBox() {}
CountSelItems()37 int32_t IFWL_ListBox::CountSelItems() {
38 return static_cast<CFWL_ListBoxImp*>(GetImpl())->CountSelItems();
39 }
GetSelItem(int32_t nIndexSel)40 FWL_HLISTITEM IFWL_ListBox::GetSelItem(int32_t nIndexSel) {
41 return static_cast<CFWL_ListBoxImp*>(GetImpl())->GetSelItem(nIndexSel);
42 }
GetSelIndex(int32_t nIndex)43 int32_t IFWL_ListBox::GetSelIndex(int32_t nIndex) {
44 return static_cast<CFWL_ListBoxImp*>(GetImpl())->GetSelIndex(nIndex);
45 }
SetSelItem(FWL_HLISTITEM hItem,FX_BOOL bSelect)46 FWL_ERR IFWL_ListBox::SetSelItem(FWL_HLISTITEM hItem, FX_BOOL bSelect) {
47 return static_cast<CFWL_ListBoxImp*>(GetImpl())->SetSelItem(hItem, bSelect);
48 }
GetItemText(FWL_HLISTITEM hItem,CFX_WideString & wsText)49 FWL_ERR IFWL_ListBox::GetItemText(FWL_HLISTITEM hItem, CFX_WideString& wsText) {
50 return static_cast<CFWL_ListBoxImp*>(GetImpl())->GetItemText(hItem, wsText);
51 }
GetScrollPos(FX_FLOAT & fPos,FX_BOOL bVert)52 FWL_ERR IFWL_ListBox::GetScrollPos(FX_FLOAT& fPos, FX_BOOL bVert) {
53 return static_cast<CFWL_ListBoxImp*>(GetImpl())->GetScrollPos(fPos, bVert);
54 }
Sort(IFWL_ListBoxCompare * pCom)55 FWL_ERR* IFWL_ListBox::Sort(IFWL_ListBoxCompare* pCom) {
56 return static_cast<CFWL_ListBoxImp*>(GetImpl())->Sort(pCom);
57 }
58
CFWL_ListBoxImp(const CFWL_WidgetImpProperties & properties,IFWL_Widget * pOuter)59 CFWL_ListBoxImp::CFWL_ListBoxImp(const CFWL_WidgetImpProperties& properties,
60 IFWL_Widget* pOuter)
61 : CFWL_WidgetImp(properties, pOuter),
62 m_dwTTOStyles(0),
63 m_iTTOAligns(0),
64 m_hAnchor(NULL),
65 m_fScorllBarWidth(0),
66 m_bLButtonDown(FALSE),
67 m_pScrollBarTP(NULL) {
68 m_rtClient.Reset();
69 m_rtConent.Reset();
70 m_rtStatic.Reset();
71 }
~CFWL_ListBoxImp()72 CFWL_ListBoxImp::~CFWL_ListBoxImp() {
73 }
GetClassName(CFX_WideString & wsClass) const74 FWL_ERR CFWL_ListBoxImp::GetClassName(CFX_WideString& wsClass) const {
75 wsClass = FWL_CLASS_ListBox;
76 return FWL_ERR_Succeeded;
77 }
GetClassID() const78 FX_DWORD CFWL_ListBoxImp::GetClassID() const {
79 return FWL_CLASSHASH_ListBox;
80 }
Initialize()81 FWL_ERR CFWL_ListBoxImp::Initialize() {
82 if (CFWL_WidgetImp::Initialize() != FWL_ERR_Succeeded)
83 return FWL_ERR_Indefinite;
84 m_pDelegate = new CFWL_ListBoxImpDelegate(this);
85 return FWL_ERR_Succeeded;
86 }
Finalize()87 FWL_ERR CFWL_ListBoxImp::Finalize() {
88 if (m_pVertScrollBar) {
89 m_pVertScrollBar->Finalize();
90 }
91 if (m_pHorzScrollBar) {
92 m_pHorzScrollBar->Finalize();
93 }
94 delete m_pDelegate;
95 m_pDelegate = nullptr;
96 return CFWL_WidgetImp::Finalize();
97 }
GetWidgetRect(CFX_RectF & rect,FX_BOOL bAutoSize)98 FWL_ERR CFWL_ListBoxImp::GetWidgetRect(CFX_RectF& rect, FX_BOOL bAutoSize) {
99 if (bAutoSize) {
100 rect.Set(0, 0, 0, 0);
101 if (!m_pProperties->m_pThemeProvider) {
102 m_pProperties->m_pThemeProvider = GetAvailableTheme();
103 }
104 CFX_SizeF fs = CalcSize(TRUE);
105 rect.Set(0, 0, fs.x, fs.y);
106 CFWL_WidgetImp::GetWidgetRect(rect, TRUE);
107 } else {
108 rect = m_pProperties->m_rtWidget;
109 }
110 return FWL_ERR_Succeeded;
111 }
Update()112 FWL_ERR CFWL_ListBoxImp::Update() {
113 if (IsLocked()) {
114 return FWL_ERR_Indefinite;
115 }
116 if (!m_pProperties->m_pThemeProvider) {
117 m_pProperties->m_pThemeProvider = GetAvailableTheme();
118 }
119 m_iTTOAligns = FDE_TTOALIGNMENT_Center;
120 switch (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_LTB_AlignMask) {
121 case FWL_STYLEEXT_LTB_LeftAlign: {
122 m_iTTOAligns = FDE_TTOALIGNMENT_CenterLeft;
123 break;
124 }
125 case FWL_STYLEEXT_LTB_RightAlign: {
126 m_iTTOAligns = FDE_TTOALIGNMENT_CenterRight;
127 break;
128 }
129 case FWL_STYLEEXT_LTB_CenterAlign:
130 default: { m_iTTOAligns = FDE_TTOALIGNMENT_Center; }
131 }
132 if (m_pProperties->m_dwStyleExes & FWL_WGTSTYLE_RTLReading) {
133 m_dwTTOStyles |= FDE_TTOSTYLE_RTL;
134 }
135 m_dwTTOStyles |= FDE_TTOSTYLE_SingleLine;
136 m_fScorllBarWidth = GetScrollWidth();
137 SortItem();
138 CalcSize();
139 return FWL_ERR_Succeeded;
140 }
HitTest(FX_FLOAT fx,FX_FLOAT fy)141 FX_DWORD CFWL_ListBoxImp::HitTest(FX_FLOAT fx, FX_FLOAT fy) {
142 if (IsShowScrollBar(FALSE)) {
143 CFX_RectF rect;
144 m_pHorzScrollBar->GetWidgetRect(rect);
145 if (rect.Contains(fx, fy)) {
146 return FWL_WGTHITTEST_HScrollBar;
147 }
148 }
149 if (IsShowScrollBar(TRUE)) {
150 CFX_RectF rect;
151 m_pVertScrollBar->GetWidgetRect(rect);
152 if (rect.Contains(fx, fy)) {
153 return FWL_WGTHITTEST_VScrollBar;
154 }
155 }
156 if (m_rtClient.Contains(fx, fy)) {
157 return FWL_WGTHITTEST_Client;
158 }
159 return FWL_WGTHITTEST_Unknown;
160 }
DrawWidget(CFX_Graphics * pGraphics,const CFX_Matrix * pMatrix)161 FWL_ERR CFWL_ListBoxImp::DrawWidget(CFX_Graphics* pGraphics,
162 const CFX_Matrix* pMatrix) {
163 if (!pGraphics)
164 return FWL_ERR_Indefinite;
165 if (!m_pProperties->m_pThemeProvider)
166 return FWL_ERR_Indefinite;
167 IFWL_ThemeProvider* pTheme = m_pProperties->m_pThemeProvider;
168 pGraphics->SaveGraphState();
169 if (HasBorder()) {
170 DrawBorder(pGraphics, FWL_PART_LTB_Border, pTheme, pMatrix);
171 }
172 if (HasEdge()) {
173 DrawEdge(pGraphics, FWL_PART_LTB_Edge, pTheme, pMatrix);
174 }
175 CFX_RectF rtClip(m_rtConent);
176 if (IsShowScrollBar(FALSE)) {
177 rtClip.height -= m_fScorllBarWidth;
178 }
179 if (IsShowScrollBar(TRUE)) {
180 rtClip.width -= m_fScorllBarWidth;
181 }
182 if (pMatrix) {
183 pMatrix->TransformRect(rtClip);
184 }
185 pGraphics->SetClipRect(rtClip);
186 if ((m_pProperties->m_dwStyles & FWL_WGTSTYLE_NoBackground) == 0) {
187 DrawBkground(pGraphics, pTheme, pMatrix);
188 }
189 DrawItems(pGraphics, pTheme, pMatrix);
190 pGraphics->RestoreGraphState();
191 return FWL_ERR_Succeeded;
192 }
SetThemeProvider(IFWL_ThemeProvider * pThemeProvider)193 FWL_ERR CFWL_ListBoxImp::SetThemeProvider(IFWL_ThemeProvider* pThemeProvider) {
194 if (!pThemeProvider)
195 return FWL_ERR_Indefinite;
196 if (!pThemeProvider->IsValidWidget(m_pInterface)) {
197 m_pScrollBarTP = pThemeProvider;
198 return FWL_ERR_Succeeded;
199 }
200 m_pProperties->m_pThemeProvider = pThemeProvider;
201 return FWL_ERR_Succeeded;
202 }
CountSelItems()203 int32_t CFWL_ListBoxImp::CountSelItems() {
204 if (!m_pProperties->m_pDataProvider)
205 return 0;
206 int32_t iRet = 0;
207 IFWL_ListBoxDP* pData =
208 static_cast<IFWL_ListBoxDP*>(m_pProperties->m_pDataProvider);
209 int32_t iCount = pData->CountItems(m_pInterface);
210 for (int32_t i = 0; i < iCount; i++) {
211 FWL_HLISTITEM hItem = pData->GetItem(m_pInterface, i);
212 if (!hItem) {
213 continue;
214 }
215 FX_DWORD dwStyle = pData->GetItemStyles(m_pInterface, hItem);
216 if (dwStyle & FWL_ITEMSTATE_LTB_Selected) {
217 iRet++;
218 }
219 }
220 return iRet;
221 }
GetSelItem(int32_t nIndexSel)222 FWL_HLISTITEM CFWL_ListBoxImp::GetSelItem(int32_t nIndexSel) {
223 if (!m_pProperties->m_pDataProvider)
224 return NULL;
225 int32_t index = 0;
226 IFWL_ListBoxDP* pData =
227 static_cast<IFWL_ListBoxDP*>(m_pProperties->m_pDataProvider);
228 int32_t iCount = pData->CountItems(m_pInterface);
229 for (int32_t i = 0; i < iCount; i++) {
230 FWL_HLISTITEM hItem = pData->GetItem(m_pInterface, i);
231 if (!hItem) {
232 return NULL;
233 }
234 FX_DWORD dwStyle = pData->GetItemStyles(m_pInterface, hItem);
235 if (dwStyle & FWL_ITEMSTATE_LTB_Selected) {
236 if (index == nIndexSel) {
237 return hItem;
238 } else {
239 index++;
240 }
241 }
242 }
243 return NULL;
244 }
GetSelIndex(int32_t nIndex)245 int32_t CFWL_ListBoxImp::GetSelIndex(int32_t nIndex) {
246 if (!m_pProperties->m_pDataProvider)
247 return -1;
248 int32_t index = 0;
249 IFWL_ListBoxDP* pData =
250 static_cast<IFWL_ListBoxDP*>(m_pProperties->m_pDataProvider);
251 int32_t iCount = pData->CountItems(m_pInterface);
252 for (int32_t i = 0; i < iCount; i++) {
253 FWL_HLISTITEM hItem = pData->GetItem(m_pInterface, i);
254 if (!hItem) {
255 return -1;
256 }
257 FX_DWORD dwStyle = pData->GetItemStyles(m_pInterface, hItem);
258 if (dwStyle & FWL_ITEMSTATE_LTB_Selected) {
259 if (index == nIndex) {
260 return i;
261 } else {
262 index++;
263 }
264 }
265 }
266 return -1;
267 }
SetSelItem(FWL_HLISTITEM hItem,FX_BOOL bSelect)268 FWL_ERR CFWL_ListBoxImp::SetSelItem(FWL_HLISTITEM hItem, FX_BOOL bSelect) {
269 if (!m_pProperties->m_pDataProvider)
270 return FWL_ERR_Indefinite;
271 if (!hItem) {
272 if (bSelect) {
273 SelectAll();
274 } else {
275 ClearSelection();
276 SetFocusItem(NULL);
277 }
278 return FWL_ERR_Indefinite;
279 }
280 if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_LTB_MultiSelection) {
281 SetSelectionDirect(hItem, bSelect);
282 } else {
283 SetSelection(hItem, hItem, bSelect);
284 }
285 return FWL_ERR_Succeeded;
286 }
GetItemText(FWL_HLISTITEM hItem,CFX_WideString & wsText)287 FWL_ERR CFWL_ListBoxImp::GetItemText(FWL_HLISTITEM hItem,
288 CFX_WideString& wsText) {
289 if (!m_pProperties->m_pDataProvider)
290 return FWL_ERR_Indefinite;
291 IFWL_ListBoxDP* pData =
292 static_cast<IFWL_ListBoxDP*>(m_pProperties->m_pDataProvider);
293 if (!hItem)
294 return FWL_ERR_Indefinite;
295 pData->GetItemText(m_pInterface, hItem, wsText);
296 return FWL_ERR_Succeeded;
297 }
GetScrollPos(FX_FLOAT & fPos,FX_BOOL bVert)298 FWL_ERR CFWL_ListBoxImp::GetScrollPos(FX_FLOAT& fPos, FX_BOOL bVert) {
299 if ((bVert && IsShowScrollBar(TRUE)) || (!bVert && IsShowScrollBar(FALSE))) {
300 IFWL_ScrollBar* pScrollBar =
301 bVert ? m_pVertScrollBar.get() : m_pHorzScrollBar.get();
302 fPos = pScrollBar->GetPos();
303 return FWL_ERR_Succeeded;
304 }
305 return FWL_ERR_Indefinite;
306 }
Sort(IFWL_ListBoxCompare * pCom)307 FWL_ERR* CFWL_ListBoxImp::Sort(IFWL_ListBoxCompare* pCom) {
308 FWL_HLISTITEM hTemp;
309 IFWL_ListBoxDP* pData =
310 static_cast<IFWL_ListBoxDP*>(m_pProperties->m_pDataProvider);
311 int32_t sz = pData->CountItems(m_pInterface);
312 for (int32_t i = 0; i < sz - 1; i++) {
313 for (int32_t j = i + 1; j < sz; j++) {
314 if (pCom->Compare(pData->GetItem(m_pInterface, i),
315 pData->GetItem(m_pInterface, j)) > 0) {
316 hTemp = pData->GetItem(m_pInterface, i);
317 pData->SetItemIndex(m_pInterface, pData->GetItem(m_pInterface, j), i);
318 pData->SetItemIndex(m_pInterface, hTemp, j);
319 }
320 }
321 }
322 return FWL_ERR_Succeeded;
323 }
GetItem(FWL_HLISTITEM hItem,FX_DWORD dwKeyCode)324 FWL_HLISTITEM CFWL_ListBoxImp::GetItem(FWL_HLISTITEM hItem,
325 FX_DWORD dwKeyCode) {
326 FWL_HLISTITEM hRet = NULL;
327 switch (dwKeyCode) {
328 case FWL_VKEY_Up:
329 case FWL_VKEY_Down:
330 case FWL_VKEY_Home:
331 case FWL_VKEY_End: {
332 FX_BOOL bUp = dwKeyCode == FWL_VKEY_Up;
333 FX_BOOL bDown = dwKeyCode == FWL_VKEY_Down;
334 FX_BOOL bHome = dwKeyCode == FWL_VKEY_Home;
335 IFWL_ListBoxDP* pData =
336 static_cast<IFWL_ListBoxDP*>(m_pProperties->m_pDataProvider);
337 int32_t iDstItem = -1;
338 if (bUp || bDown) {
339 int32_t index = pData->GetItemIndex(m_pInterface, hItem);
340 iDstItem = dwKeyCode == FWL_VKEY_Up ? index - 1 : index + 1;
341 } else if (bHome) {
342 iDstItem = 0;
343 } else {
344 int32_t iCount = pData->CountItems(m_pInterface);
345 iDstItem = iCount - 1;
346 }
347 hRet = pData->GetItem(m_pInterface, iDstItem);
348 break;
349 }
350 default: {}
351 }
352 return hRet;
353 }
SetSelection(FWL_HLISTITEM hStart,FWL_HLISTITEM hEnd,FX_BOOL bSelected)354 void CFWL_ListBoxImp::SetSelection(FWL_HLISTITEM hStart,
355 FWL_HLISTITEM hEnd,
356 FX_BOOL bSelected) {
357 IFWL_ListBoxDP* pData =
358 static_cast<IFWL_ListBoxDP*>(m_pProperties->m_pDataProvider);
359 int32_t iStart = pData->GetItemIndex(m_pInterface, hStart);
360 int32_t iEnd = pData->GetItemIndex(m_pInterface, hEnd);
361 if (iStart > iEnd) {
362 int32_t iTemp = iStart;
363 iStart = iEnd;
364 iEnd = iTemp;
365 }
366 if (bSelected) {
367 int32_t iCount = pData->CountItems(m_pInterface);
368 for (int32_t i = 0; i < iCount; i++) {
369 FWL_HLISTITEM hItem = pData->GetItem(m_pInterface, i);
370 SetSelectionDirect(hItem, FALSE);
371 }
372 }
373 for (; iStart <= iEnd; iStart++) {
374 FWL_HLISTITEM hItem = pData->GetItem(m_pInterface, iStart);
375 SetSelectionDirect(hItem, bSelected);
376 }
377 }
SetSelectionDirect(FWL_HLISTITEM hItem,FX_BOOL bSelect)378 void CFWL_ListBoxImp::SetSelectionDirect(FWL_HLISTITEM hItem, FX_BOOL bSelect) {
379 IFWL_ListBoxDP* pData =
380 static_cast<IFWL_ListBoxDP*>(m_pProperties->m_pDataProvider);
381 FX_DWORD dwOldStyle = pData->GetItemStyles(m_pInterface, hItem);
382 bSelect ? dwOldStyle |= FWL_ITEMSTATE_LTB_Selected
383 : dwOldStyle &= ~FWL_ITEMSTATE_LTB_Selected;
384 pData->SetItemStyles(m_pInterface, hItem, dwOldStyle);
385 }
IsItemSelected(FWL_HLISTITEM hItem)386 FX_BOOL CFWL_ListBoxImp::IsItemSelected(FWL_HLISTITEM hItem) {
387 IFWL_ListBoxDP* pData =
388 static_cast<IFWL_ListBoxDP*>(m_pProperties->m_pDataProvider);
389 FX_DWORD dwState = pData->GetItemStyles(m_pInterface, hItem);
390 return (dwState & FWL_ITEMSTATE_LTB_Selected) != 0;
391 }
ClearSelection()392 void CFWL_ListBoxImp::ClearSelection() {
393 FX_BOOL bMulti =
394 m_pProperties->m_dwStyleExes & FWL_STYLEEXT_LTB_MultiSelection;
395 IFWL_ListBoxDP* pData =
396 static_cast<IFWL_ListBoxDP*>(m_pProperties->m_pDataProvider);
397 int32_t iCount = pData->CountItems(m_pInterface);
398 for (int32_t i = 0; i < iCount; i++) {
399 FWL_HLISTITEM hItem = pData->GetItem(m_pInterface, i);
400 FX_DWORD dwState = pData->GetItemStyles(m_pInterface, hItem);
401 FX_BOOL bFindSel = dwState & FWL_ITEMSTATE_LTB_Selected;
402 if (!bFindSel) {
403 continue;
404 }
405 SetSelectionDirect(hItem, FALSE);
406 if (!bMulti) {
407 return;
408 }
409 }
410 }
SelectAll()411 void CFWL_ListBoxImp::SelectAll() {
412 FX_BOOL bMulti =
413 m_pProperties->m_dwStyleExes & FWL_STYLEEXT_LTB_MultiSelection;
414 if (!bMulti) {
415 return;
416 }
417 IFWL_ListBoxDP* pData =
418 static_cast<IFWL_ListBoxDP*>(m_pProperties->m_pDataProvider);
419 int32_t iCount = pData->CountItems(m_pInterface);
420 if (iCount > 0) {
421 FWL_HLISTITEM hItemStart = pData->GetItem(m_pInterface, 0);
422 FWL_HLISTITEM hItemEnd = pData->GetItem(m_pInterface, iCount - 1);
423 SetSelection(hItemStart, hItemEnd, FALSE);
424 }
425 }
GetFocusedItem()426 FWL_HLISTITEM CFWL_ListBoxImp::GetFocusedItem() {
427 IFWL_ListBoxDP* pData =
428 static_cast<IFWL_ListBoxDP*>(m_pProperties->m_pDataProvider);
429 int32_t iCount = pData->CountItems(m_pInterface);
430 for (int32_t i = 0; i < iCount; i++) {
431 FWL_HLISTITEM hItem = pData->GetItem(m_pInterface, i);
432 if (!hItem)
433 return NULL;
434 if (pData->GetItemStyles(m_pInterface, hItem) & FWL_ITEMSTATE_LTB_Focused) {
435 return hItem;
436 }
437 }
438 return NULL;
439 }
SetFocusItem(FWL_HLISTITEM hItem)440 void CFWL_ListBoxImp::SetFocusItem(FWL_HLISTITEM hItem) {
441 IFWL_ListBoxDP* pData =
442 static_cast<IFWL_ListBoxDP*>(m_pProperties->m_pDataProvider);
443 FWL_HLISTITEM hFocus = GetFocusedItem();
444 if (hItem != hFocus) {
445 if (hFocus) {
446 FX_DWORD dwStyle = pData->GetItemStyles(m_pInterface, hFocus);
447 dwStyle &= ~FWL_ITEMSTATE_LTB_Focused;
448 pData->SetItemStyles(m_pInterface, hFocus, dwStyle);
449 }
450 if (hItem) {
451 FX_DWORD dwStyle = pData->GetItemStyles(m_pInterface, hItem);
452 dwStyle |= FWL_ITEMSTATE_LTB_Focused;
453 pData->SetItemStyles(m_pInterface, hItem, dwStyle);
454 }
455 }
456 }
GetItemAtPoint(FX_FLOAT fx,FX_FLOAT fy)457 FWL_HLISTITEM CFWL_ListBoxImp::GetItemAtPoint(FX_FLOAT fx, FX_FLOAT fy) {
458 fx -= m_rtConent.left, fy -= m_rtConent.top;
459 FX_FLOAT fPosX = 0.0f;
460 if (m_pHorzScrollBar) {
461 fPosX = m_pHorzScrollBar->GetPos();
462 }
463 FX_FLOAT fPosY = 0.0;
464 if (m_pVertScrollBar) {
465 fPosY = m_pVertScrollBar->GetPos();
466 }
467 IFWL_ListBoxDP* pData =
468 static_cast<IFWL_ListBoxDP*>(m_pProperties->m_pDataProvider);
469 int32_t nCount = pData->CountItems(m_pInterface);
470 for (int32_t i = 0; i < nCount; i++) {
471 FWL_HLISTITEM hItem = pData->GetItem(m_pInterface, i);
472 if (!hItem) {
473 continue;
474 }
475 CFX_RectF rtItem;
476 pData->GetItemRect(m_pInterface, hItem, rtItem);
477 rtItem.Offset(-fPosX, -fPosY);
478 if (rtItem.Contains(fx, fy)) {
479 return hItem;
480 }
481 }
482 return NULL;
483 }
GetItemCheckRect(FWL_HLISTITEM hItem,CFX_RectF & rtCheck)484 FX_BOOL CFWL_ListBoxImp::GetItemCheckRect(FWL_HLISTITEM hItem,
485 CFX_RectF& rtCheck) {
486 if (!m_pProperties->m_pDataProvider)
487 return FALSE;
488 if (!(m_pProperties->m_dwStyleExes & FWL_STYLEEXT_LTB_Check)) {
489 return FALSE;
490 }
491 IFWL_ListBoxDP* pData =
492 static_cast<IFWL_ListBoxDP*>(m_pProperties->m_pDataProvider);
493 pData->GetItemCheckRect(m_pInterface, hItem, rtCheck);
494 return TRUE;
495 }
GetItemChecked(FWL_HLISTITEM hItem)496 FX_BOOL CFWL_ListBoxImp::GetItemChecked(FWL_HLISTITEM hItem) {
497 if (!m_pProperties->m_pDataProvider)
498 return FALSE;
499 if (!(m_pProperties->m_dwStyleExes & FWL_STYLEEXT_LTB_Check)) {
500 return FALSE;
501 }
502 IFWL_ListBoxDP* pData =
503 static_cast<IFWL_ListBoxDP*>(m_pProperties->m_pDataProvider);
504 return (pData->GetItemCheckState(m_pInterface, hItem) &
505 FWL_ITEMSTATE_LTB_Checked);
506 }
SetItemChecked(FWL_HLISTITEM hItem,FX_BOOL bChecked)507 FX_BOOL CFWL_ListBoxImp::SetItemChecked(FWL_HLISTITEM hItem, FX_BOOL bChecked) {
508 if (!m_pProperties->m_pDataProvider)
509 return FALSE;
510 if (!(m_pProperties->m_dwStyleExes & FWL_STYLEEXT_LTB_Check)) {
511 return FALSE;
512 }
513 IFWL_ListBoxDP* pData =
514 static_cast<IFWL_ListBoxDP*>(m_pProperties->m_pDataProvider);
515 pData->SetItemCheckState(m_pInterface, hItem,
516 bChecked ? FWL_ITEMSTATE_LTB_Checked : 0);
517 return TRUE;
518 }
ScrollToVisible(FWL_HLISTITEM hItem)519 FX_BOOL CFWL_ListBoxImp::ScrollToVisible(FWL_HLISTITEM hItem) {
520 if (!m_pVertScrollBar)
521 return FALSE;
522 CFX_RectF rtItem;
523 IFWL_ListBoxDP* pData =
524 static_cast<IFWL_ListBoxDP*>(m_pProperties->m_pDataProvider);
525 pData->GetItemRect(m_pInterface, hItem, rtItem);
526 FX_BOOL bScroll = FALSE;
527 FX_FLOAT fPosY = m_pVertScrollBar->GetPos();
528 rtItem.Offset(0, -fPosY + m_rtConent.top);
529 if (rtItem.top < m_rtConent.top) {
530 fPosY += rtItem.top - m_rtConent.top;
531 bScroll = TRUE;
532 } else if (rtItem.bottom() > m_rtConent.bottom()) {
533 fPosY += rtItem.bottom() - m_rtConent.bottom();
534 bScroll = TRUE;
535 }
536 if (!bScroll) {
537 return FALSE;
538 }
539 m_pVertScrollBar->SetPos(fPosY);
540 m_pVertScrollBar->SetTrackPos(fPosY);
541 Repaint(&m_rtClient);
542 return TRUE;
543 }
DrawBkground(CFX_Graphics * pGraphics,IFWL_ThemeProvider * pTheme,const CFX_Matrix * pMatrix)544 void CFWL_ListBoxImp::DrawBkground(CFX_Graphics* pGraphics,
545 IFWL_ThemeProvider* pTheme,
546 const CFX_Matrix* pMatrix) {
547 if (!pGraphics)
548 return;
549 if (!pTheme)
550 return;
551 CFWL_ThemeBackground param;
552 param.m_pWidget = m_pInterface;
553 param.m_iPart = FWL_PART_LTB_Background;
554 param.m_dwStates = 0;
555 param.m_pGraphics = pGraphics;
556 param.m_matrix.Concat(*pMatrix);
557 param.m_rtPart = m_rtClient;
558 if (IsShowScrollBar(FALSE) && IsShowScrollBar(TRUE)) {
559 param.m_pData = &m_rtStatic;
560 }
561 if (!IsEnabled()) {
562 param.m_dwStates = FWL_PARTSTATE_LTB_Disabled;
563 }
564 pTheme->DrawBackground(¶m);
565 }
DrawItems(CFX_Graphics * pGraphics,IFWL_ThemeProvider * pTheme,const CFX_Matrix * pMatrix)566 void CFWL_ListBoxImp::DrawItems(CFX_Graphics* pGraphics,
567 IFWL_ThemeProvider* pTheme,
568 const CFX_Matrix* pMatrix) {
569 FX_FLOAT fPosX = 0.0f;
570 if (m_pHorzScrollBar) {
571 fPosX = m_pHorzScrollBar->GetPos();
572 }
573 FX_FLOAT fPosY = 0.0f;
574 if (m_pVertScrollBar) {
575 fPosY = m_pVertScrollBar->GetPos();
576 }
577 CFX_RectF rtView(m_rtConent);
578 if (m_pHorzScrollBar) {
579 rtView.height -= m_fScorllBarWidth;
580 }
581 if (m_pVertScrollBar) {
582 rtView.width -= m_fScorllBarWidth;
583 }
584 FX_BOOL bMultiCol =
585 m_pProperties->m_dwStyleExes & FWL_STYLEEXT_LTB_MultiColumn;
586 IFWL_ListBoxDP* pData =
587 static_cast<IFWL_ListBoxDP*>(m_pProperties->m_pDataProvider);
588 int32_t iCount = pData->CountItems(m_pInterface);
589 for (int32_t i = 0; i < iCount; i++) {
590 FWL_HLISTITEM hItem = pData->GetItem(m_pInterface, i);
591 if (!hItem) {
592 continue;
593 }
594 CFX_RectF rtItem;
595 pData->GetItemRect(m_pInterface, hItem, rtItem);
596 rtItem.Offset(m_rtConent.left - fPosX, m_rtConent.top - fPosY);
597 if (rtItem.bottom() < m_rtConent.top) {
598 continue;
599 }
600 if (rtItem.top >= m_rtConent.bottom()) {
601 break;
602 }
603 if (bMultiCol && rtItem.left > m_rtConent.right()) {
604 break;
605 }
606 if (GetStylesEx() & FWL_STYLEEXT_LTB_OwnerDraw) {
607 CFWL_EvtLtbDrawItem ev;
608 ev.m_pSrcTarget = m_pInterface;
609 ev.m_pGraphics = pGraphics;
610 ev.m_matrix = *pMatrix;
611 ev.m_index = i;
612 ev.m_rect = rtItem;
613 DispatchEvent(&ev);
614 } else {
615 DrawItem(pGraphics, pTheme, hItem, i, rtItem, pMatrix);
616 }
617 }
618 }
DrawItem(CFX_Graphics * pGraphics,IFWL_ThemeProvider * pTheme,FWL_HLISTITEM hItem,int32_t Index,const CFX_RectF & rtItem,const CFX_Matrix * pMatrix)619 void CFWL_ListBoxImp::DrawItem(CFX_Graphics* pGraphics,
620 IFWL_ThemeProvider* pTheme,
621 FWL_HLISTITEM hItem,
622 int32_t Index,
623 const CFX_RectF& rtItem,
624 const CFX_Matrix* pMatrix) {
625 IFWL_ListBoxDP* pData =
626 static_cast<IFWL_ListBoxDP*>(m_pProperties->m_pDataProvider);
627 FX_DWORD dwItemStyles = pData->GetItemStyles(m_pInterface, hItem);
628 FX_DWORD dwPartStates = FWL_PARTSTATE_LTB_Normal;
629 if (m_pProperties->m_dwStates & FWL_WGTSTATE_Disabled) {
630 dwPartStates = FWL_PARTSTATE_LTB_Disabled;
631 } else if (dwItemStyles & FWL_ITEMSTATE_LTB_Selected) {
632 dwPartStates = FWL_PARTSTATE_LTB_Selected;
633 }
634 if (m_pProperties->m_dwStates & FWL_WGTSTATE_Focused &&
635 dwItemStyles & FWL_ITEMSTATE_LTB_Focused) {
636 dwPartStates |= FWL_PARTSTATE_LTB_Focused;
637 }
638 FWL_ListBoxItemData itemData;
639 itemData.pDataProvider = pData;
640 itemData.iIndex = Index;
641 {
642 CFWL_ThemeBackground param;
643 param.m_pWidget = m_pInterface;
644 param.m_iPart = FWL_PART_LTB_ListItem;
645 param.m_dwStates = dwPartStates;
646 param.m_pGraphics = pGraphics;
647 param.m_matrix.Concat(*pMatrix);
648 param.m_rtPart = rtItem;
649 param.m_dwData = (FX_DWORD)(uintptr_t)(&itemData);
650 CFX_RectF rtFocus(rtItem);
651 param.m_pData = &rtFocus;
652 if (m_pVertScrollBar && !m_pHorzScrollBar &&
653 (dwPartStates & FWL_PARTSTATE_LTB_Focused)) {
654 param.m_rtPart.left += 1;
655 param.m_rtPart.width -= (m_fScorllBarWidth + 1);
656 rtFocus.Deflate(0.5, 0.5, 1 + m_fScorllBarWidth, 1);
657 }
658 pTheme->DrawBackground(¶m);
659 }
660 {
661 FX_BOOL bHasIcon = GetStylesEx() & FWL_STYLEEXT_LTB_Icon;
662 if (bHasIcon) {
663 CFX_RectF rtDIB;
664 CFX_DIBitmap* pDib = pData->GetItemIcon(m_pInterface, hItem);
665 rtDIB.Set(rtItem.left, rtItem.top, rtItem.height, rtItem.height);
666 if (pDib) {
667 CFWL_ThemeBackground param;
668 param.m_pWidget = m_pInterface;
669 param.m_iPart = FWL_PART_LTB_Icon;
670 param.m_pGraphics = pGraphics;
671 param.m_matrix.Concat(*pMatrix);
672 param.m_rtPart = rtDIB;
673 param.m_dwData = (FX_DWORD)(uintptr_t)(&itemData);
674 param.m_pImage = pDib;
675 pTheme->DrawBackground(¶m);
676 }
677 }
678 FX_BOOL bHasCheck = GetStylesEx() & FWL_STYLEEXT_LTB_Check;
679 if (bHasCheck) {
680 CFX_RectF rtCheck;
681 rtCheck.Set(rtItem.left, rtItem.top, rtItem.height, rtItem.height);
682 rtCheck.Deflate(2, 2, 2, 2);
683 pData->SetItemCheckRect(m_pInterface, hItem, rtCheck);
684 CFWL_ThemeBackground param;
685 param.m_pWidget = m_pInterface;
686 param.m_iPart = FWL_PART_LTB_Check;
687 param.m_pGraphics = pGraphics;
688 if (GetItemChecked(hItem)) {
689 param.m_dwStates = FWL_PARTSTATE_LTB_Checked;
690 } else {
691 param.m_dwStates = FWL_PARTSTATE_LTB_UnChecked;
692 }
693 param.m_matrix.Concat(*pMatrix);
694 param.m_rtPart = rtCheck;
695 param.m_dwData = (FX_DWORD)(uintptr_t)(&itemData);
696 pTheme->DrawBackground(¶m);
697 }
698 CFX_WideString wsText;
699 pData->GetItemText(m_pInterface, hItem, wsText);
700 if (wsText.GetLength() <= 0) {
701 return;
702 }
703 CFX_RectF rtText(rtItem);
704 rtText.Deflate(FWL_LISTBOX_ItemTextMargin, FWL_LISTBOX_ItemTextMargin);
705 if (bHasIcon || bHasCheck) {
706 rtText.Deflate(rtItem.height, 0, 0, 0);
707 }
708 CFWL_ThemeText textParam;
709 textParam.m_pWidget = m_pInterface;
710 textParam.m_iPart = FWL_PART_LTB_ListItem;
711 textParam.m_dwStates = dwPartStates;
712 textParam.m_pGraphics = pGraphics;
713 textParam.m_matrix.Concat(*pMatrix);
714 textParam.m_rtPart = rtText;
715 textParam.m_wsText = wsText;
716 textParam.m_dwTTOStyles = m_dwTTOStyles;
717 textParam.m_iTTOAlign = m_iTTOAligns;
718 textParam.m_dwData = (FX_DWORD)(uintptr_t)(&itemData);
719 pTheme->DrawText(&textParam);
720 }
721 }
CalcSize(FX_BOOL bAutoSize)722 CFX_SizeF CFWL_ListBoxImp::CalcSize(FX_BOOL bAutoSize) {
723 CFX_SizeF fs;
724 fs.Set(0, 0);
725 if (!m_pProperties->m_pThemeProvider)
726 return fs;
727 GetClientRect(m_rtClient);
728 m_rtConent = m_rtClient;
729 CFX_RectF rtUIMargin;
730 rtUIMargin.Set(0, 0, 0, 0);
731 if (!m_pOuter) {
732 CFX_RectF* pUIMargin =
733 static_cast<CFX_RectF*>(GetThemeCapacity(FWL_WGTCAPACITY_UIMargin));
734 if (pUIMargin) {
735 m_rtConent.Deflate(pUIMargin->left, pUIMargin->top, pUIMargin->width,
736 pUIMargin->height);
737 }
738 }
739 FX_FLOAT fWidth = 0;
740 if (m_pProperties->m_pThemeProvider->IsCustomizedLayout(m_pInterface)) {
741 IFWL_ListBoxDP* pData =
742 static_cast<IFWL_ListBoxDP*>(m_pProperties->m_pDataProvider);
743 if (!bAutoSize) {
744 }
745 int32_t iCount = pData->CountItems(m_pInterface);
746 for (int32_t i = 0; i < iCount; i++) {
747 FWL_HLISTITEM hItem = pData->GetItem(m_pInterface, i);
748 CFWL_ThemePart itemPart;
749 itemPart.m_pWidget = m_pInterface;
750 itemPart.m_iPart = FWL_PART_LTB_ListItem;
751 itemPart.m_pData = m_pProperties->m_pDataProvider;
752 itemPart.m_dwData = i;
753 CFX_RectF r;
754 m_pProperties->m_pThemeProvider->GetPartRect(&itemPart, r);
755 if (!bAutoSize) {
756 CFX_RectF rtItem;
757 rtItem.Set(m_rtClient.left, m_rtClient.top + fs.y, r.width, r.height);
758 IFWL_ListBoxDP* pData =
759 static_cast<IFWL_ListBoxDP*>(m_pProperties->m_pDataProvider);
760 pData->SetItemRect(m_pInterface, hItem, rtItem);
761 }
762 fs.y += r.height;
763 if (fs.x < r.width) {
764 fs.x = r.width;
765 fWidth = r.width;
766 }
767 }
768 } else {
769 fWidth = GetMaxTextWidth();
770 fWidth += 2 * FWL_LISTBOX_ItemTextMargin;
771 if (!bAutoSize) {
772 FX_FLOAT fActualWidth =
773 m_rtClient.width - rtUIMargin.left - rtUIMargin.width;
774 if (fWidth < fActualWidth) {
775 fWidth = fActualWidth;
776 }
777 }
778 IFWL_ListBoxDP* pData =
779 static_cast<IFWL_ListBoxDP*>(m_pProperties->m_pDataProvider);
780 m_fItemHeight = GetItemHeigt();
781 FX_BOOL bHasIcon;
782 bHasIcon = GetStylesEx() & FWL_STYLEEXT_LTB_Icon;
783 if (bHasIcon) {
784 fWidth += m_fItemHeight;
785 }
786 int32_t iCount = pData->CountItems(m_pInterface);
787 for (int32_t i = 0; i < iCount; i++) {
788 FWL_HLISTITEM htem = pData->GetItem(m_pInterface, i);
789 GetItemSize(fs, htem, fWidth, m_fItemHeight, bAutoSize);
790 }
791 }
792 if (bAutoSize) {
793 return fs;
794 }
795 FX_FLOAT iWidth = m_rtClient.width - rtUIMargin.left - rtUIMargin.width;
796 FX_FLOAT iHeight = m_rtClient.height;
797 FX_BOOL bShowVertScr =
798 (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_LTB_ShowScrollBarAlaways) &&
799 (m_pProperties->m_dwStyles & FWL_WGTSTYLE_VScroll);
800 FX_BOOL bShowHorzScr =
801 (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_LTB_ShowScrollBarAlaways) &&
802 (m_pProperties->m_dwStyles & FWL_WGTSTYLE_HScroll);
803 if (!bShowVertScr && m_pProperties->m_dwStyles & FWL_WGTSTYLE_VScroll &&
804 (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_LTB_MultiColumn) == 0) {
805 bShowVertScr = (fs.y > iHeight);
806 }
807 if (!bShowHorzScr && m_pProperties->m_dwStyles & FWL_WGTSTYLE_HScroll) {
808 bShowHorzScr = (fs.x > iWidth);
809 }
810 CFX_SizeF szRange;
811 if (bShowVertScr) {
812 if (!m_pVertScrollBar) {
813 InitScrollBar();
814 }
815 CFX_RectF rtScrollBar;
816 rtScrollBar.Set(m_rtClient.right() - m_fScorllBarWidth, m_rtClient.top,
817 m_fScorllBarWidth, m_rtClient.height - 1);
818 if (bShowHorzScr) {
819 rtScrollBar.height -= m_fScorllBarWidth;
820 }
821 m_pVertScrollBar->SetWidgetRect(rtScrollBar);
822 szRange.x = 0, szRange.y = fs.y - m_rtConent.height;
823 if (szRange.y < m_fItemHeight) {
824 szRange.y = m_fItemHeight;
825 }
826 m_pVertScrollBar->SetRange(szRange.x, szRange.y);
827 m_pVertScrollBar->SetPageSize(rtScrollBar.height * 9 / 10);
828 m_pVertScrollBar->SetStepSize(m_fItemHeight);
829 FX_FLOAT fPos = m_pVertScrollBar->GetPos();
830 if (fPos < 0) {
831 fPos = 0;
832 }
833 if (fPos > szRange.y) {
834 fPos = szRange.y;
835 }
836 m_pVertScrollBar->SetPos(fPos);
837 m_pVertScrollBar->SetTrackPos(fPos);
838 if ((m_pProperties->m_dwStyleExes & FWL_STYLEEXT_LTB_ShowScrollBarFocus) ==
839 0 ||
840 (m_pProperties->m_dwStates & FWL_WGTSTATE_Focused)) {
841 m_pVertScrollBar->SetStates(FWL_WGTSTATE_Invisible, FALSE);
842 }
843 m_pVertScrollBar->Update();
844 } else if (m_pVertScrollBar) {
845 m_pVertScrollBar->SetPos(0);
846 m_pVertScrollBar->SetTrackPos(0);
847 m_pVertScrollBar->SetStates(FWL_WGTSTATE_Invisible, TRUE);
848 }
849 if (bShowHorzScr) {
850 if (!m_pHorzScrollBar) {
851 InitScrollBar(FALSE);
852 }
853 CFX_RectF rtScrollBar;
854 rtScrollBar.Set(m_rtClient.left, m_rtClient.bottom() - m_fScorllBarWidth,
855 m_rtClient.width, m_fScorllBarWidth);
856 if (bShowVertScr) {
857 rtScrollBar.width -= m_fScorllBarWidth;
858 }
859 m_pHorzScrollBar->SetWidgetRect(rtScrollBar);
860 szRange.x = 0, szRange.y = fs.x - rtScrollBar.width;
861 m_pHorzScrollBar->SetRange(szRange.x, szRange.y);
862 m_pHorzScrollBar->SetPageSize(fWidth * 9 / 10);
863 m_pHorzScrollBar->SetStepSize(fWidth / 10);
864 FX_FLOAT fPos = m_pHorzScrollBar->GetPos();
865 if (fPos < 0) {
866 fPos = 0;
867 }
868 if (fPos > szRange.y) {
869 fPos = szRange.y;
870 }
871 m_pHorzScrollBar->SetPos(fPos);
872 m_pHorzScrollBar->SetTrackPos(fPos);
873 if ((m_pProperties->m_dwStyleExes & FWL_STYLEEXT_LTB_ShowScrollBarFocus) ==
874 0 ||
875 (m_pProperties->m_dwStates & FWL_WGTSTATE_Focused)) {
876 m_pHorzScrollBar->SetStates(FWL_WGTSTATE_Invisible, FALSE);
877 }
878 m_pHorzScrollBar->Update();
879 } else if (m_pHorzScrollBar) {
880 m_pHorzScrollBar->SetPos(0);
881 m_pHorzScrollBar->SetTrackPos(0);
882 m_pHorzScrollBar->SetStates(FWL_WGTSTATE_Invisible, TRUE);
883 }
884 if (bShowVertScr && bShowHorzScr) {
885 m_rtStatic.Set(m_rtClient.right() - m_fScorllBarWidth,
886 m_rtClient.bottom() - m_fScorllBarWidth, m_fScorllBarWidth,
887 m_fScorllBarWidth);
888 }
889 return fs;
890 }
GetItemSize(CFX_SizeF & size,FWL_HLISTITEM hItem,FX_FLOAT fWidth,FX_FLOAT m_fItemHeight,FX_BOOL bAutoSize)891 void CFWL_ListBoxImp::GetItemSize(CFX_SizeF& size,
892 FWL_HLISTITEM hItem,
893 FX_FLOAT fWidth,
894 FX_FLOAT m_fItemHeight,
895 FX_BOOL bAutoSize) {
896 if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_LTB_MultiColumn) {
897 } else {
898 if (!bAutoSize) {
899 CFX_RectF rtItem;
900 rtItem.Set(0, size.y, fWidth, m_fItemHeight);
901 IFWL_ListBoxDP* pData =
902 static_cast<IFWL_ListBoxDP*>(m_pProperties->m_pDataProvider);
903 pData->SetItemRect(m_pInterface, hItem, rtItem);
904 }
905 size.x = fWidth;
906 size.y += m_fItemHeight;
907 }
908 }
GetMaxTextWidth()909 FX_FLOAT CFWL_ListBoxImp::GetMaxTextWidth() {
910 FX_FLOAT fRet = 0.0f;
911 IFWL_ListBoxDP* pData =
912 static_cast<IFWL_ListBoxDP*>(m_pProperties->m_pDataProvider);
913 int32_t iCount = pData->CountItems(m_pInterface);
914 for (int32_t i = 0; i < iCount; i++) {
915 FWL_HLISTITEM hItem = pData->GetItem(m_pInterface, i);
916 if (!hItem) {
917 continue;
918 }
919 CFX_WideString wsText;
920 pData->GetItemText(m_pInterface, hItem, wsText);
921 CFX_SizeF sz = CalcTextSize(wsText, m_pProperties->m_pThemeProvider);
922 if (sz.x > fRet) {
923 fRet = sz.x;
924 }
925 }
926 return fRet;
927 }
GetScrollWidth()928 FX_FLOAT CFWL_ListBoxImp::GetScrollWidth() {
929 FX_FLOAT* pfWidth =
930 static_cast<FX_FLOAT*>(GetThemeCapacity(FWL_WGTCAPACITY_ScrollBarWidth));
931 if (!pfWidth)
932 return 0;
933 return *pfWidth;
934 }
GetItemHeigt()935 FX_FLOAT CFWL_ListBoxImp::GetItemHeigt() {
936 FX_FLOAT* pfFont =
937 static_cast<FX_FLOAT*>(GetThemeCapacity(FWL_WGTCAPACITY_FontSize));
938 if (!pfFont)
939 return 20;
940 return *pfFont + 2 * FWL_LISTBOX_ItemTextMargin;
941 }
InitScrollBar(FX_BOOL bVert)942 void CFWL_ListBoxImp::InitScrollBar(FX_BOOL bVert) {
943 if ((bVert && m_pVertScrollBar) || (!bVert && m_pHorzScrollBar)) {
944 return;
945 }
946 CFWL_WidgetImpProperties prop;
947 prop.m_dwStyleExes = bVert ? FWL_STYLEEXT_SCB_Vert : FWL_STYLEEXT_SCB_Horz;
948 prop.m_dwStates = FWL_WGTSTATE_Invisible;
949 prop.m_pParent = m_pInterface;
950 prop.m_pThemeProvider = m_pScrollBarTP;
951 IFWL_ScrollBar* pScrollBar = IFWL_ScrollBar::Create(prop, m_pInterface);
952 pScrollBar->Initialize();
953 (bVert ? &m_pVertScrollBar : &m_pHorzScrollBar)->reset(pScrollBar);
954 }
SortItem()955 void CFWL_ListBoxImp::SortItem() {}
IsShowScrollBar(FX_BOOL bVert)956 FX_BOOL CFWL_ListBoxImp::IsShowScrollBar(FX_BOOL bVert) {
957 IFWL_ScrollBar* pScrollbar =
958 bVert ? m_pVertScrollBar.get() : m_pHorzScrollBar.get();
959 if (!pScrollbar || (pScrollbar->GetStates() & FWL_WGTSTATE_Invisible)) {
960 return FALSE;
961 }
962 return !(m_pProperties->m_dwStyleExes &
963 FWL_STYLEEXT_LTB_ShowScrollBarFocus) ||
964 (m_pProperties->m_dwStates & FWL_WGTSTATE_Focused);
965 }
ProcessSelChanged()966 void CFWL_ListBoxImp::ProcessSelChanged() {
967 CFWL_EvtLtbSelChanged selEvent;
968 selEvent.m_pSrcTarget = m_pInterface;
969 CFX_Int32Array arrSels;
970 int32_t iCount = CountSelItems();
971 for (int32_t i = 0; i < iCount; i++) {
972 FWL_HLISTITEM item = GetSelItem(i);
973 if (item == NULL) {
974 continue;
975 }
976 selEvent.iarraySels.Add(i);
977 }
978 DispatchEvent(&selEvent);
979 }
CFWL_ListBoxImpDelegate(CFWL_ListBoxImp * pOwner)980 CFWL_ListBoxImpDelegate::CFWL_ListBoxImpDelegate(CFWL_ListBoxImp* pOwner)
981 : m_pOwner(pOwner) {}
OnProcessMessage(CFWL_Message * pMessage)982 int32_t CFWL_ListBoxImpDelegate::OnProcessMessage(CFWL_Message* pMessage) {
983 if (!pMessage)
984 return 0;
985 if (!m_pOwner->IsEnabled()) {
986 return 1;
987 }
988 FX_DWORD dwMsgCode = pMessage->GetClassID();
989 int32_t iRet = 1;
990 switch (dwMsgCode) {
991 case FWL_MSGHASH_SetFocus:
992 case FWL_MSGHASH_KillFocus: {
993 OnFocusChanged(pMessage, dwMsgCode == FWL_MSGHASH_SetFocus);
994 break;
995 }
996 case FWL_MSGHASH_Mouse: {
997 CFWL_MsgMouse* pMsg = static_cast<CFWL_MsgMouse*>(pMessage);
998 FX_DWORD dwCmd = pMsg->m_dwCmd;
999 switch (dwCmd) {
1000 case FWL_MSGMOUSECMD_LButtonDown: {
1001 OnLButtonDown(pMsg);
1002 break;
1003 }
1004 case FWL_MSGMOUSECMD_LButtonUp: {
1005 OnLButtonUp(pMsg);
1006 break;
1007 }
1008 default: {}
1009 }
1010 break;
1011 }
1012 case FWL_MSGHASH_MouseWheel: {
1013 OnMouseWheel(static_cast<CFWL_MsgMouseWheel*>(pMessage));
1014 break;
1015 }
1016 case FWL_MSGHASH_Key: {
1017 CFWL_MsgKey* pMsg = static_cast<CFWL_MsgKey*>(pMessage);
1018 if (pMsg->m_dwCmd == FWL_MSGKEYCMD_KeyDown)
1019 OnKeyDown(pMsg);
1020 break;
1021 }
1022 default: { iRet = 0; }
1023 }
1024 CFWL_WidgetImpDelegate::OnProcessMessage(pMessage);
1025 return iRet;
1026 }
OnProcessEvent(CFWL_Event * pEvent)1027 FWL_ERR CFWL_ListBoxImpDelegate::OnProcessEvent(CFWL_Event* pEvent) {
1028 if (!pEvent)
1029 return FWL_ERR_Indefinite;
1030 if (pEvent->GetClassID() != FWL_EVTHASH_Scroll) {
1031 return FWL_ERR_Succeeded;
1032 }
1033 IFWL_Widget* pSrcTarget = pEvent->m_pSrcTarget;
1034 if ((pSrcTarget == m_pOwner->m_pVertScrollBar.get() &&
1035 m_pOwner->m_pVertScrollBar) ||
1036 (pSrcTarget == m_pOwner->m_pHorzScrollBar.get() &&
1037 m_pOwner->m_pHorzScrollBar)) {
1038 CFWL_EvtScroll* pScrollEvent = static_cast<CFWL_EvtScroll*>(pEvent);
1039 OnScroll(static_cast<IFWL_ScrollBar*>(pSrcTarget),
1040 pScrollEvent->m_iScrollCode, pScrollEvent->m_fPos);
1041 }
1042 return FWL_ERR_Succeeded;
1043 }
OnDrawWidget(CFX_Graphics * pGraphics,const CFX_Matrix * pMatrix)1044 FWL_ERR CFWL_ListBoxImpDelegate::OnDrawWidget(CFX_Graphics* pGraphics,
1045 const CFX_Matrix* pMatrix) {
1046 return m_pOwner->DrawWidget(pGraphics, pMatrix);
1047 }
OnFocusChanged(CFWL_Message * pMsg,FX_BOOL bSet)1048 void CFWL_ListBoxImpDelegate::OnFocusChanged(CFWL_Message* pMsg, FX_BOOL bSet) {
1049 if (m_pOwner->GetStylesEx() & FWL_STYLEEXT_LTB_ShowScrollBarFocus) {
1050 if (m_pOwner->m_pVertScrollBar) {
1051 m_pOwner->m_pVertScrollBar->SetStates(FWL_WGTSTATE_Invisible, !bSet);
1052 }
1053 if (m_pOwner->m_pHorzScrollBar) {
1054 m_pOwner->m_pHorzScrollBar->SetStates(FWL_WGTSTATE_Invisible, !bSet);
1055 }
1056 }
1057 if (bSet) {
1058 m_pOwner->m_pProperties->m_dwStates |= (FWL_WGTSTATE_Focused);
1059 } else {
1060 m_pOwner->m_pProperties->m_dwStates &= ~(FWL_WGTSTATE_Focused);
1061 }
1062 m_pOwner->Repaint(&m_pOwner->m_rtClient);
1063 }
OnLButtonDown(CFWL_MsgMouse * pMsg)1064 void CFWL_ListBoxImpDelegate::OnLButtonDown(CFWL_MsgMouse* pMsg) {
1065 m_pOwner->m_bLButtonDown = TRUE;
1066 if ((m_pOwner->m_pProperties->m_dwStates & FWL_WGTSTATE_Focused) == 0) {
1067 m_pOwner->SetFocus(TRUE);
1068 }
1069 FWL_HLISTITEM hItem = m_pOwner->GetItemAtPoint(pMsg->m_fx, pMsg->m_fy);
1070 if (!hItem) {
1071 return;
1072 }
1073 if (m_pOwner->m_pProperties->m_dwStyleExes &
1074 FWL_STYLEEXT_LTB_MultiSelection) {
1075 if (pMsg->m_dwFlags & FWL_KEYFLAG_Ctrl) {
1076 FX_BOOL bSelected = m_pOwner->IsItemSelected(hItem);
1077 m_pOwner->SetSelectionDirect(hItem, !bSelected);
1078 m_pOwner->m_hAnchor = hItem;
1079 } else if (pMsg->m_dwFlags & FWL_KEYFLAG_Shift) {
1080 if (m_pOwner->m_hAnchor) {
1081 m_pOwner->SetSelection(m_pOwner->m_hAnchor, hItem, TRUE);
1082 } else {
1083 m_pOwner->SetSelectionDirect(hItem, TRUE);
1084 }
1085 } else {
1086 m_pOwner->SetSelection(hItem, hItem, TRUE);
1087 m_pOwner->m_hAnchor = hItem;
1088 }
1089 } else {
1090 m_pOwner->SetSelection(hItem, hItem, TRUE);
1091 }
1092 if (m_pOwner->m_pProperties->m_dwStyleExes & FWL_STYLEEXT_LTB_Check) {
1093 FWL_HLISTITEM hSelectedItem =
1094 m_pOwner->GetItemAtPoint(pMsg->m_fx, pMsg->m_fy);
1095 CFX_RectF rtCheck;
1096 m_pOwner->GetItemCheckRect(hSelectedItem, rtCheck);
1097 FX_BOOL bChecked = m_pOwner->GetItemChecked(hItem);
1098 if (rtCheck.Contains(pMsg->m_fx, pMsg->m_fy)) {
1099 if (bChecked) {
1100 m_pOwner->SetItemChecked(hItem, FALSE);
1101 } else {
1102 m_pOwner->SetItemChecked(hItem, TRUE);
1103 }
1104 m_pOwner->Update();
1105 }
1106 }
1107 m_pOwner->SetFocusItem(hItem);
1108 m_pOwner->ScrollToVisible(hItem);
1109 m_pOwner->SetGrab(TRUE);
1110 m_pOwner->ProcessSelChanged();
1111 m_pOwner->Repaint(&m_pOwner->m_rtClient);
1112 }
OnLButtonUp(CFWL_MsgMouse * pMsg)1113 void CFWL_ListBoxImpDelegate::OnLButtonUp(CFWL_MsgMouse* pMsg) {
1114 if (m_pOwner->m_bLButtonDown) {
1115 m_pOwner->m_bLButtonDown = FALSE;
1116 m_pOwner->SetGrab(FALSE);
1117 DispatchSelChangedEv();
1118 }
1119 }
OnMouseWheel(CFWL_MsgMouseWheel * pMsg)1120 void CFWL_ListBoxImpDelegate::OnMouseWheel(CFWL_MsgMouseWheel* pMsg) {
1121 if (!m_pOwner->IsShowScrollBar(TRUE)) {
1122 return;
1123 }
1124 IFWL_WidgetDelegate* pDelegate =
1125 m_pOwner->m_pVertScrollBar->SetDelegate(NULL);
1126 pDelegate->OnProcessMessage(pMsg);
1127 }
OnKeyDown(CFWL_MsgKey * pMsg)1128 void CFWL_ListBoxImpDelegate::OnKeyDown(CFWL_MsgKey* pMsg) {
1129 FX_DWORD dwKeyCode = pMsg->m_dwKeyCode;
1130 switch (dwKeyCode) {
1131 case FWL_VKEY_Tab:
1132 case FWL_VKEY_Up:
1133 case FWL_VKEY_Down:
1134 case FWL_VKEY_Home:
1135 case FWL_VKEY_End: {
1136 FWL_HLISTITEM hItem = m_pOwner->GetFocusedItem();
1137 hItem = m_pOwner->GetItem(hItem, dwKeyCode);
1138 FX_BOOL bShift = pMsg->m_dwFlags & FWL_KEYFLAG_Shift;
1139 FX_BOOL bCtrl = pMsg->m_dwFlags & FWL_KEYFLAG_Ctrl;
1140 OnVK(hItem, bShift, bCtrl);
1141 DispatchSelChangedEv();
1142 m_pOwner->ProcessSelChanged();
1143 break;
1144 }
1145 default: {}
1146 }
1147 }
OnVK(FWL_HLISTITEM hItem,FX_BOOL bShift,FX_BOOL bCtrl)1148 void CFWL_ListBoxImpDelegate::OnVK(FWL_HLISTITEM hItem,
1149 FX_BOOL bShift,
1150 FX_BOOL bCtrl) {
1151 if (!hItem) {
1152 return;
1153 }
1154 if (m_pOwner->m_pProperties->m_dwStyleExes &
1155 FWL_STYLEEXT_LTB_MultiSelection) {
1156 if (bCtrl) {
1157 } else if (bShift) {
1158 if (m_pOwner->m_hAnchor) {
1159 m_pOwner->SetSelection(m_pOwner->m_hAnchor, hItem, TRUE);
1160 } else {
1161 m_pOwner->SetSelectionDirect(hItem, TRUE);
1162 }
1163 } else {
1164 m_pOwner->SetSelection(hItem, hItem, TRUE);
1165 m_pOwner->m_hAnchor = hItem;
1166 }
1167 } else {
1168 m_pOwner->SetSelection(hItem, hItem, TRUE);
1169 }
1170 m_pOwner->SetFocusItem(hItem);
1171 m_pOwner->ScrollToVisible(hItem);
1172 {
1173 CFX_RectF rtInvalidate;
1174 rtInvalidate.Set(0, 0, m_pOwner->m_pProperties->m_rtWidget.width,
1175 m_pOwner->m_pProperties->m_rtWidget.height);
1176 m_pOwner->Repaint(&rtInvalidate);
1177 }
1178 }
OnScroll(IFWL_ScrollBar * pScrollBar,FX_DWORD dwCode,FX_FLOAT fPos)1179 FX_BOOL CFWL_ListBoxImpDelegate::OnScroll(IFWL_ScrollBar* pScrollBar,
1180 FX_DWORD dwCode,
1181 FX_FLOAT fPos) {
1182 CFX_SizeF fs;
1183 pScrollBar->GetRange(fs.x, fs.y);
1184 FX_FLOAT iCurPos = pScrollBar->GetPos();
1185 FX_FLOAT fStep = pScrollBar->GetStepSize();
1186 switch (dwCode) {
1187 case FWL_SCBCODE_Min: {
1188 fPos = fs.x;
1189 break;
1190 }
1191 case FWL_SCBCODE_Max: {
1192 fPos = fs.y;
1193 break;
1194 }
1195 case FWL_SCBCODE_StepBackward: {
1196 fPos -= fStep;
1197 if (fPos < fs.x + fStep / 2) {
1198 fPos = fs.x;
1199 }
1200 break;
1201 }
1202 case FWL_SCBCODE_StepForward: {
1203 fPos += fStep;
1204 if (fPos > fs.y - fStep / 2) {
1205 fPos = fs.y;
1206 }
1207 break;
1208 }
1209 case FWL_SCBCODE_PageBackward: {
1210 fPos -= pScrollBar->GetPageSize();
1211 if (fPos < fs.x) {
1212 fPos = fs.x;
1213 }
1214 break;
1215 }
1216 case FWL_SCBCODE_PageForward: {
1217 fPos += pScrollBar->GetPageSize();
1218 if (fPos > fs.y) {
1219 fPos = fs.y;
1220 }
1221 break;
1222 }
1223 case FWL_SCBCODE_Pos:
1224 case FWL_SCBCODE_TrackPos:
1225 break;
1226 case FWL_SCBCODE_EndScroll:
1227 return FALSE;
1228 }
1229 if (iCurPos != fPos) {
1230 pScrollBar->SetPos(fPos);
1231 pScrollBar->SetTrackPos(fPos);
1232 m_pOwner->Repaint(&m_pOwner->m_rtClient);
1233 }
1234 return TRUE;
1235 }
DispatchSelChangedEv()1236 void CFWL_ListBoxImpDelegate::DispatchSelChangedEv() {
1237 CFWL_EvtLtbSelChanged ev;
1238 ev.m_pSrcTarget = m_pOwner->m_pInterface;
1239 m_pOwner->DispatchEvent(&ev);
1240 }
1241