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