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