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