Merge XFA to PDFium master at 4dc95e7 on 10/28/2014
[pdfium.git] / xfa / src / fwl / src / basewidget / fwl_comboboximp.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 "../../src/core/include/fwl_threadimp.h"\r
9 #include "../../src/core/include/fwl_appimp.h"\r
10 #include "../core/include/fwl_targetimp.h"\r
11 #include "../core/include/fwl_noteimp.h"\r
12 #include "../core/include/fwl_widgetimp.h"\r
13 #include "../core/include/fwl_panelimp.h"\r
14 #include "../core/include/fwl_formimp.h"\r
15 #include "../core/include/fwl_widgetmgrimp.h"\r
16 #include "include/fwl_scrollbarimp.h"\r
17 #include "include/fwl_editimp.h"\r
18 #include "include/fwl_listboximp.h"\r
19 #include "include/fwl_formproxyimp.h"\r
20 #include "include/fwl_comboboximp.h"\r
21 IFWL_ComboBox* IFWL_ComboBox::Create()\r
22 {\r
23     return new IFWL_ComboBox;\r
24 }\r
25 IFWL_ComboBox::IFWL_ComboBox()\r
26 {\r
27     m_pData = NULL;\r
28 }\r
29 IFWL_ComboBox::~IFWL_ComboBox()\r
30 {\r
31     if (m_pData) {\r
32         delete (CFWL_ComboBoxImp*)m_pData;\r
33         m_pData = NULL;\r
34     }\r
35 }\r
36 FWL_ERR IFWL_ComboBox::Initialize(IFWL_Widget *pOuter)\r
37 {\r
38     m_pData = FX_NEW CFWL_ComboBoxImp(pOuter);\r
39     ((CFWL_ComboBoxImp*)m_pData)->SetInterface(this);\r
40     return ((CFWL_ComboBoxImp*)m_pData)->Initialize();\r
41 }\r
42 FWL_ERR IFWL_ComboBox::Initialize(const CFWL_WidgetImpProperties &properties, IFWL_Widget *pOuter)\r
43 {\r
44     m_pData = FX_NEW CFWL_ComboBoxImp(properties, pOuter);\r
45     ((CFWL_ComboBoxImp*)m_pData)->SetInterface(this);\r
46     return ((CFWL_ComboBoxImp*)m_pData)->Initialize();\r
47 }\r
48 FX_INT32 IFWL_ComboBox::GetCurSel()\r
49 {\r
50     return ((CFWL_ComboBoxImp*)m_pData)->GetCurSel();\r
51 }\r
52 FWL_ERR IFWL_ComboBox::SetCurSel(FX_INT32 iSel)\r
53 {\r
54     return ((CFWL_ComboBoxImp*)m_pData)->SetCurSel(iSel);\r
55 }\r
56 FWL_ERR IFWL_ComboBox::SetEditText(const CFX_WideString &wsText)\r
57 {\r
58     return ((CFWL_ComboBoxImp*)m_pData)->SetEditText(wsText);\r
59 }\r
60 FX_INT32 IFWL_ComboBox::GetEditTextLength() const\r
61 {\r
62     return ((CFWL_ComboBoxImp*)m_pData)->GetEditTextLength();\r
63 }\r
64 FWL_ERR IFWL_ComboBox::GetEditText(CFX_WideString &wsText, FX_INT32 nStart, FX_INT32 nCount) const\r
65 {\r
66     return ((CFWL_ComboBoxImp*)m_pData)->GetEditText(wsText, nStart, nCount);\r
67 }\r
68 FWL_ERR IFWL_ComboBox::SetEditSelRange(FX_INT32 nStart, FX_INT32 nCount)\r
69 {\r
70     return ((CFWL_ComboBoxImp*)m_pData)->SetEditSelRange(nStart, nCount);\r
71 }\r
72 FX_INT32 IFWL_ComboBox::GetEditSelRange(FX_INT32 nIndex, FX_INT32 &nStart)\r
73 {\r
74     return ((CFWL_ComboBoxImp*)m_pData)->GetEditSelRange(nIndex, nStart);\r
75 }\r
76 FX_INT32 IFWL_ComboBox::GetEditLimit()\r
77 {\r
78     return ((CFWL_ComboBoxImp*)m_pData)->GetEditLimit();\r
79 }\r
80 FWL_ERR IFWL_ComboBox::SetEditLimit(FX_INT32 nLimit)\r
81 {\r
82     return ((CFWL_ComboBoxImp*)m_pData)->SetEditLimit(nLimit);\r
83 }\r
84 FWL_ERR IFWL_ComboBox::EditDoClipboard(FX_INT32 iCmd)\r
85 {\r
86     return ((CFWL_ComboBoxImp*)m_pData)->EditDoClipboard(iCmd);\r
87 }\r
88 FX_BOOL IFWL_ComboBox::EditRedo(FX_BSTR bsRecord)\r
89 {\r
90     return ((CFWL_ComboBoxImp*)m_pData)->EditRedo(bsRecord);\r
91 }\r
92 FX_BOOL IFWL_ComboBox::EditUndo(FX_BSTR bsRecord)\r
93 {\r
94     return ((CFWL_ComboBoxImp*)m_pData)->EditUndo(bsRecord);\r
95 }\r
96 IFWL_ListBox*  IFWL_ComboBox::GetListBoxt()\r
97 {\r
98     return ((CFWL_ComboBoxImp*)m_pData)->GetListBoxt();\r
99 }\r
100 FX_BOOL IFWL_ComboBox::AfterFocusShowDropList()\r
101 {\r
102     return ((CFWL_ComboBoxImp*)m_pData)->AfterFocusShowDropList();\r
103 }\r
104 FX_ERR IFWL_ComboBox::OpenDropDownList(FX_BOOL bActivate)\r
105 {\r
106     return ((CFWL_ComboBoxImp*)m_pData)->OpenDropDownList(bActivate);\r
107 }\r
108 FX_BOOL IFWL_ComboBox::EditCanUndo()\r
109 {\r
110     return ((CFWL_ComboBoxImp*)m_pData)->EditCanUndo();\r
111 }\r
112 FX_BOOL IFWL_ComboBox::EditCanRedo()\r
113 {\r
114     return ((CFWL_ComboBoxImp*)m_pData)->EditCanRedo();\r
115 }\r
116 FX_BOOL IFWL_ComboBox::EditUndo()\r
117 {\r
118     return ((CFWL_ComboBoxImp*)m_pData)->EditUndo();\r
119 }\r
120 FX_BOOL IFWL_ComboBox::EditRedo()\r
121 {\r
122     return ((CFWL_ComboBoxImp*)m_pData)->EditRedo();\r
123 }\r
124 FX_BOOL IFWL_ComboBox::EditCanCopy()\r
125 {\r
126     return ((CFWL_ComboBoxImp*)m_pData)->EditCanCopy();\r
127 }\r
128 FX_BOOL IFWL_ComboBox::EditCanCut()\r
129 {\r
130     return ((CFWL_ComboBoxImp*)m_pData)->EditCanCut();\r
131 }\r
132 FX_BOOL IFWL_ComboBox::EditCanSelectAll()\r
133 {\r
134     return ((CFWL_ComboBoxImp*)m_pData)->EditCanSelectAll();\r
135 }\r
136 FX_BOOL IFWL_ComboBox::EditCopy(CFX_WideString &wsCopy)\r
137 {\r
138     return ((CFWL_ComboBoxImp*)m_pData)->EditCopy(wsCopy);\r
139 }\r
140 FX_BOOL IFWL_ComboBox::EditCut(CFX_WideString &wsCut)\r
141 {\r
142     return ((CFWL_ComboBoxImp*)m_pData)->EditCut(wsCut);\r
143 }\r
144 FX_BOOL IFWL_ComboBox::EditPaste(const CFX_WideString &wsPaste)\r
145 {\r
146     return ((CFWL_ComboBoxImp*)m_pData)->EditPaste(wsPaste);\r
147 }\r
148 FX_BOOL IFWL_ComboBox::EditSelectAll()\r
149 {\r
150     return ((CFWL_ComboBoxImp*)m_pData)->EditSelectAll();\r
151 }\r
152 FX_BOOL IFWL_ComboBox::EditDelete()\r
153 {\r
154     return ((CFWL_ComboBoxImp*)m_pData)->EditDelete();\r
155 }\r
156 FX_BOOL IFWL_ComboBox::EditDeSelect()\r
157 {\r
158     return ((CFWL_ComboBoxImp*)m_pData)->EditDeSelect();\r
159 }\r
160 FWL_ERR IFWL_ComboBox::GetBBox(CFX_RectF &rect)\r
161 {\r
162     return ((CFWL_ComboBoxImp*)m_pData)->GetBBox(rect);\r
163 }\r
164 FWL_ERR IFWL_ComboBox::EditModifyStylesEx(FX_DWORD dwStylesExAdded,\r
165         FX_DWORD dwStylesExRemoved)\r
166 {\r
167     return ((CFWL_ComboBoxImp*)m_pData)->EditModifyStylesEx(dwStylesExAdded,\r
168             dwStylesExRemoved);\r
169 }\r
170 CFWL_ComboEdit::CFWL_ComboEdit(IFWL_Widget *pOuter)\r
171     : CFWL_EditImp(pOuter)\r
172 {\r
173     FXSYS_assert(pOuter != NULL);\r
174     m_pOuter = (CFWL_ComboBoxImp*)(((IFWL_TargetData*)pOuter)->GetData());\r
175 }\r
176 CFWL_ComboEdit::CFWL_ComboEdit(const CFWL_WidgetImpProperties &properties, IFWL_Widget *pOuter)\r
177     : CFWL_EditImp(properties, pOuter)\r
178 {\r
179     FXSYS_assert(pOuter != NULL);\r
180     m_pOuter = (CFWL_ComboBoxImp*)(((IFWL_TargetData*)pOuter)->GetData());\r
181 }\r
182 \r
183 CFWL_ComboEditDelegate::CFWL_ComboEditDelegate(CFWL_ComboEdit *pOwner)\r
184     : CFWL_EditImpDelegate(pOwner)\r
185     , m_pOwner(pOwner)\r
186 {\r
187 }\r
188 FX_INT32 CFWL_ComboEditDelegate::OnProcessMessage(CFWL_Message *pMessage)\r
189 {\r
190     _FWL_RETURN_VALUE_IF_FAIL(pMessage, 0);\r
191     FX_DWORD dwMsgCode = pMessage->GetClassID();\r
192     FX_BOOL backDefault = TRUE;\r
193     switch (dwMsgCode) {\r
194         case FWL_MSGHASH_SetFocus:\r
195         case FWL_MSGHASH_KillFocus: {\r
196                 if (dwMsgCode == FWL_MSGHASH_SetFocus) {\r
197                     m_pOwner->m_pProperties->m_dwStates |= FWL_WGTSTATE_Focused;\r
198                 } else {\r
199                     m_pOwner->m_pProperties->m_dwStates &= ~FWL_WGTSTATE_Focused;\r
200                 }\r
201                 backDefault = FALSE;\r
202                 break;\r
203             }\r
204         case FWL_MSGHASH_Mouse: {\r
205                 CFWL_MsgMouse *pMsg = (CFWL_MsgMouse*)pMessage;\r
206                 if ((pMsg->m_dwCmd == FWL_MSGMOUSECMD_LButtonDown) &&\r
207                         ((m_pOwner->m_pProperties->m_dwStates & FWL_WGTSTATE_Focused) == 0)) {\r
208                     m_pOwner->SetSelected();\r
209                     m_pOwner->SetComboBoxFocus(TRUE);\r
210                 }\r
211                 break;\r
212             }\r
213         default: {\r
214             }\r
215     }\r
216     if (!backDefault) {\r
217         return 1;\r
218     }\r
219     return CFWL_EditImpDelegate::OnProcessMessage(pMessage);\r
220 }\r
221 void CFWL_ComboEdit::ClearSelected()\r
222 {\r
223     ClearSelections();\r
224     Repaint(&m_rtClient);\r
225 }\r
226 void CFWL_ComboEdit::SetSelected()\r
227 {\r
228     FlagFocus(TRUE);\r
229     EndCaret();\r
230     AddSelRange(0);\r
231 }\r
232 void CFWL_ComboEdit::EndCaret()\r
233 {\r
234     m_pEdtEngine->MoveCaretPos(MC_End);\r
235 }\r
236 void CFWL_ComboEdit::FlagFocus(FX_BOOL bSet)\r
237 {\r
238     if (bSet) {\r
239         m_pProperties->m_dwStates |= FWL_WGTSTATE_Focused;\r
240     } else {\r
241         m_pProperties->m_dwStates &= ~FWL_WGTSTATE_Focused;\r
242         ShowCaret(FALSE);\r
243     }\r
244 };\r
245 void CFWL_ComboEdit::SetComboBoxFocus(FX_BOOL bSet)\r
246 {\r
247     m_pOuter->SetFocus(bSet);\r
248 }\r
249 CFWL_ComboList::CFWL_ComboList(IFWL_Widget *pOuter)\r
250     : CFWL_ListBoxImp(pOuter)\r
251     , m_bNotifyOwner(TRUE)\r
252 {\r
253     FXSYS_assert(pOuter != NULL);\r
254 }\r
255 CFWL_ComboList::CFWL_ComboList(const CFWL_WidgetImpProperties &properties, IFWL_Widget *pOuter)\r
256     : CFWL_ListBoxImp(properties, pOuter)\r
257     , m_bNotifyOwner(TRUE)\r
258 {\r
259     FXSYS_assert(pOuter != NULL);\r
260 }\r
261 FWL_ERR CFWL_ComboList::Initialize()\r
262 {\r
263     _FWL_ERR_CHECK_RETURN_VALUE_IF_FAIL(CFWL_ListBoxImp::Initialize(), FWL_ERR_Indefinite);\r
264     if (m_pDelegate) {\r
265         delete (CFWL_ComboListDelegate*)m_pDelegate;\r
266         m_pDelegate = NULL;\r
267     }\r
268     m_pDelegate = (IFWL_WidgetDelegate*)FX_NEW CFWL_ComboListDelegate(this);\r
269     return FWL_ERR_Succeeded;\r
270 }\r
271 FWL_ERR CFWL_ComboList::Finalize()\r
272 {\r
273     if ( m_pDelegate) {\r
274         delete (CFWL_ComboListDelegate*)m_pDelegate;\r
275         m_pDelegate = NULL;\r
276     }\r
277     return CFWL_ListBoxImp::Finalize();\r
278 }\r
279 FX_INT32 CFWL_ComboList::MatchItem(const CFX_WideString &wsMatch)\r
280 {\r
281     if (wsMatch.IsEmpty()) {\r
282         return -1;\r
283     }\r
284     _FWL_RETURN_VALUE_IF_FAIL(m_pProperties->m_pDataProvider, -1);\r
285     IFWL_ListBoxDP *pData = (IFWL_ListBoxDP*)m_pProperties->m_pDataProvider;\r
286     FX_INT32 iCount = pData->CountItems(m_pInterface);\r
287     for (FX_INT32 i = 0; i < iCount; i ++) {\r
288         FWL_HLISTITEM hItem = pData->GetItem(m_pInterface, i);\r
289         CFX_WideString wsText;\r
290         pData->GetItemText(m_pInterface, hItem, wsText);\r
291         FX_STRSIZE pos = wsText.Find((FX_LPCWSTR)wsMatch);\r
292         if (!pos) {\r
293             return i;\r
294         }\r
295     }\r
296     return -1;\r
297 }\r
298 void CFWL_ComboList::ChangeSelected(FX_INT32 iSel)\r
299 {\r
300     _FWL_RETURN_IF_FAIL(m_pProperties->m_pDataProvider);\r
301     IFWL_ListBoxDP *pData = (IFWL_ListBoxDP*)m_pProperties->m_pDataProvider;\r
302     FWL_HLISTITEM hItem = pData->GetItem(m_pInterface, iSel);\r
303     CFX_RectF rtInvalidate;\r
304     rtInvalidate.Reset();\r
305     FWL_HLISTITEM hOld = GetSelItem(0);\r
306     FX_INT32 iOld = pData->GetItemIndex(m_pInterface, hOld);\r
307     if (iOld == iSel) {\r
308         return;\r
309     } else if (iOld > -1) {\r
310         GetItemRect(iOld, rtInvalidate);\r
311         SetSelItem(hOld, FALSE);\r
312     }\r
313     if (hItem) {\r
314         CFX_RectF rect;\r
315         GetItemRect(iSel, rect);\r
316         rtInvalidate.Union(rect);\r
317         FWL_HLISTITEM hSel = pData->GetItem(m_pInterface, iSel);\r
318         SetSelItem(hSel, TRUE);\r
319     }\r
320     if (!rtInvalidate.IsEmpty()) {\r
321         Repaint(&rtInvalidate);\r
322     }\r
323 }\r
324 FX_INT32 CFWL_ComboList::CountItems()\r
325 {\r
326     _FWL_RETURN_VALUE_IF_FAIL(m_pProperties->m_pDataProvider, 0);\r
327     IFWL_ListBoxDP *pData = (IFWL_ListBoxDP*)m_pProperties->m_pDataProvider;\r
328     return pData->CountItems(m_pInterface);\r
329 }\r
330 void CFWL_ComboList::GetItemRect(FX_INT32 nIndex, CFX_RectF &rtItem)\r
331 {\r
332     IFWL_ListBoxDP *pData = (IFWL_ListBoxDP*)m_pProperties->m_pDataProvider;\r
333     FWL_HLISTITEM hItem = pData->GetItem(m_pInterface, nIndex);\r
334     pData->GetItemRect(m_pInterface, hItem, rtItem);\r
335 }\r
336 void CFWL_ComboList::ClientToOuter(FX_FLOAT &fx, FX_FLOAT &fy)\r
337 {\r
338     fx += m_pProperties->m_rtWidget.left, fy += m_pProperties->m_rtWidget.top;\r
339     IFWL_Widget *pOwner = GetOwner();\r
340     _FWL_RETURN_IF_FAIL(pOwner);\r
341     pOwner->TransformTo(m_pOuter, fx, fy);\r
342 }\r
343 void CFWL_ComboList::SetFocus(FX_BOOL bSet)\r
344 {\r
345     CFWL_WidgetImp::SetFocus(bSet);\r
346 }\r
347 CFWL_ComboListDelegate::CFWL_ComboListDelegate(CFWL_ComboList *pOwner)\r
348     : CFWL_ListBoxImpDelegate(pOwner)\r
349     , m_pOwner(pOwner)\r
350 {\r
351 }\r
352 FX_INT32 CFWL_ComboListDelegate::OnProcessMessage(CFWL_Message *pMessage)\r
353 {\r
354     _FWL_RETURN_VALUE_IF_FAIL(pMessage, 0);\r
355     FX_DWORD dwHashCode = pMessage->GetClassID();\r
356     FX_BOOL backDefault = TRUE;\r
357     if (dwHashCode == FWL_MSGHASH_SetFocus || dwHashCode == FWL_MSGHASH_KillFocus) {\r
358         OnDropListFocusChanged(pMessage, dwHashCode == FWL_MSGHASH_SetFocus);\r
359     } else if (dwHashCode == FWL_MSGHASH_Mouse) {\r
360         CFWL_MsgMouse *pMsg = (CFWL_MsgMouse*)pMessage;\r
361         if (m_pOwner->IsShowScrollBar(TRUE) && m_pOwner->m_pVertScrollBar) {\r
362             CFX_RectF rect;\r
363             m_pOwner->m_pVertScrollBar->GetWidgetRect(rect);\r
364             if (rect.Contains(pMsg->m_fx, pMsg->m_fy)) {\r
365                 pMsg->m_fx -= rect.left;\r
366                 pMsg->m_fy -= rect.top;\r
367                 IFWL_WidgetDelegate *pDelegate = m_pOwner->m_pVertScrollBar->SetDelegate(NULL);\r
368                 return pDelegate->OnProcessMessage(pMsg);\r
369             }\r
370         }\r
371         FX_DWORD dwCmd = pMsg->m_dwCmd;\r
372         switch (dwCmd) {\r
373             case FWL_MSGMOUSECMD_MouseMove: {\r
374                     backDefault = FALSE;\r
375                     OnDropListMouseMove(pMsg);\r
376                     break;\r
377                 }\r
378             case FWL_MSGMOUSECMD_LButtonDown: {\r
379                     backDefault = FALSE;\r
380                     OnDropListLButtonDown(pMsg);\r
381                     break;\r
382                 }\r
383             case FWL_MSGMOUSECMD_LButtonUp: {\r
384                     backDefault = FALSE;\r
385                     OnDropListLButtonUp(pMsg);\r
386                     break;\r
387                 }\r
388             default: {\r
389                 }\r
390         }\r
391     } else if (dwHashCode == FWL_MSGHASH_Key) {\r
392         CFWL_MsgKey *pMsg = (CFWL_MsgKey*)pMessage;\r
393         backDefault = !OnDropListKey(pMsg);\r
394     }\r
395     if (!backDefault) {\r
396         return 1;\r
397     }\r
398     return CFWL_ListBoxImpDelegate::OnProcessMessage(pMessage);\r
399 }\r
400 void CFWL_ComboListDelegate::OnDropListFocusChanged(CFWL_Message *pMsg, FX_BOOL bSet )\r
401 {\r
402     if (!bSet) {\r
403         CFWL_MsgKillFocus *pKill = (CFWL_MsgKillFocus*)pMsg;\r
404         CFWL_ComboBoxImp *pOuter = (CFWL_ComboBoxImp*)(((IFWL_TargetData*)m_pOwner->m_pOuter)->GetData());\r
405         if (pKill->m_pSetFocus == (IFWL_Widget*)m_pOwner->m_pOuter ||   (IFWL_Widget*)pKill->m_pSetFocus == (IFWL_Widget*)pOuter->m_pEdit) {\r
406             pOuter->ShowDropList(FALSE);\r
407         }\r
408     }\r
409 }\r
410 FX_INT32 CFWL_ComboListDelegate::OnDropListMouseMove(CFWL_MsgMouse *pMsg)\r
411 {\r
412     if (m_pOwner->m_rtClient.Contains(pMsg->m_fx, pMsg->m_fy)) {\r
413         if (m_pOwner->m_bNotifyOwner) {\r
414             m_pOwner->m_bNotifyOwner = FALSE;\r
415         }\r
416         if (m_pOwner->IsShowScrollBar(TRUE) && m_pOwner->m_pVertScrollBar) {\r
417             CFX_RectF rect;\r
418             m_pOwner->m_pVertScrollBar->GetWidgetRect(rect);\r
419             if (rect.Contains(pMsg->m_fx, pMsg->m_fy)) {\r
420                 return 1;\r
421             }\r
422         }\r
423         FWL_HLISTITEM hItem = m_pOwner->GetItemAtPoint(pMsg->m_fx, pMsg->m_fy);\r
424         if (hItem) {\r
425             _FWL_RETURN_VALUE_IF_FAIL(m_pOwner->m_pProperties->m_pDataProvider, 0);\r
426             IFWL_ListBoxDP *pData = (IFWL_ListBoxDP*)m_pOwner->m_pProperties->m_pDataProvider;\r
427             FX_INT32 iSel = pData->GetItemIndex(m_pOwner->m_pInterface, hItem);\r
428             CFWL_EvtCmbHoverChanged event;\r
429             event.m_pSrcTarget = m_pOwner->m_pOuter;\r
430             event.m_iCurHover = iSel;\r
431             m_pOwner->DispatchEvent(&event);\r
432             m_pOwner->ChangeSelected(iSel);\r
433         }\r
434     } else if (m_pOwner->m_bNotifyOwner) {\r
435         m_pOwner->ClientToOuter(pMsg->m_fx, pMsg->m_fy);\r
436         CFWL_ComboBoxImp *pOuter = (CFWL_ComboBoxImp*)(((IFWL_TargetData*)m_pOwner->m_pOuter)->GetData());\r
437         pOuter->m_pDelegate->OnProcessMessage(pMsg);\r
438     }\r
439     return 1;\r
440 }\r
441 FX_INT32 CFWL_ComboListDelegate::OnDropListLButtonDown(CFWL_MsgMouse *pMsg)\r
442 {\r
443     if (m_pOwner->m_rtClient.Contains(pMsg->m_fx, pMsg->m_fy)) {\r
444         return 0;\r
445     }\r
446     CFWL_ComboBoxImp *pOuter = (CFWL_ComboBoxImp*)((IFWL_TargetData*)m_pOwner->m_pOuter)->GetData();\r
447     pOuter->ShowDropList(FALSE);\r
448     return 1;\r
449 }\r
450 FX_INT32 CFWL_ComboListDelegate::OnDropListLButtonUp(CFWL_MsgMouse *pMsg)\r
451 {\r
452     CFWL_ComboBoxImp *pOuter = (CFWL_ComboBoxImp*)((IFWL_TargetData*)m_pOwner->m_pOuter)->GetData();\r
453     if (m_pOwner->m_bNotifyOwner) {\r
454         m_pOwner->ClientToOuter(pMsg->m_fx, pMsg->m_fy);\r
455         pOuter->m_pDelegate->OnProcessMessage(pMsg);\r
456     } else {\r
457         if (m_pOwner->IsShowScrollBar(TRUE) && m_pOwner->m_pVertScrollBar) {\r
458             CFX_RectF rect;\r
459             m_pOwner->m_pVertScrollBar->GetWidgetRect(rect);\r
460             if (rect.Contains(pMsg->m_fx, pMsg->m_fy)) {\r
461                 return 1;\r
462             }\r
463         }\r
464         pOuter->ShowDropList(FALSE);\r
465         FWL_HLISTITEM hItem = m_pOwner->GetItemAtPoint(pMsg->m_fx, pMsg->m_fy);\r
466         if (hItem) {\r
467             pOuter->ProcessSelChanged(TRUE);\r
468         }\r
469     }\r
470     return 1;\r
471 }\r
472 FX_INT32 CFWL_ComboListDelegate::OnDropListKey(CFWL_MsgKey *pKey)\r
473 {\r
474     CFWL_ComboBoxImp *pOuter = (CFWL_ComboBoxImp*)((IFWL_TargetData*)m_pOwner->m_pOuter)->GetData();\r
475     FX_BOOL bPropagate = FALSE;\r
476     if (pKey->m_dwCmd == FWL_MSGKEYCMD_KeyDown) {\r
477         FX_DWORD dwKeyCode = pKey->m_dwKeyCode;\r
478         switch (dwKeyCode) {\r
479             case FWL_VKEY_Return:\r
480             case FWL_VKEY_Escape: {\r
481                     pOuter->ShowDropList(FALSE);\r
482                     return 1;\r
483                 }\r
484             case FWL_VKEY_Up:\r
485             case FWL_VKEY_Down: {\r
486                     OnDropListKeyDown(pKey);\r
487                     IFWL_WidgetDelegate *pDelegate = pOuter->SetDelegate(NULL);\r
488                     pOuter->ProcessSelChanged(FALSE);\r
489                     return 1;\r
490                 }\r
491             default: {\r
492                     bPropagate = TRUE;\r
493                 }\r
494         }\r
495     } else if (pKey->m_dwCmd == FWL_MSGKEYCMD_Char) {\r
496         bPropagate = TRUE;\r
497     }\r
498     if (bPropagate) {\r
499         pKey->m_pDstTarget = (IFWL_Widget*)m_pOwner->m_pOuter;\r
500         pOuter->m_pDelegate->OnProcessMessage(pKey);\r
501         return 1;\r
502     }\r
503     return 0;\r
504 }\r
505 void CFWL_ComboListDelegate::OnDropListKeyDown(CFWL_MsgKey *pKey)\r
506 {\r
507     FX_DWORD dwKeyCode = pKey->m_dwKeyCode;\r
508     switch(dwKeyCode) {\r
509         case FWL_VKEY_Up:\r
510         case FWL_VKEY_Down:\r
511         case FWL_VKEY_Home:\r
512         case FWL_VKEY_End: {\r
513                 CFWL_ComboBoxImp *pOuter = (CFWL_ComboBoxImp*)((IFWL_TargetData*)m_pOwner->m_pOuter)->GetData();\r
514                 IFWL_ListBoxDP *pData = (IFWL_ListBoxDP*)m_pOwner->m_pProperties->m_pDataProvider;\r
515                 FWL_HLISTITEM hItem = pData->GetItem(m_pOwner->m_pInterface, pOuter->m_iCurSel);\r
516                 hItem = m_pOwner->GetItem(hItem, dwKeyCode);\r
517                 if (!hItem) {\r
518                     break;\r
519                 }\r
520                 m_pOwner->SetSelection(hItem, hItem, TRUE);\r
521                 m_pOwner->ScrollToVisible(hItem);\r
522                 CFX_RectF rtInvalidate;\r
523                 rtInvalidate.Set(0,\r
524                                  0,\r
525                                  m_pOwner->m_pProperties->m_rtWidget.width,\r
526                                  m_pOwner->m_pProperties->m_rtWidget.height);\r
527                 m_pOwner->Repaint(&rtInvalidate);\r
528                 break;\r
529             }\r
530         default: {\r
531             }\r
532     }\r
533 }\r
534 CFWL_ComboBoxImp::CFWL_ComboBoxImp(IFWL_Widget *pOuter )\r
535     : CFWL_WidgetImp(pOuter)\r
536     , m_pEdit(NULL)\r
537     , m_pListBox(NULL)\r
538     , m_pForm(NULL)\r
539     , m_bLButtonDown(FALSE)\r
540     , m_iCurSel(-1)\r
541     , m_iBtnState(FWL_PARTSTATE_CMB_Normal)\r
542     , m_fComboFormHandler(0)\r
543     , m_bNeedShowList(FALSE)\r
544 {\r
545     m_rtClient.Reset();\r
546     m_rtBtn.Reset();\r
547     m_rtHandler.Reset();\r
548 }\r
549 CFWL_ComboBoxImp::CFWL_ComboBoxImp(const CFWL_WidgetImpProperties &properties, IFWL_Widget *pOuter )\r
550     : CFWL_WidgetImp(properties, pOuter)\r
551     , m_pEdit(NULL)\r
552     , m_pListBox(NULL)\r
553     , m_pForm(NULL)\r
554     , m_bLButtonDown(FALSE)\r
555     , m_iCurSel(-1)\r
556     , m_iBtnState(FWL_PARTSTATE_CMB_Normal)\r
557     , m_fComboFormHandler(0)\r
558     , m_bNeedShowList(FALSE)\r
559 {\r
560     m_rtClient.Reset();\r
561     m_rtBtn.Reset();\r
562     m_rtHandler.Reset();\r
563 }\r
564 CFWL_ComboBoxImp::~CFWL_ComboBoxImp()\r
565 {\r
566     if (m_pEdit) {\r
567         m_pEdit->Release();\r
568         m_pEdit = NULL;\r
569     }\r
570     if (m_pListBox) {\r
571         m_pListBox->Release();\r
572         m_pListBox = NULL;\r
573     }\r
574 }\r
575 FWL_ERR CFWL_ComboBoxImp::GetClassName(CFX_WideString &wsClass) const\r
576 {\r
577     wsClass = FWL_CLASS_ComboBox;\r
578     return FWL_ERR_Succeeded;\r
579 }\r
580 FX_DWORD CFWL_ComboBoxImp::GetClassID() const\r
581 {\r
582     return FWL_CLASSHASH_ComboBox;\r
583 }\r
584 FWL_ERR CFWL_ComboBoxImp::Initialize()\r
585 {\r
586     if (m_pWidgetMgr->IsFormDisabled()) {\r
587         return DisForm_Initialize();\r
588     }\r
589     _FWL_ERR_CHECK_RETURN_VALUE_IF_FAIL(CFWL_WidgetImp::Initialize(), FWL_WGTSTATE_Invisible);\r
590     m_pDelegate = (IFWL_WidgetDelegate*)FX_NEW CFWL_ComboBoxImpDelegate(this);\r
591     CFWL_WidgetImpProperties prop;\r
592     prop.m_pThemeProvider = m_pProperties->m_pThemeProvider;\r
593     prop.m_dwStyles |= FWL_WGTSTYLE_Border | FWL_WGTSTYLE_VScroll;\r
594     if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_CMB_ListItemIconText) {\r
595         prop.m_dwStyleExes |= FWL_STYLEEXT_LTB_Icon;\r
596     }\r
597     prop.m_pDataProvider = m_pProperties->m_pDataProvider;\r
598     CFWL_ComboList *pList = FX_NEW CFWL_ComboList(prop, m_pInterface);\r
599     m_pListBox = IFWL_ListBox::Create();\r
600     pList->SetInterface(m_pListBox);\r
601     ((IFWL_TargetData*)m_pListBox)->SetData(pList);\r
602     pList->Initialize();\r
603     if ((m_pProperties->m_dwStyleExes & FWL_STYLEEXT_CMB_DropDown) && !m_pEdit) {\r
604         CFWL_ComboEdit *pEdit = FX_NEW CFWL_ComboEdit(m_pInterface);\r
605         m_pEdit = IFWL_Edit::Create();\r
606         pEdit->SetInterface(m_pEdit);\r
607         ((IFWL_TargetData*)m_pEdit)->SetData(pEdit);\r
608         pEdit->Initialize();\r
609         pEdit->SetOuter(m_pInterface);\r
610     }\r
611     if (m_pEdit) {\r
612         m_pEdit->SetParent(m_pInterface);\r
613     }\r
614     SetStates(m_pProperties->m_dwStates);\r
615     return FWL_ERR_Succeeded;\r
616 }\r
617 FWL_ERR CFWL_ComboBoxImp::Finalize()\r
618 {\r
619     if (m_pEdit) {\r
620         m_pEdit->Finalize();\r
621     }\r
622     m_pListBox->Finalize();\r
623     if ( m_pDelegate) {\r
624         delete (CFWL_ComboBoxImpDelegate*)m_pDelegate;\r
625         m_pDelegate = NULL;\r
626     }\r
627     return CFWL_WidgetImp::Finalize();\r
628 }\r
629 FWL_ERR CFWL_ComboBoxImp::GetWidgetRect(CFX_RectF &rect, FX_BOOL bAutoSize )\r
630 {\r
631     if (bAutoSize) {\r
632         rect.Reset();\r
633         FX_BOOL bIsDropDown = IsDropDownStyle();\r
634         if (bIsDropDown && m_pEdit) {\r
635             m_pEdit->GetWidgetRect(rect, TRUE);\r
636         } else {\r
637             rect.width = 100;\r
638             rect.height = 16;\r
639         }\r
640         if (!m_pProperties->m_pThemeProvider) {\r
641             ReSetTheme();\r
642         }\r
643         FX_FLOAT *pFWidth = (FX_FLOAT*)GetThemeCapacity(FWL_WGTCAPACITY_ScrollBarWidth);\r
644         _FWL_RETURN_VALUE_IF_FAIL(pFWidth, FWL_ERR_Indefinite);\r
645         rect.Inflate(0, 0, *pFWidth, 0);\r
646         CFWL_WidgetImp::GetWidgetRect(rect, TRUE);\r
647     } else {\r
648         rect = m_pProperties->m_rtWidget;\r
649     }\r
650     return FWL_ERR_Succeeded;\r
651 }\r
652 FWL_ERR CFWL_ComboBoxImp::ModifyStylesEx(FX_DWORD dwStylesExAdded, FX_DWORD dwStylesExRemoved)\r
653 {\r
654     if (m_pWidgetMgr->IsFormDisabled()) {\r
655         return DisForm_ModifyStylesEx(dwStylesExAdded, dwStylesExRemoved);\r
656     }\r
657     FX_BOOL bAddDropDown = dwStylesExAdded & FWL_STYLEEXT_CMB_DropDown;\r
658     FX_BOOL bRemoveDropDown = dwStylesExRemoved & FWL_STYLEEXT_CMB_DropDown;\r
659     if (bAddDropDown && !m_pEdit) {\r
660         CFWL_ComboEdit *pEdit = FX_NEW CFWL_ComboEdit(m_pInterface);\r
661         m_pEdit = IFWL_Edit::Create();\r
662         pEdit->SetInterface(m_pEdit);\r
663         ((IFWL_TargetData*)m_pEdit)->SetData(pEdit);\r
664         pEdit->Initialize();\r
665         pEdit->SetOuter(m_pInterface);\r
666         m_pEdit->SetParent(m_pInterface);\r
667     } else if (bRemoveDropDown && m_pEdit) {\r
668         m_pEdit->SetStates(FWL_WGTSTATE_Invisible, TRUE);\r
669     }\r
670     return CFWL_WidgetImp::ModifyStylesEx(dwStylesExAdded, dwStylesExRemoved);\r
671 }\r
672 FWL_ERR CFWL_ComboBoxImp::Update()\r
673 {\r
674     if (m_pWidgetMgr->IsFormDisabled()) {\r
675         return DisForm_Update();\r
676     }\r
677     if (IsLocked()) {\r
678         return FWL_ERR_Indefinite;\r
679     }\r
680     ReSetTheme();\r
681     FX_BOOL bDropDown = IsDropDownStyle();\r
682     if (bDropDown && m_pEdit) {\r
683         ReSetEditAlignment();\r
684     }\r
685     if (m_pProperties->m_pThemeProvider == NULL) {\r
686         m_pProperties->m_pThemeProvider = GetAvailableTheme();\r
687     }\r
688     Layout();\r
689     CFWL_ThemePart part;\r
690     part.m_pWidget = m_pInterface;\r
691     m_fComboFormHandler = *(FX_FLOAT *) m_pProperties->m_pThemeProvider->GetCapacity(&part, FWL_WGTCAPACITY_CMB_ComboFormHandler);\r
692     return FWL_ERR_Succeeded;\r
693 }\r
694 FX_DWORD CFWL_ComboBoxImp::HitTest(FX_FLOAT fx, FX_FLOAT fy)\r
695 {\r
696     if (m_pWidgetMgr->IsFormDisabled()) {\r
697         return DisForm_HitTest(fx, fy);\r
698     }\r
699     return CFWL_WidgetImp::HitTest(fx, fy);\r
700 }\r
701 FWL_ERR CFWL_ComboBoxImp::DrawWidget(CFX_Graphics *pGraphics, const CFX_Matrix *pMatrix )\r
702 {\r
703     if (m_pWidgetMgr->IsFormDisabled()) {\r
704         return DisForm_DrawWidget(pGraphics, pMatrix);\r
705     }\r
706     _FWL_RETURN_VALUE_IF_FAIL(pGraphics, FWL_ERR_Indefinite);\r
707     _FWL_RETURN_VALUE_IF_FAIL(m_pProperties->m_pThemeProvider, FWL_ERR_Indefinite);\r
708     IFWL_ThemeProvider *pTheme = m_pProperties->m_pThemeProvider;\r
709     FX_BOOL bIsDropDown = IsDropDownStyle();\r
710     if (HasBorder()) {\r
711         DrawBorder(pGraphics, FWL_PART_CMB_Border, pTheme, pMatrix);\r
712     }\r
713     if (HasEdge()) {\r
714         DrawEdge(pGraphics, FWL_PART_CMB_Edge, pTheme, pMatrix);\r
715     }\r
716     if (!bIsDropDown) {\r
717         CFX_RectF rtTextBk(m_rtClient);\r
718         rtTextBk.width -= m_rtBtn.width;\r
719         CFWL_ThemeBackground param;\r
720         param.m_pWidget = m_pInterface;\r
721         param.m_iPart = FWL_PART_CMB_Background;\r
722         param.m_pGraphics = pGraphics;\r
723         if (pMatrix) {\r
724             param.m_matrix.Concat(*pMatrix);\r
725         }\r
726         param.m_rtPart = rtTextBk;\r
727         if (m_iCurSel >= 0) {\r
728             IFWL_ListBoxDP* pData = (IFWL_ListBoxDP*)((CFWL_ComboList*)((IFWL_TargetData*)m_pListBox)->GetData())->m_pProperties->m_pDataProvider;\r
729             FX_LPVOID p = pData->GetItemData(m_pListBox, pData->GetItem(m_pListBox, m_iCurSel));\r
730             if (p != NULL) {\r
731                 param.m_pData = p;\r
732             }\r
733         }\r
734         if (m_pProperties->m_dwStates & FWL_WGTSTATE_Disabled) {\r
735             param.m_dwStates = FWL_PARTSTATE_CMB_Disabled;\r
736         } else if ((m_pProperties->m_dwStates & FWL_WGTSTATE_Focused) && (m_iCurSel >= 0)) {\r
737             param.m_dwStates = FWL_PARTSTATE_CMB_Selected;\r
738         } else {\r
739             param.m_dwStates = FWL_PARTSTATE_CMB_Normal;\r
740         }\r
741         pTheme->DrawBackground(&param);\r
742         if (m_iCurSel >= 0) {\r
743             _FWL_RETURN_VALUE_IF_FAIL(m_pListBox, FWL_ERR_Indefinite);\r
744             CFX_WideString wsText;\r
745             IFWL_ComboBoxDP *pData = (IFWL_ComboBoxDP *)m_pProperties->m_pDataProvider;\r
746             FWL_HLISTITEM hItem = pData->GetItem(m_pInterface, m_iCurSel);\r
747             ((CFWL_ComboList*)((IFWL_TargetData*)m_pListBox)->GetData())->GetItemText(hItem, wsText);\r
748             CFWL_ThemeText param;\r
749             param.m_pWidget = m_pInterface;\r
750             param.m_iPart = FWL_PART_CMB_Caption;\r
751             param.m_dwStates = m_iBtnState;\r
752             param.m_pGraphics = pGraphics;\r
753             param.m_matrix.Concat(*pMatrix);\r
754             param.m_rtPart = rtTextBk;\r
755             param.m_dwStates = (m_pProperties->m_dwStates & FWL_WGTSTATE_Focused) ? FWL_PARTSTATE_CMB_Selected : FWL_PARTSTATE_CMB_Normal;\r
756             param.m_wsText = wsText;\r
757             param.m_dwTTOStyles = FDE_TTOSTYLE_SingleLine;\r
758             param.m_iTTOAlign = FDE_TTOALIGNMENT_CenterLeft;\r
759             pTheme->DrawText(&param);\r
760         }\r
761     }\r
762     {\r
763         CFWL_ThemeBackground param;\r
764         param.m_pWidget = m_pInterface;\r
765         param.m_iPart = FWL_PART_CMB_DropDownButton;\r
766         param.m_dwStates = (m_pProperties->m_dwStates & FWL_WGTSTATE_Disabled) ? FWL_PARTSTATE_CMB_Disabled : m_iBtnState;\r
767         param.m_pGraphics = pGraphics;\r
768         param.m_matrix.Concat(*pMatrix);\r
769         param.m_rtPart = m_rtBtn;\r
770         pTheme->DrawBackground(&param);\r
771     }\r
772     return FWL_ERR_Succeeded;\r
773 }\r
774 FWL_ERR CFWL_ComboBoxImp::SetThemeProvider(IFWL_ThemeProvider *pThemeProvider)\r
775 {\r
776     _FWL_RETURN_VALUE_IF_FAIL(pThemeProvider, FWL_ERR_Indefinite);\r
777     m_pProperties->m_pThemeProvider = pThemeProvider;\r
778     if (m_pListBox && pThemeProvider->IsValidWidget(m_pListBox)) {\r
779         m_pListBox->SetThemeProvider(pThemeProvider);\r
780     }\r
781     if (m_pEdit && pThemeProvider->IsValidWidget(m_pEdit)) {\r
782         m_pEdit->SetThemeProvider(pThemeProvider);\r
783     }\r
784     return FWL_ERR_Succeeded;\r
785 }\r
786 FX_INT32 CFWL_ComboBoxImp::GetCurSel()\r
787 {\r
788     return m_iCurSel;\r
789 }\r
790 FWL_ERR CFWL_ComboBoxImp::SetCurSel(FX_INT32 iSel)\r
791 {\r
792     FX_INT32 iCount = ((CFWL_ComboList*)((IFWL_TargetData*)m_pListBox)->GetData())->CountItems();\r
793     FX_BOOL bClearSel = iSel < 0 || iSel >= iCount;\r
794     FX_BOOL bDropDown = IsDropDownStyle();\r
795     if (bDropDown && m_pEdit) {\r
796         if (bClearSel) {\r
797             m_pEdit->SetText(CFX_WideString());\r
798         } else {\r
799             CFX_WideString wsText;\r
800             IFWL_ComboBoxDP *pData = (IFWL_ComboBoxDP *)m_pProperties->m_pDataProvider;\r
801             FWL_HLISTITEM hItem = pData->GetItem(m_pInterface, iSel);\r
802             ((CFWL_ComboList*)((IFWL_TargetData*)m_pListBox)->GetData())->GetItemText(hItem, wsText);\r
803             m_pEdit->SetText(wsText);\r
804         }\r
805         m_pEdit->Update();\r
806     }\r
807     m_iCurSel = bClearSel ? -1 : iSel;\r
808     return FWL_ERR_Succeeded;\r
809 }\r
810 FWL_ERR CFWL_ComboBoxImp::SetStates(FX_DWORD dwStates, FX_BOOL bSet )\r
811 {\r
812     FX_BOOL bIsDropDown = IsDropDownStyle();\r
813     if (bIsDropDown && m_pEdit) {\r
814         m_pEdit->SetStates(dwStates, bSet);\r
815     }\r
816     if (m_pListBox) {\r
817         m_pListBox->SetStates(dwStates, bSet);\r
818     }\r
819     return CFWL_WidgetImp::SetStates(dwStates, bSet);\r
820 }\r
821 FWL_ERR CFWL_ComboBoxImp::SetEditText(const CFX_WideString &wsText)\r
822 {\r
823     _FWL_RETURN_VALUE_IF_FAIL(m_pEdit, FWL_ERR_Indefinite);\r
824     m_pEdit->SetText(wsText);\r
825     return m_pEdit->Update();\r
826 }\r
827 FX_INT32 CFWL_ComboBoxImp::GetEditTextLength() const\r
828 {\r
829     _FWL_RETURN_VALUE_IF_FAIL(m_pEdit, -1);\r
830     return m_pEdit->GetTextLength();\r
831 }\r
832 FWL_ERR CFWL_ComboBoxImp::GetEditText(CFX_WideString &wsText, FX_INT32 nStart , FX_INT32 nCount ) const\r
833 {\r
834     if (m_pEdit) {\r
835         return m_pEdit->GetText(wsText, nStart, nCount);\r
836     } else if (m_pListBox) {\r
837         IFWL_ComboBoxDP *pData = (IFWL_ComboBoxDP *)m_pProperties->m_pDataProvider;\r
838         FWL_HLISTITEM hItem = pData->GetItem(m_pInterface, m_iCurSel);\r
839         return m_pListBox->GetItemText(hItem, wsText);\r
840     }\r
841     return FWL_ERR_Indefinite;\r
842 }\r
843 FWL_ERR CFWL_ComboBoxImp::SetEditSelRange(FX_INT32 nStart, FX_INT32 nCount )\r
844 {\r
845     _FWL_RETURN_VALUE_IF_FAIL(m_pEdit, FWL_ERR_Indefinite);\r
846     ((CFWL_ComboEdit*)((IFWL_TargetData*)m_pEdit)->GetData())->ClearSelected();\r
847     m_pEdit->AddSelRange(nStart, nCount);\r
848     return FWL_ERR_Succeeded;\r
849 }\r
850 FX_INT32 CFWL_ComboBoxImp::GetEditSelRange(FX_INT32 nIndex, FX_INT32 &nStart)\r
851 {\r
852     _FWL_RETURN_VALUE_IF_FAIL(m_pEdit, -1);\r
853     return m_pEdit->GetSelRange(nIndex, nStart);\r
854 }\r
855 FX_INT32 CFWL_ComboBoxImp::GetEditLimit()\r
856 {\r
857     _FWL_RETURN_VALUE_IF_FAIL(m_pEdit, -1);\r
858     return m_pEdit->GetLimit();\r
859 }\r
860 FWL_ERR CFWL_ComboBoxImp::SetEditLimit(FX_INT32 nLimit)\r
861 {\r
862     _FWL_RETURN_VALUE_IF_FAIL(m_pEdit, FWL_ERR_Indefinite);\r
863     return m_pEdit->SetLimit(nLimit);\r
864 }\r
865 FWL_ERR CFWL_ComboBoxImp::EditDoClipboard(FX_INT32 iCmd)\r
866 {\r
867     _FWL_RETURN_VALUE_IF_FAIL(m_pEdit, FWL_ERR_Indefinite);\r
868     return m_pEdit->DoClipboard(iCmd);\r
869 }\r
870 FX_BOOL CFWL_ComboBoxImp::EditRedo(FX_BSTR bsRecord)\r
871 {\r
872     _FWL_RETURN_VALUE_IF_FAIL(m_pEdit, FALSE);\r
873     return m_pEdit->Redo(bsRecord);\r
874 }\r
875 FX_BOOL CFWL_ComboBoxImp::EditUndo(FX_BSTR bsRecord)\r
876 {\r
877     _FWL_RETURN_VALUE_IF_FAIL(m_pEdit, FALSE);\r
878     return m_pEdit->Undo(bsRecord);\r
879 }\r
880 IFWL_ListBox* CFWL_ComboBoxImp::GetListBoxt()\r
881 {\r
882     _FWL_RETURN_VALUE_IF_FAIL(m_pListBox, FALSE);\r
883     return m_pListBox;\r
884 }\r
885 FX_BOOL CFWL_ComboBoxImp::AfterFocusShowDropList()\r
886 {\r
887     if (!m_bNeedShowList) {\r
888         return FALSE;\r
889     }\r
890     if (m_pEdit) {\r
891         MatchEditText();\r
892     }\r
893     ShowDropList(TRUE);\r
894     m_bNeedShowList = FALSE;\r
895     return TRUE;\r
896 }\r
897 FX_ERR CFWL_ComboBoxImp::OpenDropDownList(FX_BOOL bActivate)\r
898 {\r
899     ShowDropList(bActivate);\r
900     return FWL_ERR_Succeeded;\r
901 }\r
902 FX_BOOL CFWL_ComboBoxImp::EditCanUndo()\r
903 {\r
904     return m_pEdit->CanUndo();\r
905 }\r
906 FX_BOOL CFWL_ComboBoxImp::EditCanRedo()\r
907 {\r
908     return m_pEdit->CanRedo();\r
909 }\r
910 FX_BOOL CFWL_ComboBoxImp::EditUndo()\r
911 {\r
912     return m_pEdit->Undo();\r
913 }\r
914 FX_BOOL CFWL_ComboBoxImp::EditRedo()\r
915 {\r
916     return m_pEdit->Redo();\r
917 }\r
918 FX_BOOL CFWL_ComboBoxImp::EditCanCopy()\r
919 {\r
920     return m_pEdit->CountSelRanges() > 0;\r
921 }\r
922 FX_BOOL CFWL_ComboBoxImp::EditCanCut()\r
923 {\r
924     if (m_pEdit->GetStylesEx() & FWL_STYLEEXT_EDT_ReadOnly) {\r
925         return FALSE;\r
926     }\r
927     return m_pEdit->CountSelRanges() > 0;\r
928 }\r
929 FX_BOOL CFWL_ComboBoxImp::EditCanSelectAll()\r
930 {\r
931     return m_pEdit->GetTextLength() > 0;\r
932 }\r
933 FX_BOOL CFWL_ComboBoxImp::EditCopy(CFX_WideString &wsCopy)\r
934 {\r
935     return m_pEdit->Copy(wsCopy);\r
936 }\r
937 FX_BOOL CFWL_ComboBoxImp::EditCut(CFX_WideString &wsCut)\r
938 {\r
939     return m_pEdit->Cut(wsCut);\r
940 }\r
941 FX_BOOL CFWL_ComboBoxImp::EditPaste(const CFX_WideString &wsPaste)\r
942 {\r
943     return m_pEdit->Paste(wsPaste);\r
944 }\r
945 FX_BOOL CFWL_ComboBoxImp::EditSelectAll()\r
946 {\r
947     return (m_pEdit->AddSelRange(0) == FWL_ERR_Succeeded) ? TRUE : FALSE;\r
948 }\r
949 FX_BOOL CFWL_ComboBoxImp::EditDelete()\r
950 {\r
951     return (m_pEdit->ClearText() == FWL_ERR_Succeeded) ? TRUE : FALSE;\r
952 }\r
953 FX_BOOL CFWL_ComboBoxImp::EditDeSelect()\r
954 {\r
955     return (m_pEdit->ClearSelections() == FWL_ERR_Succeeded) ? TRUE : FALSE;\r
956 }\r
957 FWL_ERR CFWL_ComboBoxImp::GetBBox(CFX_RectF &rect)\r
958 {\r
959     if (m_pWidgetMgr->IsFormDisabled()) {\r
960         return DisForm_GetBBox(rect);\r
961     }\r
962     rect = m_pProperties->m_rtWidget;\r
963     if (m_pListBox && IsDropListShowed()) {\r
964         CFX_RectF rtList;\r
965         m_pListBox->GetWidgetRect(rtList);\r
966         rtList.Offset(rect.left, rect.top);\r
967         rect.Union(rtList);\r
968     }\r
969     return FWL_ERR_Succeeded;\r
970 }\r
971 FWL_ERR CFWL_ComboBoxImp::EditModifyStylesEx(FX_DWORD dwStylesExAdded,\r
972         FX_DWORD dwStylesExRemoved)\r
973 {\r
974     if (m_pEdit != NULL) {\r
975         return m_pEdit->ModifyStylesEx(dwStylesExAdded, dwStylesExRemoved);\r
976     } else {\r
977         return FWL_ERR_Parameter_Invalid;\r
978     }\r
979 }\r
980 FX_FLOAT CFWL_ComboBoxImp::GetListHeight()\r
981 {\r
982     return ((IFWL_ComboBoxDP*)m_pProperties->m_pDataProvider)->GetListHeight(m_pInterface);\r
983 }\r
984 void CFWL_ComboBoxImp::DrawStretchHandler(CFX_Graphics *pGraphics, const CFX_Matrix *pMatrix)\r
985 {\r
986     CFWL_ThemeBackground param;\r
987     param.m_pGraphics = pGraphics;\r
988     param.m_iPart =     FWL_PART_CMB_StretcgHandler;\r
989     param.m_dwStates = FWL_PARTSTATE_CMB_Normal;\r
990     param.m_pWidget = m_pInterface;\r
991     if (pMatrix) {\r
992         param.m_matrix.Concat(*pMatrix);\r
993     }\r
994     param.m_rtPart = m_rtHandler;\r
995     m_pProperties->m_pThemeProvider->DrawBackground(&param);\r
996 }\r
997 void CFWL_ComboBoxImp::ShowDropList(FX_BOOL bActivate)\r
998 {\r
999     if (m_pWidgetMgr->IsFormDisabled()) {\r
1000         return DisForm_ShowDropList(bActivate);\r
1001     }\r
1002     FX_BOOL bDropList = IsDropListShowed();\r
1003     if(bDropList == bActivate) {\r
1004         return;\r
1005     }\r
1006     if (!m_pForm) {\r
1007         InitProxyForm();\r
1008     }\r
1009     m_pListProxyDelegate->Reset();\r
1010     if (bActivate) {\r
1011         ((CFWL_ComboList*)((IFWL_TargetData*)m_pListBox)->GetData())->ChangeSelected(m_iCurSel);\r
1012         ReSetListItemAlignment();\r
1013         FX_DWORD dwStyleAdd = m_pProperties->m_dwStyleExes & (FWL_STYLEEXT_CMB_Sort | FWL_STYLEEXT_CMB_OwnerDraw);\r
1014         m_pListBox->ModifyStylesEx(dwStyleAdd, 0);\r
1015         m_pListBox->GetWidgetRect(m_rtList, TRUE);\r
1016         FX_FLOAT fHeight = GetListHeight();\r
1017         if (fHeight > 0) {\r
1018             if (m_rtList.height > GetListHeight()) {\r
1019                 m_rtList.height = GetListHeight();\r
1020                 m_pListBox->ModifyStyles(FWL_WGTSTYLE_VScroll, 0);\r
1021             }\r
1022         }\r
1023         CFX_RectF rtAnchor;\r
1024         rtAnchor.Set(0,\r
1025                      0,\r
1026                      m_pProperties->m_rtWidget.width,\r
1027                      m_pProperties->m_rtWidget.height);\r
1028         FX_FLOAT fMinHeight = 0;\r
1029         FX_FLOAT fMaxHeight = m_rtList.height;\r
1030         if (m_rtList.width < m_rtClient.width) {\r
1031             m_rtList.width = m_rtClient.width;\r
1032         }\r
1033         m_rtProxy = m_rtList;\r
1034         if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_CMB_ListDrag) {\r
1035             m_rtProxy.height += m_fComboFormHandler;\r
1036         }\r
1037         GetPopupPos(fMinHeight, m_rtProxy.height, rtAnchor, m_rtProxy);\r
1038         if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_CMB_ListDrag) {\r
1039             FX_FLOAT fx = 0;\r
1040             FX_FLOAT fy = m_rtClient.top + m_rtClient.height / 2;\r
1041             TransformTo(NULL, fx, fy);\r
1042             m_bUpFormHandler = fy > m_rtProxy.top;\r
1043             if (m_bUpFormHandler) {\r
1044                 m_rtHandler.Set(0, 0, m_rtList.width, m_fComboFormHandler);\r
1045                 m_rtList.top = m_fComboFormHandler;\r
1046             } else {\r
1047                 m_rtHandler.Set(0, m_rtList.height, m_rtList.width, m_fComboFormHandler);\r
1048             }\r
1049         }\r
1050         m_pForm->SetWidgetRect(m_rtProxy);\r
1051         m_pForm->Update();\r
1052         m_pListBox->SetWidgetRect(m_rtList);\r
1053         m_pListBox->Update();\r
1054         CFWL_EvtCmbPreDropDown ev;\r
1055         ev.m_pSrcTarget = m_pInterface;\r
1056         DispatchEvent(&ev);\r
1057         m_fItemHeight = ((CFWL_ComboList*)((IFWL_TargetData*)m_pListBox)->GetData())->m_fItemHeight;\r
1058         ((CFWL_ComboList*)((IFWL_TargetData*)m_pListBox)->GetData())->SetFocus(TRUE);\r
1059         m_pForm->DoModal();\r
1060         ((CFWL_ComboList*)((IFWL_TargetData*)m_pListBox)->GetData())->SetFocus(FALSE);\r
1061     } else {\r
1062         m_pForm->EndDoModal();\r
1063         CFWL_EvtCmbCloseUp ev;\r
1064         ev.m_pSrcTarget = m_pInterface;\r
1065         DispatchEvent(&ev);\r
1066         m_bLButtonDown = FALSE;\r
1067         ((CFWL_ComboList*)((IFWL_TargetData*)m_pListBox)->GetData())->m_bNotifyOwner = TRUE;\r
1068         SetFocus(TRUE);\r
1069     }\r
1070 }\r
1071 FX_BOOL CFWL_ComboBoxImp::IsDropListShowed()\r
1072 {\r
1073     return m_pForm && !(m_pForm->GetStates() & FWL_WGTSTATE_Invisible);\r
1074 }\r
1075 FX_BOOL CFWL_ComboBoxImp::IsDropDownStyle() const\r
1076 {\r
1077     return m_pProperties->m_dwStyleExes & FWL_STYLEEXT_CMB_DropDown;\r
1078 }\r
1079 void CFWL_ComboBoxImp::MatchEditText()\r
1080 {\r
1081     CFX_WideString wsText;\r
1082     m_pEdit->GetText(wsText);\r
1083     FX_INT32 iMatch = ((CFWL_ComboList*)((IFWL_TargetData*)m_pListBox)->GetData())->MatchItem(wsText);\r
1084     if (iMatch != m_iCurSel) {\r
1085         ((CFWL_ComboList*)((IFWL_TargetData*)m_pListBox)->GetData())->ChangeSelected(iMatch);\r
1086         if (iMatch >= 0) {\r
1087             SynchrEditText(iMatch);\r
1088         }\r
1089     } else if (iMatch >= 0) {\r
1090         ((CFWL_ComboEdit*)((IFWL_TargetData*)m_pEdit)->GetData())->SetSelected();\r
1091     }\r
1092     m_iCurSel = iMatch;\r
1093 }\r
1094 void CFWL_ComboBoxImp::SynchrEditText(FX_INT32 iListItem)\r
1095 {\r
1096     CFX_WideString wsText;\r
1097     IFWL_ComboBoxDP *pData = (IFWL_ComboBoxDP *)m_pProperties->m_pDataProvider;\r
1098     FWL_HLISTITEM hItem = pData->GetItem(m_pInterface, iListItem);\r
1099     ((CFWL_ComboList*)((IFWL_TargetData*)m_pListBox)->GetData())->GetItemText(hItem, wsText);\r
1100     m_pEdit->SetText(wsText);\r
1101     m_pEdit->Update();\r
1102     ((CFWL_ComboEdit*)((IFWL_TargetData*)m_pEdit)->GetData())->SetSelected();\r
1103 }\r
1104 void CFWL_ComboBoxImp::Layout()\r
1105 {\r
1106     if (m_pWidgetMgr->IsFormDisabled()) {\r
1107         return DisForm_Layout();\r
1108     }\r
1109     GetClientRect(m_rtClient);\r
1110     FX_FLOAT *pFWidth = (FX_FLOAT*)GetThemeCapacity(FWL_WGTCAPACITY_ScrollBarWidth);\r
1111     _FWL_RETURN_IF_FAIL(pFWidth);\r
1112     FX_FLOAT fBtn = *pFWidth;\r
1113     m_rtBtn.Set(m_rtClient.right() - fBtn, m_rtClient.top, fBtn, m_rtClient.height);\r
1114     FX_BOOL bIsDropDown = IsDropDownStyle();\r
1115     if (bIsDropDown && m_pEdit) {\r
1116         CFX_RectF rtEdit;\r
1117         rtEdit.Set(m_rtClient.left, m_rtClient.top, m_rtClient.width - fBtn, m_rtClient.height);\r
1118         m_pEdit->SetWidgetRect(rtEdit);\r
1119         if (m_iCurSel >= 0) {\r
1120             CFX_WideString wsText;\r
1121             IFWL_ComboBoxDP *pData = (IFWL_ComboBoxDP *)m_pProperties->m_pDataProvider;\r
1122             FWL_HLISTITEM hItem = pData->GetItem(m_pInterface, m_iCurSel);\r
1123             ((CFWL_ComboList*)((IFWL_TargetData*)m_pListBox)->GetData())->GetItemText(hItem, wsText);\r
1124             m_pEdit->LockUpdate();\r
1125             m_pEdit->SetText(wsText);\r
1126             m_pEdit->UnlockUpdate();\r
1127         }\r
1128         m_pEdit->Update();\r
1129     }\r
1130 }\r
1131 void CFWL_ComboBoxImp::ReSetTheme()\r
1132 {\r
1133     IFWL_ThemeProvider *pTheme = m_pProperties->m_pThemeProvider;\r
1134     if (!pTheme) {\r
1135         pTheme = GetAvailableTheme();\r
1136         m_pProperties->m_pThemeProvider = pTheme;\r
1137     }\r
1138     if (m_pListBox) {\r
1139         if (!m_pListBox->GetThemeProvider() && pTheme->IsValidWidget(m_pListBox)) {\r
1140             m_pListBox->SetThemeProvider(pTheme);\r
1141         }\r
1142     }\r
1143     if (m_pEdit) {\r
1144         if (!m_pEdit->GetThemeProvider() && pTheme->IsValidWidget(m_pEdit)) {\r
1145             m_pEdit->SetThemeProvider(pTheme);\r
1146         }\r
1147     }\r
1148 }\r
1149 void CFWL_ComboBoxImp::ReSetEditAlignment()\r
1150 {\r
1151     _FWL_RETURN_IF_FAIL(m_pEdit);\r
1152     FX_DWORD dwStylExes = m_pProperties->m_dwStyleExes;\r
1153     FX_DWORD dwAdd = 0;\r
1154     switch (dwStylExes & FWL_STYLEEXT_CMB_EditHAlignMask) {\r
1155         case FWL_STYLEEXT_CMB_EditHCenter: {\r
1156                 dwAdd |= FWL_STYLEEXT_EDT_HCenter;\r
1157                 break;\r
1158             }\r
1159         case FWL_STYLEEXT_CMB_EditHFar: {\r
1160                 dwAdd |= FWL_STYLEEXT_EDT_HFar;\r
1161                 break;\r
1162             }\r
1163         default: {\r
1164                 dwAdd |= FWL_STYLEEXT_EDT_HNear;\r
1165             }\r
1166     }\r
1167     switch (dwStylExes & FWL_STYLEEXT_CMB_EditVAlignMask) {\r
1168         case FWL_STYLEEXT_CMB_EditVCenter: {\r
1169                 dwAdd |= FWL_STYLEEXT_EDT_VCenter;\r
1170                 break;\r
1171             }\r
1172         case FWL_STYLEEXT_CMB_EditVFar: {\r
1173                 dwAdd |= FWL_STYLEEXT_EDT_VFar;\r
1174                 break;\r
1175             }\r
1176         default: {\r
1177                 dwAdd |= FWL_STYLEEXT_EDT_VNear;\r
1178             }\r
1179     }\r
1180     if (dwStylExes & FWL_STYLEEXT_CMB_EditJustified) {\r
1181         dwAdd |= FWL_STYLEEXT_EDT_Justified;\r
1182     }\r
1183     if (dwStylExes & FWL_STYLEEXT_CMB_EditDistributed) {\r
1184         dwAdd |= FWL_STYLEEXT_EDT_Distributed;\r
1185     }\r
1186     m_pEdit->ModifyStylesEx(dwAdd, FWL_STYLEEXT_EDT_HAlignMask |\r
1187                             FWL_STYLEEXT_EDT_HAlignModeMask |\r
1188                             FWL_STYLEEXT_EDT_VAlignMask);\r
1189 }\r
1190 void CFWL_ComboBoxImp::ReSetListItemAlignment()\r
1191 {\r
1192     _FWL_RETURN_IF_FAIL(m_pListBox);\r
1193     FX_DWORD dwStylExes = m_pProperties->m_dwStyleExes;\r
1194     FX_DWORD dwAdd = 0;\r
1195     switch (dwStylExes & FWL_STYLEEXT_CMB_ListItemAlignMask) {\r
1196         case FWL_STYLEEXT_CMB_ListItemCenterAlign: {\r
1197                 dwAdd |= FWL_STYLEEXT_LTB_CenterAlign;\r
1198             }\r
1199         case FWL_STYLEEXT_CMB_ListItemRightAlign: {\r
1200                 dwAdd |= FWL_STYLEEXT_LTB_RightAlign;\r
1201             }\r
1202         default: {\r
1203                 dwAdd |= FWL_STYLEEXT_LTB_LeftAlign;\r
1204             }\r
1205     }\r
1206     m_pListBox->ModifyStylesEx(dwAdd, FWL_STYLEEXT_CMB_ListItemAlignMask);\r
1207 }\r
1208 void CFWL_ComboBoxImp::ProcessSelChanged(FX_BOOL bLButtonUp)\r
1209 {\r
1210     IFWL_ComboBoxDP *pDatas = (IFWL_ComboBoxDP*)m_pProperties->m_pDataProvider;\r
1211     m_iCurSel = pDatas->GetItemIndex(m_pInterface, m_pListBox->GetSelItem(0));\r
1212     FX_BOOL bDropDown = IsDropDownStyle();\r
1213     if (bDropDown) {\r
1214         IFWL_ComboBoxDP *pData = (IFWL_ComboBoxDP*)m_pProperties->m_pDataProvider;\r
1215         FWL_HLISTITEM hItem = pData->GetItem(m_pInterface, m_iCurSel);\r
1216         if (hItem) {\r
1217             CFX_WideString wsText;\r
1218             pData->GetItemText(m_pInterface, hItem, wsText);\r
1219             if (m_pEdit) {\r
1220                 m_pEdit->SetText(wsText);\r
1221                 m_pEdit->Update();\r
1222                 ((CFWL_ComboEdit*)((IFWL_TargetData*)m_pEdit)->GetData())->SetSelected();\r
1223             }\r
1224             CFWL_EvtCmbSelChanged ev;\r
1225             ev.bLButtonUp = bLButtonUp;\r
1226             ev.m_pSrcTarget = m_pInterface;\r
1227             ev.iArraySels.Add(m_iCurSel);\r
1228             DispatchEvent(&ev);\r
1229         }\r
1230     } else {\r
1231         Repaint(&m_rtClient);\r
1232     }\r
1233 }\r
1234 void CFWL_ComboBoxImp::InitProxyForm()\r
1235 {\r
1236     _FWL_RETURN_IF_FAIL(!m_pForm);\r
1237     _FWL_RETURN_IF_FAIL(m_pListBox);\r
1238     CFWL_WidgetImpProperties propForm;\r
1239     propForm.m_pOwner = m_pInterface;\r
1240     propForm.m_dwStyles = FWL_WGTSTYLE_Popup;\r
1241     propForm.m_dwStates = FWL_WGTSTATE_Invisible;\r
1242     m_pProxy = FX_NEW CFWL_FormProxyImp(propForm, m_pListBox);\r
1243     m_pForm = IFWL_Form::Create();\r
1244     m_pProxy->SetInterface(m_pForm);\r
1245     ((IFWL_TargetData*)m_pForm)->SetData(m_pProxy);\r
1246     m_pProxy->Initialize();\r
1247     m_pListBox->SetParent((IFWL_Widget*)m_pForm);\r
1248     m_pListProxyDelegate = FX_NEW CFWL_ComboProxyImpDelegate(m_pForm, this);\r
1249     m_pProxy->SetDelegate((IFWL_WidgetDelegate*)m_pListProxyDelegate);\r
1250 }\r
1251 FWL_ERR CFWL_ComboBoxImp::DisForm_Initialize()\r
1252 {\r
1253     _FWL_ERR_CHECK_RETURN_VALUE_IF_FAIL(CFWL_WidgetImp::Initialize(), FWL_WGTSTATE_Invisible);\r
1254     m_pDelegate = (IFWL_WidgetDelegate*)FX_NEW CFWL_ComboBoxImpDelegate(this);\r
1255     DisForm_InitComboList();\r
1256     DisForm_InitComboEdit();\r
1257     return FWL_ERR_Succeeded;\r
1258 }\r
1259 void CFWL_ComboBoxImp::DisForm_InitComboList()\r
1260 {\r
1261     if (m_pListBox) {\r
1262         return;\r
1263     }\r
1264     CFWL_WidgetImpProperties prop;\r
1265     prop.m_pParent = (IFWL_Widget*)this->m_pInterface;\r
1266     prop.m_dwStyles = FWL_WGTSTYLE_Border | FWL_WGTSTYLE_VScroll;\r
1267     prop.m_dwStates = FWL_WGTSTATE_Invisible;\r
1268     prop.m_pDataProvider = m_pProperties->m_pDataProvider;\r
1269     prop.m_pThemeProvider = m_pProperties->m_pThemeProvider;\r
1270     CFWL_ComboList *pList = FX_NEW CFWL_ComboList(prop, m_pInterface);\r
1271     m_pListBox = IFWL_ListBox::Create();\r
1272     pList->SetInterface(m_pListBox);\r
1273     ((IFWL_TargetData*)m_pListBox)->SetData(pList);\r
1274     pList->Initialize();\r
1275 }\r
1276 void CFWL_ComboBoxImp::DisForm_InitComboEdit()\r
1277 {\r
1278     if (m_pEdit) {\r
1279         return;\r
1280     }\r
1281     CFWL_WidgetImpProperties prop;\r
1282     prop.m_pParent = (IFWL_Widget*)this->m_pInterface;\r
1283     prop.m_pThemeProvider = m_pProperties->m_pThemeProvider;\r
1284     if ((m_pProperties->m_dwStyleExes & FWL_STYLEEXT_CMB_DropDown) == 0) {\r
1285     }\r
1286     CFWL_ComboEdit *pEdit = FX_NEW CFWL_ComboEdit(prop, m_pInterface);\r
1287     m_pEdit = IFWL_Edit::Create();\r
1288     pEdit->SetInterface(m_pEdit);\r
1289     ((IFWL_TargetData*)m_pEdit)->SetData(pEdit);\r
1290     pEdit->Initialize();\r
1291     pEdit->SetOuter(m_pInterface);\r
1292 }\r
1293 void CFWL_ComboBoxImp::DisForm_ShowDropList(FX_BOOL bActivate)\r
1294 {\r
1295     FX_BOOL bDropList = DisForm_IsDropListShowed();\r
1296     if(bDropList == bActivate) {\r
1297         return;\r
1298     }\r
1299     if (bActivate) {\r
1300         CFWL_EvtCmbPreDropDown preEvent;\r
1301         preEvent.m_pSrcTarget = m_pInterface;\r
1302         DispatchEvent(&preEvent);\r
1303         CFWL_ComboList* pComboList = (CFWL_ComboList*)(((IFWL_TargetData*)m_pListBox)->GetData());\r
1304         FX_INT32 iItems = pComboList->CountItems();\r
1305         if (iItems < 1) {\r
1306             return;\r
1307         }\r
1308         ReSetListItemAlignment();\r
1309         pComboList->ChangeSelected(m_iCurSel);\r
1310         FX_FLOAT fItemHeight = pComboList->GetItemHeigt();\r
1311         FX_FLOAT fBorder = GetBorderSize();\r
1312         FX_DWORD nWhere = 0;\r
1313         FX_FLOAT fPopupRet = 0.0f;\r
1314         FX_FLOAT fPopupMin = 0.0f;\r
1315         if (iItems > 3) {\r
1316             fPopupMin = fItemHeight * 3 + fBorder * 2;\r
1317         }\r
1318         FX_FLOAT fPopupMax = fItemHeight * iItems + fBorder * 2;\r
1319         CFX_RectF rtList;\r
1320         rtList.left = m_rtClient.left;\r
1321         rtList.width = m_pProperties->m_rtWidget.width;\r
1322         rtList.top = 0;\r
1323         rtList.height = 0;\r
1324         GetPopupPos(fPopupMin, fPopupMax, m_pProperties->m_rtWidget, rtList);\r
1325         m_pListBox->SetWidgetRect(rtList);\r
1326         m_pListBox->Update();\r
1327     } else {\r
1328         SetFocus(TRUE);\r
1329     }\r
1330     m_pListBox->SetStates(FWL_WGTSTATE_Invisible, !bActivate);\r
1331     if (bActivate) {\r
1332         CFWL_EvtCmbPostDropDown postEvent;\r
1333         postEvent.m_pSrcTarget = m_pInterface;\r
1334         DispatchEvent(&postEvent);\r
1335     }\r
1336     CFX_RectF rect;\r
1337     m_pListBox->GetWidgetRect(rect);\r
1338     rect.Inflate(2, 2);\r
1339     Repaint(&rect);\r
1340 }\r
1341 FX_BOOL CFWL_ComboBoxImp::DisForm_IsDropListShowed()\r
1342 {\r
1343     return !(m_pListBox->GetStates() & FWL_WGTSTATE_Invisible);\r
1344 }\r
1345 FWL_ERR CFWL_ComboBoxImp::DisForm_ModifyStylesEx(FX_DWORD dwStylesExAdded, FX_DWORD dwStylesExRemoved)\r
1346 {\r
1347     if (!m_pEdit) {\r
1348         DisForm_InitComboEdit();\r
1349     }\r
1350     FX_BOOL bAddDropDown = dwStylesExAdded & FWL_STYLEEXT_CMB_DropDown;\r
1351     FX_BOOL bDelDropDown = dwStylesExRemoved & FWL_STYLEEXT_CMB_DropDown;\r
1352     dwStylesExRemoved &= ~FWL_STYLEEXT_CMB_DropDown;\r
1353     m_pProperties->m_dwStyleExes |= FWL_STYLEEXT_CMB_DropDown;\r
1354     if (bAddDropDown) {\r
1355         m_pEdit->ModifyStylesEx(0, FWL_STYLEEXT_EDT_ReadOnly);\r
1356     } else if (bDelDropDown) {\r
1357         m_pEdit->ModifyStylesEx(FWL_STYLEEXT_EDT_ReadOnly, 0);\r
1358     }\r
1359     return CFWL_WidgetImp::ModifyStylesEx(dwStylesExAdded, dwStylesExRemoved);\r
1360 }\r
1361 FWL_ERR CFWL_ComboBoxImp::DisForm_Update()\r
1362 {\r
1363     if (m_iLock) {\r
1364         return FWL_ERR_Indefinite;\r
1365     }\r
1366     if (m_pEdit) {\r
1367         ReSetEditAlignment();\r
1368     }\r
1369     ReSetTheme();\r
1370     Layout();\r
1371     return FWL_ERR_Succeeded;\r
1372 }\r
1373 FX_DWORD CFWL_ComboBoxImp::DisForm_HitTest(FX_FLOAT fx, FX_FLOAT fy)\r
1374 {\r
1375     CFX_RectF rect;\r
1376     rect.Set(0,\r
1377              0,\r
1378              m_pProperties->m_rtWidget.width - m_rtBtn.width,\r
1379              m_pProperties->m_rtWidget.height);\r
1380     if (rect.Contains(fx, fy)) {\r
1381         return FWL_WGTHITTEST_Edit;\r
1382     }\r
1383     if (m_rtBtn.Contains(fx, fy)) {\r
1384         return FWL_WGTHITTEST_Client;\r
1385     }\r
1386     if (DisForm_IsDropListShowed()) {\r
1387         m_pListBox->GetWidgetRect(rect);\r
1388         if (rect.Contains(fx, fy)) {\r
1389             return FWL_WGTHITTEST_Client;\r
1390         }\r
1391     }\r
1392     return FWL_WGTHITTEST_Unknown;\r
1393 }\r
1394 FWL_ERR CFWL_ComboBoxImp::DisForm_DrawWidget(CFX_Graphics *pGraphics, const CFX_Matrix *pMatrix)\r
1395 {\r
1396     IFWL_ThemeProvider *pTheme = m_pProperties->m_pThemeProvider;\r
1397     CFX_Matrix mtOrg;\r
1398     mtOrg.Set(1, 0, 0, 1, 0, 0);\r
1399     if (pMatrix) {\r
1400         mtOrg = *pMatrix;\r
1401     }\r
1402     FX_BOOL bListShowed = m_pListBox && DisForm_IsDropListShowed();\r
1403     pGraphics->SaveGraphState();\r
1404     pGraphics->ConcatMatrix(&mtOrg);\r
1405     if (!m_rtBtn.IsEmpty(0.1f)) {\r
1406         CFWL_ThemeBackground param;\r
1407         param.m_pWidget = (IFWL_Widget*)this->m_pInterface;\r
1408         param.m_iPart = FWL_PART_CMB_DropDownButton;\r
1409         param.m_dwStates = m_iBtnState;\r
1410         param.m_pGraphics = pGraphics;\r
1411         param.m_rtPart = m_rtBtn;\r
1412         pTheme->DrawBackground(&param);\r
1413     }\r
1414     pGraphics->RestoreGraphState();\r
1415     if (m_pEdit) {\r
1416         CFX_RectF rtEdit;\r
1417         m_pEdit->GetWidgetRect(rtEdit);\r
1418         CFX_Matrix mt;\r
1419         mt.Set(1, 0, 0, 1, rtEdit.left, rtEdit.top);\r
1420         mt.Concat(mtOrg);\r
1421         m_pEdit->DrawWidget(pGraphics, &mt);\r
1422     }\r
1423     if (bListShowed) {\r
1424         CFX_RectF rtList;\r
1425         m_pListBox->GetWidgetRect(rtList);\r
1426         CFX_Matrix mt;\r
1427         mt.Set(1, 0, 0, 1, rtList.left, rtList.top);\r
1428         mt.Concat(mtOrg);\r
1429         m_pListBox->DrawWidget(pGraphics, &mt);\r
1430     }\r
1431     return FWL_ERR_Succeeded;\r
1432 }\r
1433 FWL_ERR CFWL_ComboBoxImp::DisForm_GetBBox(CFX_RectF &rect)\r
1434 {\r
1435     rect = m_pProperties->m_rtWidget;\r
1436     if (m_pListBox && DisForm_IsDropListShowed()) {\r
1437         CFX_RectF rtList;\r
1438         m_pListBox->GetWidgetRect(rtList);\r
1439         rtList.Offset(rect.left, rect.top);\r
1440         rect.Union(rtList);\r
1441     }\r
1442     return FWL_ERR_Succeeded;\r
1443 }\r
1444 void CFWL_ComboBoxImp::DisForm_Layout()\r
1445 {\r
1446     GetClientRect(m_rtClient);\r
1447     m_rtContent = m_rtClient;\r
1448     FX_FLOAT *pFWidth = (FX_FLOAT*)GetThemeCapacity(FWL_WGTCAPACITY_ScrollBarWidth);\r
1449     _FWL_RETURN_IF_FAIL(pFWidth);\r
1450     FX_FLOAT borderWidth = 0;\r
1451     {\r
1452         borderWidth = FWL_PART_CMB_Border;\r
1453     }\r
1454     FX_FLOAT fBtn = *pFWidth;\r
1455     if (!(this->GetStylesEx() & FWL_STYLEEXT_CMB_ReadOnly)) {\r
1456         m_rtBtn.Set(m_rtClient.right() - fBtn, m_rtClient.top + borderWidth,\r
1457                     fBtn - borderWidth, m_rtClient.height - 2 * borderWidth);\r
1458     }\r
1459     CFX_RectF* pUIMargin = (CFX_RectF*)GetThemeCapacity(FWL_WGTCAPACITY_UIMargin);\r
1460     if (pUIMargin) {\r
1461         m_rtContent.Deflate(pUIMargin->left, pUIMargin->top, pUIMargin->width, pUIMargin->height);\r
1462     }\r
1463     FX_BOOL bIsDropDown = IsDropDownStyle();\r
1464     if (bIsDropDown && m_pEdit) {\r
1465         CFX_RectF rtEdit;\r
1466         rtEdit.Set(m_rtContent.left,\r
1467                    m_rtContent.top, m_rtContent.width - fBtn, m_rtContent.height);\r
1468         m_pEdit->SetWidgetRect(rtEdit);\r
1469         if (m_iCurSel >= 0) {\r
1470             CFX_WideString wsText;\r
1471             IFWL_ComboBoxDP *pData = (IFWL_ComboBoxDP *)m_pProperties->m_pDataProvider;\r
1472             FWL_HLISTITEM hItem = pData->GetItem(m_pInterface, m_iCurSel);\r
1473             ((CFWL_ComboList*)((IFWL_TargetData*)m_pListBox)->GetData())->GetItemText(hItem, wsText);\r
1474             m_pEdit->LockUpdate();\r
1475             m_pEdit->SetText(wsText);\r
1476             m_pEdit->UnlockUpdate();\r
1477         }\r
1478         m_pEdit->Update();\r
1479     }\r
1480 }\r
1481 CFWL_ComboBoxImpDelegate::CFWL_ComboBoxImpDelegate(CFWL_ComboBoxImp *pOwner)\r
1482     : m_pOwner(pOwner)\r
1483 {\r
1484 }\r
1485 FX_INT32 CFWL_ComboBoxImpDelegate::OnProcessMessage(CFWL_Message *pMessage)\r
1486 {\r
1487     if (m_pOwner->m_pWidgetMgr->IsFormDisabled()) {\r
1488         return DisForm_OnProcessMessage(pMessage);\r
1489     }\r
1490     _FWL_RETURN_VALUE_IF_FAIL(pMessage, 0);\r
1491     FX_DWORD dwMsgCode = pMessage->GetClassID();\r
1492     FX_BOOL iRet = 1;\r
1493     switch (dwMsgCode) {\r
1494         case FWL_MSGHASH_SetFocus:\r
1495         case FWL_MSGHASH_KillFocus: {\r
1496                 OnFocusChanged(pMessage, dwMsgCode == FWL_MSGHASH_SetFocus);\r
1497                 break;\r
1498             }\r
1499         case FWL_MSGHASH_Mouse: {\r
1500                 CFWL_MsgMouse *pMsg = (CFWL_MsgMouse*)pMessage;\r
1501                 FX_DWORD dwCmd = pMsg->m_dwCmd;\r
1502                 switch(dwCmd) {\r
1503                     case FWL_MSGMOUSECMD_LButtonDown: {\r
1504                             OnLButtonDown(pMsg);\r
1505                             break;\r
1506                         }\r
1507                     case FWL_MSGMOUSECMD_LButtonUp: {\r
1508                             OnLButtonUp(pMsg);\r
1509                             break;\r
1510                         }\r
1511                     case FWL_MSGMOUSECMD_MouseMove: {\r
1512                             OnMouseMove(pMsg);\r
1513                             break;\r
1514                         }\r
1515                     case FWL_MSGMOUSECMD_MouseLeave: {\r
1516                             OnMouseLeave(pMsg);\r
1517                             break;\r
1518                         }\r
1519                     default: {\r
1520                         }\r
1521                 }\r
1522                 break;\r
1523             }\r
1524         case FWL_MSGHASH_Key: {\r
1525                 OnKey((CFWL_MsgKey*)pMessage);\r
1526                 break;\r
1527             }\r
1528         default: {\r
1529                 iRet = 0;\r
1530             }\r
1531     }\r
1532     CFWL_WidgetImpDelegate::OnProcessMessage(pMessage);\r
1533     return iRet;\r
1534 }\r
1535 FWL_ERR CFWL_ComboBoxImpDelegate::OnProcessEvent(CFWL_Event *pEvent)\r
1536 {\r
1537     FX_DWORD dwFlag = pEvent->GetClassID();\r
1538     if (dwFlag == FWL_EVTHASH_LTB_DrawItem) {\r
1539         CFWL_EvtCmbDrawItem pTemp;\r
1540         pTemp.m_pSrcTarget = m_pOwner->m_pInterface;\r
1541         pTemp.m_pGraphics = ((CFWL_EvtLtbDrawItem *)pEvent)->m_pGraphics;\r
1542         pTemp.m_index = ((CFWL_EvtLtbDrawItem *)pEvent)->m_index;\r
1543         pTemp.m_rtItem = ((CFWL_EvtLtbDrawItem *)pEvent)->m_rect;\r
1544         m_pOwner->DispatchEvent(&pTemp);\r
1545     } else if (dwFlag == FWL_EVTHASH_Scroll) {\r
1546         FX_DWORD dwScrollCode = ((CFWL_EvtScroll*)pEvent)->m_iScrollCode;\r
1547         FX_FLOAT fPos = ((CFWL_EvtScroll*)pEvent)->m_fPos;\r
1548         CFWL_EvtScroll pScrollEv;\r
1549         pScrollEv.m_pSrcTarget = m_pOwner->m_pInterface;\r
1550         pScrollEv.m_iScrollCode = dwScrollCode;\r
1551         pScrollEv.m_fPos = fPos;\r
1552         m_pOwner->DispatchEvent(&pScrollEv);\r
1553     } else if (dwFlag == FWL_EVTHASH_EDT_TextChanged) {\r
1554         CFWL_EvtCmbEditChanged pTemp;\r
1555         pTemp.m_pSrcTarget = m_pOwner->m_pInterface;\r
1556         pTemp.wsInsert = ((CFWL_EvtEdtTextChanged *)pEvent)->wsInsert;\r
1557         pTemp.wsDelete = ((CFWL_EvtEdtTextChanged *)pEvent)->wsDelete;\r
1558         pTemp.nChangeType = ((CFWL_EvtEdtTextChanged *)pEvent)->nChangeType;\r
1559         m_pOwner->DispatchEvent(&pTemp);\r
1560     }\r
1561     return FWL_ERR_Succeeded;\r
1562 }\r
1563 FWL_ERR CFWL_ComboBoxImpDelegate::OnDrawWidget(CFX_Graphics *pGraphics, const CFX_Matrix *pMatrix)\r
1564 {\r
1565     return m_pOwner->DrawWidget(pGraphics, pMatrix);\r
1566 }\r
1567 void CFWL_ComboBoxImpDelegate::OnFocusChanged(CFWL_Message *pMsg, FX_BOOL bSet )\r
1568 {\r
1569     IFWL_Target *pDstTarget = pMsg->m_pDstTarget;\r
1570     IFWL_Target *pSrcTarget = pMsg->m_pSrcTarget;\r
1571     FX_BOOL bDropDown = m_pOwner->IsDropDownStyle();\r
1572     if (bSet) {\r
1573         m_pOwner->m_pProperties->m_dwStates |= FWL_WGTSTATE_Focused;\r
1574         if (bDropDown && pSrcTarget != (IFWL_Widget*)m_pOwner->m_pListBox) {\r
1575             _FWL_RETURN_IF_FAIL(m_pOwner->m_pEdit);\r
1576             ((CFWL_ComboEdit*)((IFWL_TargetData*)m_pOwner->m_pEdit)->GetData())->SetSelected();\r
1577         } else {\r
1578             m_pOwner->Repaint(&m_pOwner->m_rtClient);\r
1579         }\r
1580     } else {\r
1581         m_pOwner->m_pProperties->m_dwStates &= ~FWL_WGTSTATE_Focused;\r
1582         if (bDropDown && pDstTarget != (IFWL_Widget*)m_pOwner->m_pListBox) {\r
1583             _FWL_RETURN_IF_FAIL(m_pOwner->m_pEdit);\r
1584             ((CFWL_ComboEdit*)((IFWL_TargetData*)m_pOwner->m_pEdit)->GetData())->FlagFocus(FALSE);\r
1585             ((CFWL_ComboEdit*)((IFWL_TargetData*)m_pOwner->m_pEdit)->GetData())->ClearSelected();\r
1586         } else {\r
1587             m_pOwner->Repaint(&m_pOwner->m_rtClient);\r
1588         }\r
1589     }\r
1590 }\r
1591 void CFWL_ComboBoxImpDelegate::OnLButtonDown(CFWL_MsgMouse *pMsg)\r
1592 {\r
1593     if (m_pOwner->m_pProperties->m_dwStates & FWL_WGTSTATE_Disabled) {\r
1594         return;\r
1595     }\r
1596     FX_BOOL bDropDown = m_pOwner->IsDropDownStyle();\r
1597     CFX_RectF& rtBtn = bDropDown ? m_pOwner->m_rtBtn : m_pOwner->m_rtClient;\r
1598     FX_BOOL bClickBtn = rtBtn.Contains(pMsg->m_fx, pMsg->m_fy);\r
1599     if (bClickBtn) {\r
1600         if (bDropDown && m_pOwner->m_pEdit) {\r
1601             m_pOwner->MatchEditText();\r
1602         }\r
1603         m_pOwner->m_bLButtonDown = TRUE;\r
1604         m_pOwner->m_iBtnState = FWL_PARTSTATE_CMB_Pressed;\r
1605         m_pOwner->Repaint(&m_pOwner->m_rtClient);\r
1606         m_pOwner->ShowDropList(TRUE);\r
1607         m_pOwner->m_iBtnState = FWL_PARTSTATE_CMB_Normal;\r
1608         m_pOwner->Repaint(&m_pOwner->m_rtClient);\r
1609     }\r
1610 }\r
1611 void CFWL_ComboBoxImpDelegate::OnLButtonUp(CFWL_MsgMouse *pMsg)\r
1612 {\r
1613     m_pOwner->m_bLButtonDown = FALSE;\r
1614     if (m_pOwner->m_rtBtn.Contains(pMsg->m_fx, pMsg->m_fy)) {\r
1615         m_pOwner->m_iBtnState = FWL_PARTSTATE_CMB_Hovered;\r
1616     } else {\r
1617         m_pOwner->m_iBtnState = FWL_PARTSTATE_CMB_Normal;\r
1618     }\r
1619     m_pOwner->Repaint(&m_pOwner->m_rtBtn);\r
1620 }\r
1621 void CFWL_ComboBoxImpDelegate::OnMouseMove(CFWL_MsgMouse *pMsg)\r
1622 {\r
1623     FX_INT32 iOldState = m_pOwner->m_iBtnState;\r
1624     if (m_pOwner->m_rtBtn.Contains(pMsg->m_fx, pMsg->m_fy)) {\r
1625         m_pOwner->m_iBtnState = m_pOwner->m_bLButtonDown ? FWL_PARTSTATE_CMB_Pressed : FWL_PARTSTATE_CMB_Hovered;\r
1626     } else {\r
1627         m_pOwner->m_iBtnState = FWL_PARTSTATE_CMB_Normal;\r
1628     }\r
1629     if (  (iOldState != m_pOwner->m_iBtnState) &&\r
1630             !((m_pOwner->m_pProperties->m_dwStates & FWL_WGTSTATE_Disabled) == FWL_WGTSTATE_Disabled)) {\r
1631         m_pOwner->Repaint(&m_pOwner->m_rtBtn);\r
1632     }\r
1633 }\r
1634 void CFWL_ComboBoxImpDelegate::OnMouseLeave(CFWL_MsgMouse *pMsg)\r
1635 {\r
1636     if (!m_pOwner->IsDropListShowed() &&\r
1637             !((m_pOwner->m_pProperties->m_dwStates & FWL_WGTSTATE_Disabled) == FWL_WGTSTATE_Disabled)) {\r
1638         m_pOwner->m_iBtnState = FWL_PARTSTATE_CMB_Normal;\r
1639         m_pOwner->Repaint(&m_pOwner->m_rtBtn);\r
1640     }\r
1641 }\r
1642 void CFWL_ComboBoxImpDelegate::OnKey(CFWL_MsgKey *pMsg)\r
1643 {\r
1644     FX_DWORD dwKeyCode = pMsg->m_dwKeyCode;\r
1645     if (dwKeyCode == FWL_VKEY_Tab) {\r
1646         m_pOwner->DispatchKeyEvent(pMsg);\r
1647         return;\r
1648     }\r
1649     FX_BOOL bSubCtrlKey = pMsg->m_pDstTarget == m_pOwner->m_pInterface;\r
1650     if (bSubCtrlKey) {\r
1651         DoSubCtrlKey(pMsg);\r
1652     }\r
1653 }\r
1654 void CFWL_ComboBoxImpDelegate::DoSubCtrlKey(CFWL_MsgKey *pMsg)\r
1655 {\r
1656     FX_DWORD dwKeyCode = pMsg->m_dwKeyCode;\r
1657     FX_BOOL bUp = dwKeyCode == FWL_VKEY_Up;\r
1658     FX_BOOL bDown = dwKeyCode == FWL_VKEY_Down;\r
1659     if (bUp || bDown) {\r
1660         FX_INT32 iCount = ((CFWL_ComboList*)((IFWL_TargetData*)m_pOwner->m_pListBox)->GetData())->CountItems();\r
1661         if (iCount < 1) {\r
1662             return;\r
1663         }\r
1664         FX_BOOL bMatchEqual = FALSE;\r
1665         FX_INT32 iCurSel = m_pOwner->m_iCurSel;\r
1666         FX_BOOL bDropDown = m_pOwner->IsDropDownStyle();\r
1667         if (bDropDown && m_pOwner->m_pEdit) {\r
1668             CFX_WideString wsText;\r
1669             m_pOwner->m_pEdit->GetText(wsText);\r
1670             iCurSel = ((CFWL_ComboList*)((IFWL_TargetData*)m_pOwner->m_pListBox)->GetData())->MatchItem(wsText);\r
1671             if (iCurSel >= 0) {\r
1672                 CFX_WideString wsTemp;\r
1673                 IFWL_ComboBoxDP *pData = (IFWL_ComboBoxDP *)m_pOwner->m_pProperties->m_pDataProvider;\r
1674                 FWL_HLISTITEM hItem = pData->GetItem(m_pOwner->m_pInterface, iCurSel);\r
1675                 ((CFWL_ComboList*)((IFWL_TargetData*)m_pOwner->m_pListBox)->GetData())->GetItemText(hItem, wsTemp);\r
1676                 bMatchEqual = wsText.Equal(wsTemp);\r
1677             }\r
1678         }\r
1679         if (iCurSel < 0) {\r
1680             iCurSel = 0;\r
1681         } else if (!bDropDown || bMatchEqual) {\r
1682             if ((bUp && iCurSel == 0) || (bDown && iCurSel == iCount - 1)) {\r
1683                 return;\r
1684             }\r
1685             if (bUp) {\r
1686                 iCurSel --;\r
1687             } else {\r
1688                 iCurSel ++;\r
1689             }\r
1690         }\r
1691         m_pOwner->m_iCurSel = iCurSel;\r
1692         if (bDropDown && m_pOwner->m_pEdit) {\r
1693             m_pOwner->SynchrEditText(m_pOwner->m_iCurSel);\r
1694         } else {\r
1695             m_pOwner->Repaint(&m_pOwner->m_rtClient);\r
1696         }\r
1697         return;\r
1698     }\r
1699     FX_BOOL bDropDown = m_pOwner->IsDropDownStyle();\r
1700     if (bDropDown) {\r
1701         IFWL_WidgetDelegate *pDelegate = m_pOwner->m_pEdit->SetDelegate(NULL);\r
1702         pDelegate->OnProcessMessage(pMsg);\r
1703     }\r
1704 }\r
1705 FX_INT32 CFWL_ComboBoxImpDelegate::DisForm_OnProcessMessage(CFWL_Message *pMessage)\r
1706 {\r
1707     _FWL_RETURN_VALUE_IF_FAIL(pMessage, 0);\r
1708     FX_DWORD dwMsgCode = pMessage->GetClassID();\r
1709     FX_BOOL backDefault = TRUE;\r
1710     switch (dwMsgCode) {\r
1711         case FWL_MSGHASH_SetFocus:\r
1712         case FWL_MSGHASH_KillFocus: {\r
1713                 backDefault = FALSE;\r
1714                 DisForm_OnFocusChanged(pMessage, dwMsgCode == FWL_MSGHASH_SetFocus);\r
1715                 break;\r
1716             }\r
1717         case FWL_MSGHASH_Mouse: {\r
1718                 backDefault = FALSE;\r
1719                 CFWL_MsgMouse *pMsg = (CFWL_MsgMouse*)pMessage;\r
1720                 FX_DWORD dwCmd = pMsg->m_dwCmd;\r
1721                 switch(dwCmd) {\r
1722                     case FWL_MSGMOUSECMD_LButtonDown: {\r
1723                             DisForm_OnLButtonDown(pMsg);\r
1724                             break;\r
1725                         }\r
1726                     case FWL_MSGMOUSECMD_LButtonUp: {\r
1727                             OnLButtonUp(pMsg);\r
1728                             break;\r
1729                         }\r
1730                     default: {\r
1731                         }\r
1732                 }\r
1733                 break;\r
1734             }\r
1735         case FWL_MSGHASH_Key: {\r
1736                 backDefault = FALSE;\r
1737                 CFWL_MsgKey *pKey = (CFWL_MsgKey*)pMessage;\r
1738                 if (pKey->m_dwCmd == FWL_MSGKEYCMD_KeyUp) {\r
1739                     break;\r
1740                 }\r
1741                 if (m_pOwner->DisForm_IsDropListShowed() && pKey->m_dwCmd == FWL_MSGKEYCMD_KeyDown) {\r
1742                     FX_DWORD dwKeyCode = pKey->m_dwKeyCode;\r
1743                     FX_BOOL bListKey = dwKeyCode == FWL_VKEY_Up ||\r
1744                                        dwKeyCode == FWL_VKEY_Down ||\r
1745                                        dwKeyCode == FWL_VKEY_Return ||\r
1746                                        dwKeyCode == FWL_VKEY_Escape;\r
1747                     if (bListKey) {\r
1748                         IFWL_WidgetDelegate *pDelegate = m_pOwner->m_pListBox->SetDelegate(NULL);\r
1749                         pDelegate->OnProcessMessage(pMessage);\r
1750                         break;\r
1751                     }\r
1752                 }\r
1753                 DisForm_OnKey((CFWL_MsgKey*)pMessage);\r
1754                 break;\r
1755             }\r
1756         default: {\r
1757             }\r
1758     }\r
1759     if (!backDefault) {\r
1760         return 1;\r
1761     }\r
1762     return CFWL_WidgetImpDelegate::OnProcessMessage(pMessage);\r
1763 }\r
1764 void CFWL_ComboBoxImpDelegate::DisForm_OnLButtonDown(CFWL_MsgMouse *pMsg)\r
1765 {\r
1766     FX_BOOL bDropDown = m_pOwner->DisForm_IsDropListShowed();\r
1767     CFX_RectF& rtBtn = bDropDown ? m_pOwner->m_rtBtn : m_pOwner->m_rtClient;\r
1768     FX_BOOL bClickBtn = rtBtn.Contains(pMsg->m_fx, pMsg->m_fy);\r
1769     if (bClickBtn) {\r
1770         if (m_pOwner->DisForm_IsDropListShowed()) {\r
1771             m_pOwner->DisForm_ShowDropList(FALSE);\r
1772             return;\r
1773         }\r
1774         {\r
1775             if (m_pOwner->m_pEdit) {\r
1776                 m_pOwner->MatchEditText();\r
1777             }\r
1778             m_pOwner->DisForm_ShowDropList(TRUE);\r
1779         }\r
1780     }\r
1781 }\r
1782 void CFWL_ComboBoxImpDelegate::DisForm_OnFocusChanged(CFWL_Message *pMsg, FX_BOOL bSet)\r
1783 {\r
1784     IFWL_Target *pDstTarget = pMsg->m_pDstTarget;\r
1785     IFWL_Target *pSrcTarget = pMsg->m_pSrcTarget;\r
1786     FX_BOOL bDropDown = m_pOwner->IsDropDownStyle();\r
1787     if (bSet) {\r
1788         m_pOwner->m_pProperties->m_dwStates |= FWL_WGTSTATE_Focused;\r
1789         if ((m_pOwner->m_pEdit->GetStates() & FWL_WGTSTATE_Focused) == 0) {\r
1790             CFWL_MsgSetFocus msg;\r
1791             msg.m_pDstTarget = m_pOwner->m_pEdit;\r
1792             msg.m_pSrcTarget = NULL;\r
1793             IFWL_WidgetDelegate *pDelegate = m_pOwner->m_pEdit->SetDelegate(NULL);\r
1794             pDelegate->OnProcessMessage(&msg);\r
1795         }\r
1796     } else {\r
1797         m_pOwner->m_pProperties->m_dwStates &= ~FWL_WGTSTATE_Focused;\r
1798         m_pOwner->DisForm_ShowDropList(FALSE);\r
1799         CFWL_MsgKillFocus msg;\r
1800         msg.m_pDstTarget = NULL;\r
1801         msg.m_pSrcTarget = m_pOwner->m_pEdit;\r
1802         IFWL_WidgetDelegate *pDelegate = m_pOwner->m_pEdit->SetDelegate(NULL);\r
1803         pDelegate->OnProcessMessage(&msg);\r
1804     }\r
1805 }\r
1806 void CFWL_ComboBoxImpDelegate::DisForm_OnKey(CFWL_MsgKey *pMsg)\r
1807 {\r
1808     FX_DWORD dwKeyCode = pMsg->m_dwKeyCode;\r
1809     FX_BOOL bUp = dwKeyCode == FWL_VKEY_Up;\r
1810     FX_BOOL bDown = dwKeyCode == FWL_VKEY_Down;\r
1811     if (bUp || bDown) {\r
1812         CFWL_ComboList* pComboList = ((CFWL_ComboList*)((IFWL_TargetData*)(m_pOwner->m_pListBox))->GetData());\r
1813         FX_INT32 iCount = pComboList->CountItems();\r
1814         if (iCount < 1) {\r
1815             return;\r
1816         }\r
1817         FX_BOOL bMatchEqual = FALSE;\r
1818         FX_INT32 iCurSel = m_pOwner->m_iCurSel;\r
1819         if (m_pOwner->m_pEdit) {\r
1820             CFX_WideString wsText;\r
1821             m_pOwner->m_pEdit->GetText(wsText);\r
1822             iCurSel = pComboList->MatchItem(wsText);\r
1823             if (iCurSel >= 0) {\r
1824                 CFX_WideString wsTemp;\r
1825                 FWL_HLISTITEM item = m_pOwner->m_pListBox->GetSelItem(iCurSel);\r
1826                 m_pOwner->m_pListBox->GetItemText(item, wsTemp);\r
1827                 bMatchEqual = wsText.Equal(wsTemp);\r
1828             }\r
1829         }\r
1830         if (iCurSel < 0) {\r
1831             iCurSel = 0;\r
1832         } else if (bMatchEqual) {\r
1833             if ((bUp && iCurSel == 0) || (bDown && iCurSel == iCount - 1)) {\r
1834                 return;\r
1835             }\r
1836             if (bUp) {\r
1837                 iCurSel --;\r
1838             } else {\r
1839                 iCurSel ++;\r
1840             }\r
1841         }\r
1842         m_pOwner->m_iCurSel = iCurSel;\r
1843         m_pOwner->SynchrEditText(m_pOwner->m_iCurSel);\r
1844         return;\r
1845     }\r
1846     if (m_pOwner->m_pEdit) {\r
1847         IFWL_WidgetDelegate *pDelegate = m_pOwner->m_pEdit->SetDelegate(NULL);\r
1848         pDelegate->OnProcessMessage(pMsg);\r
1849     }\r
1850 }\r
1851 CFWL_ComboProxyImpDelegate::CFWL_ComboProxyImpDelegate(IFWL_Form *pForm, CFWL_ComboBoxImp *pComboBox)\r
1852     : m_pForm(pForm)\r
1853     , m_pComboBox(pComboBox)\r
1854     , m_bLButtonDown(FALSE)\r
1855     , m_bLButtonUpSelf(FALSE)\r
1856     , m_fStartPos(0)\r
1857 {\r
1858 }\r
1859 FX_INT32 CFWL_ComboProxyImpDelegate::OnProcessMessage(CFWL_Message *pMessage)\r
1860 {\r
1861     _FWL_RETURN_VALUE_IF_FAIL(pMessage, 0);\r
1862     FX_DWORD dwMsgCode = pMessage->GetClassID();\r
1863     if (dwMsgCode == FWL_MSGHASH_Mouse) {\r
1864         CFWL_MsgMouse *pMsg = (CFWL_MsgMouse*)pMessage;\r
1865         FX_DWORD dwCmd = pMsg->m_dwCmd;\r
1866         switch(dwCmd) {\r
1867             case FWL_MSGMOUSECMD_LButtonDown: {\r
1868                     OnLButtonDown(pMsg);\r
1869                     break;\r
1870                 }\r
1871             case FWL_MSGMOUSECMD_LButtonUp: {\r
1872                     OnLButtonUp(pMsg);\r
1873                     break;\r
1874                 }\r
1875             case FWL_MSGMOUSECMD_MouseMove: {\r
1876                     OnMouseMove(pMsg);\r
1877                     break;\r
1878                 }\r
1879             default: {\r
1880                 }\r
1881         }\r
1882     }\r
1883     if (dwMsgCode == FWL_MSGHASH_Deactivate) {\r
1884         OnDeactive((CFWL_MsgDeactivate*)pMessage);\r
1885     }\r
1886     if (dwMsgCode == FWL_MSGHASH_KillFocus || dwMsgCode == FWL_MSGHASH_SetFocus) {\r
1887         OnFocusChanged((CFWL_MsgKillFocus*)pMessage, dwMsgCode == FWL_MSGHASH_SetFocus);\r
1888     }\r
1889     return CFWL_WidgetImpDelegate::OnProcessMessage(pMessage);\r
1890 }\r
1891 FWL_ERR CFWL_ComboProxyImpDelegate::OnDrawWidget(CFX_Graphics *pGraphics, const CFX_Matrix *pMatrix)\r
1892 {\r
1893     m_pComboBox->DrawStretchHandler(pGraphics, pMatrix);\r
1894     return FWL_ERR_Succeeded;\r
1895 }\r
1896 void CFWL_ComboProxyImpDelegate::OnLButtonDown(CFWL_MsgMouse *pMsg)\r
1897 {\r
1898     IFWL_NoteThread *pThread = m_pForm->GetOwnerThread();\r
1899     _FWL_RETURN_IF_FAIL(pThread);\r
1900     CFWL_NoteDriver *pDriver = (CFWL_NoteDriver*)pThread->GetNoteDriver();\r
1901     CFX_RectF rtWidget;\r
1902     m_pForm->GetWidgetRect(rtWidget);\r
1903     rtWidget.left = rtWidget.top = 0;\r
1904     if (rtWidget.Contains(pMsg->m_fx, pMsg->m_fy)) {\r
1905         m_bLButtonDown = TRUE;\r
1906         pDriver->SetGrab(m_pForm, TRUE);\r
1907     } else {\r
1908         m_bLButtonDown = FALSE;\r
1909         pDriver->SetGrab(m_pForm, FALSE);\r
1910         m_pComboBox->ShowDropList(FALSE);\r
1911         return;\r
1912     }\r
1913     IFWL_AdapterNative *pNative = FWL_GetAdapterNative();\r
1914     IFWL_AdapterCursorMgr *pCursorMgr = pNative->GetCursorMgr();\r
1915     FWL_HCURSOR hCursor = pCursorMgr->GetSystemCursor(FWL_CURSORTYPE_SizeNS);\r
1916     pCursorMgr->SetCursor(hCursor);\r
1917     pCursorMgr->ShowCursor(TRUE);\r
1918     m_pForm->TransformTo(NULL, pMsg->m_fx, pMsg->m_fy);\r
1919     m_fStartPos = pMsg->m_fy;\r
1920 }\r
1921 void CFWL_ComboProxyImpDelegate::OnLButtonUp(CFWL_MsgMouse *pMsg)\r
1922 {\r
1923     m_bLButtonDown = FALSE;\r
1924     IFWL_NoteThread *pThread = m_pForm->GetOwnerThread();\r
1925     _FWL_RETURN_IF_FAIL(pThread);\r
1926     CFWL_NoteDriver *pDriver = (CFWL_NoteDriver*)pThread->GetNoteDriver();\r
1927     pDriver->SetGrab(m_pForm, FALSE);\r
1928     if (m_bLButtonUpSelf) {\r
1929         CFX_RectF rect;\r
1930         m_pForm->GetWidgetRect(rect);\r
1931         rect.left = rect.top = 0;\r
1932         if (!rect.Contains(pMsg->m_fx, pMsg->m_fy) && m_pComboBox->IsDropListShowed()) {\r
1933             m_pComboBox->ShowDropList(FALSE);\r
1934         }\r
1935     } else {\r
1936         m_bLButtonUpSelf = TRUE;\r
1937     }\r
1938 }\r
1939 void CFWL_ComboProxyImpDelegate::OnMouseMove(CFWL_MsgMouse *pMsg)\r
1940 {\r
1941     IFWL_AdapterNative *pNative = FWL_GetAdapterNative();\r
1942     IFWL_AdapterCursorMgr *pCursorMgr = pNative->GetCursorMgr();\r
1943     FWL_CURSORTYPE cursorType = FWL_CURSORTYPE_Arrow;\r
1944     if (m_pComboBox->m_rtHandler.Contains(pMsg->m_fx, pMsg->m_fy)) {\r
1945         cursorType = FWL_CURSORTYPE_SizeNS;\r
1946     }\r
1947     FWL_HCURSOR hCursor = pCursorMgr->GetSystemCursor(cursorType);\r
1948     pCursorMgr->SetCursor(hCursor);\r
1949     pCursorMgr->ShowCursor(TRUE);\r
1950     if (!m_bLButtonDown) {\r
1951         return;\r
1952     }\r
1953     m_pForm->TransformTo(NULL, pMsg->m_fx, pMsg->m_fy);\r
1954     FX_FLOAT fChanged = pMsg->m_fy - m_fStartPos;\r
1955     if (m_pComboBox->m_bUpFormHandler) {\r
1956         fChanged = m_fStartPos - pMsg->m_fy;\r
1957     }\r
1958     if (m_pComboBox->m_rtList.height + fChanged < m_pComboBox->m_fItemHeight) {\r
1959         return;\r
1960     }\r
1961     m_pComboBox->m_rtList.height += fChanged;\r
1962     m_pComboBox->m_rtProxy.height += fChanged;\r
1963     if (m_pComboBox->m_bUpFormHandler) {\r
1964         m_pComboBox->m_rtProxy.top -= fChanged;\r
1965         m_pComboBox->m_rtHandler.Set(0,\r
1966                                      0,\r
1967                                      m_pComboBox->m_rtList.width,\r
1968                                      m_pComboBox->m_fComboFormHandler);\r
1969     } else {\r
1970         m_pComboBox->m_rtHandler.Set(0,\r
1971                                      m_pComboBox->m_rtList.height,\r
1972                                      m_pComboBox->m_rtList.width,\r
1973                                      m_pComboBox->m_fComboFormHandler);\r
1974     }\r
1975     m_pForm->SetWidgetRect(m_pComboBox->m_rtProxy);\r
1976     m_pComboBox->m_pListBox->SetWidgetRect(m_pComboBox->m_rtList);\r
1977     m_pComboBox->m_pListBox->Update();\r
1978     m_fStartPos = pMsg->m_fy;\r
1979 }\r
1980 void CFWL_ComboProxyImpDelegate::OnDeactive(CFWL_MsgDeactivate *pMsg)\r
1981 {\r
1982     m_pComboBox->ShowDropList(FALSE);\r
1983 }\r
1984 void CFWL_ComboProxyImpDelegate::OnFocusChanged(CFWL_MsgKillFocus *pMsg, FX_BOOL bSet )\r
1985 {\r
1986     if (!bSet) {\r
1987         if (pMsg->m_pSetFocus == NULL) {\r
1988             m_pComboBox->ShowDropList(FALSE);\r
1989         }\r
1990     }\r
1991 }\r