OLD | NEW |
| (Empty) |
1 // Copyright 2014 PDFium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com | |
6 | |
7 #include "xfa/fwl/core/cfwl_combobox.h" | |
8 | |
9 #include <algorithm> | |
10 #include <memory> | |
11 #include <utility> | |
12 | |
13 #include "third_party/base/ptr_util.h" | |
14 #include "xfa/fde/cfde_txtedtengine.h" | |
15 #include "xfa/fde/tto/fde_textout.h" | |
16 #include "xfa/fwl/core/cfwl_app.h" | |
17 #include "xfa/fwl/core/cfwl_event.h" | |
18 #include "xfa/fwl/core/cfwl_evtselectchanged.h" | |
19 #include "xfa/fwl/core/cfwl_evttextchanged.h" | |
20 #include "xfa/fwl/core/cfwl_formproxy.h" | |
21 #include "xfa/fwl/core/cfwl_listbox.h" | |
22 #include "xfa/fwl/core/cfwl_msgkey.h" | |
23 #include "xfa/fwl/core/cfwl_msgkillfocus.h" | |
24 #include "xfa/fwl/core/cfwl_msgmouse.h" | |
25 #include "xfa/fwl/core/cfwl_msgsetfocus.h" | |
26 #include "xfa/fwl/core/cfwl_notedriver.h" | |
27 #include "xfa/fwl/core/cfwl_themebackground.h" | |
28 #include "xfa/fwl/core/cfwl_themepart.h" | |
29 #include "xfa/fwl/core/cfwl_themetext.h" | |
30 #include "xfa/fwl/core/cfwl_widgetmgr.h" | |
31 #include "xfa/fwl/core/ifwl_themeprovider.h" | |
32 | |
33 CFWL_ComboBox::CFWL_ComboBox(const CFWL_App* app) | |
34 : CFWL_Widget(app, pdfium::MakeUnique<CFWL_WidgetProperties>(), nullptr), | |
35 m_pComboBoxProxy(nullptr), | |
36 m_bLButtonDown(false), | |
37 m_iCurSel(-1), | |
38 m_iBtnState(CFWL_PartState_Normal), | |
39 m_fComboFormHandler(0) { | |
40 m_rtClient.Reset(); | |
41 m_rtBtn.Reset(); | |
42 m_rtHandler.Reset(); | |
43 | |
44 if (m_pWidgetMgr->IsFormDisabled()) { | |
45 DisForm_InitComboList(); | |
46 DisForm_InitComboEdit(); | |
47 return; | |
48 } | |
49 | |
50 auto prop = pdfium::MakeUnique<CFWL_WidgetProperties>(); | |
51 prop->m_pThemeProvider = m_pProperties->m_pThemeProvider; | |
52 prop->m_dwStyles |= FWL_WGTSTYLE_Border | FWL_WGTSTYLE_VScroll; | |
53 if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_CMB_ListItemIconText) | |
54 prop->m_dwStyleExes |= FWL_STYLEEXT_LTB_Icon; | |
55 m_pListBox = | |
56 pdfium::MakeUnique<CFWL_ComboList>(m_pOwnerApp, std::move(prop), this); | |
57 | |
58 if ((m_pProperties->m_dwStyleExes & FWL_STYLEEXT_CMB_DropDown) && !m_pEdit) { | |
59 m_pEdit.reset(new CFWL_ComboEdit( | |
60 m_pOwnerApp, pdfium::MakeUnique<CFWL_WidgetProperties>(), this)); | |
61 m_pEdit->SetOuter(this); | |
62 } | |
63 if (m_pEdit) | |
64 m_pEdit->SetParent(this); | |
65 | |
66 SetStates(m_pProperties->m_dwStates); | |
67 } | |
68 | |
69 CFWL_ComboBox::~CFWL_ComboBox() {} | |
70 | |
71 FWL_Type CFWL_ComboBox::GetClassID() const { | |
72 return FWL_Type::ComboBox; | |
73 } | |
74 | |
75 void CFWL_ComboBox::AddString(const CFX_WideStringC& wsText) { | |
76 m_pListBox->AddString(wsText); | |
77 } | |
78 | |
79 bool CFWL_ComboBox::RemoveAt(int32_t iIndex) { | |
80 return m_pListBox->RemoveAt(iIndex); | |
81 } | |
82 | |
83 void CFWL_ComboBox::RemoveAll() { | |
84 m_pListBox->DeleteAll(); | |
85 } | |
86 | |
87 void CFWL_ComboBox::ModifyStylesEx(uint32_t dwStylesExAdded, | |
88 uint32_t dwStylesExRemoved) { | |
89 if (m_pWidgetMgr->IsFormDisabled()) { | |
90 DisForm_ModifyStylesEx(dwStylesExAdded, dwStylesExRemoved); | |
91 return; | |
92 } | |
93 | |
94 bool bAddDropDown = !!(dwStylesExAdded & FWL_STYLEEXT_CMB_DropDown); | |
95 bool bRemoveDropDown = !!(dwStylesExRemoved & FWL_STYLEEXT_CMB_DropDown); | |
96 if (bAddDropDown && !m_pEdit) { | |
97 m_pEdit = pdfium::MakeUnique<CFWL_ComboEdit>( | |
98 m_pOwnerApp, pdfium::MakeUnique<CFWL_WidgetProperties>(), nullptr); | |
99 m_pEdit->SetOuter(this); | |
100 m_pEdit->SetParent(this); | |
101 } else if (bRemoveDropDown && m_pEdit) { | |
102 m_pEdit->SetStates(FWL_WGTSTATE_Invisible); | |
103 } | |
104 CFWL_Widget::ModifyStylesEx(dwStylesExAdded, dwStylesExRemoved); | |
105 } | |
106 | |
107 void CFWL_ComboBox::Update() { | |
108 if (m_pWidgetMgr->IsFormDisabled()) { | |
109 DisForm_Update(); | |
110 return; | |
111 } | |
112 if (IsLocked()) | |
113 return; | |
114 | |
115 ResetTheme(); | |
116 if (IsDropDownStyle() && m_pEdit) | |
117 ResetEditAlignment(); | |
118 if (!m_pProperties->m_pThemeProvider) | |
119 m_pProperties->m_pThemeProvider = GetAvailableTheme(); | |
120 | |
121 Layout(); | |
122 CFWL_ThemePart part; | |
123 part.m_pWidget = this; | |
124 m_fComboFormHandler = | |
125 *static_cast<FX_FLOAT*>(m_pProperties->m_pThemeProvider->GetCapacity( | |
126 &part, CFWL_WidgetCapacity::ComboFormHandler)); | |
127 } | |
128 | |
129 FWL_WidgetHit CFWL_ComboBox::HitTest(FX_FLOAT fx, FX_FLOAT fy) { | |
130 if (m_pWidgetMgr->IsFormDisabled()) | |
131 return DisForm_HitTest(fx, fy); | |
132 return CFWL_Widget::HitTest(fx, fy); | |
133 } | |
134 | |
135 void CFWL_ComboBox::DrawWidget(CFX_Graphics* pGraphics, | |
136 const CFX_Matrix* pMatrix) { | |
137 if (m_pWidgetMgr->IsFormDisabled()) { | |
138 DisForm_DrawWidget(pGraphics, pMatrix); | |
139 return; | |
140 } | |
141 | |
142 if (!pGraphics) | |
143 return; | |
144 if (!m_pProperties->m_pThemeProvider) | |
145 return; | |
146 | |
147 IFWL_ThemeProvider* pTheme = m_pProperties->m_pThemeProvider; | |
148 if (HasBorder()) | |
149 DrawBorder(pGraphics, CFWL_Part::Border, pTheme, pMatrix); | |
150 if (HasEdge()) | |
151 DrawEdge(pGraphics, CFWL_Part::Edge, pTheme, pMatrix); | |
152 | |
153 if (!IsDropDownStyle()) { | |
154 CFX_RectF rtTextBk(m_rtClient); | |
155 rtTextBk.width -= m_rtBtn.width; | |
156 | |
157 CFWL_ThemeBackground param; | |
158 param.m_pWidget = this; | |
159 param.m_iPart = CFWL_Part::Background; | |
160 param.m_pGraphics = pGraphics; | |
161 if (pMatrix) | |
162 param.m_matrix.Concat(*pMatrix); | |
163 param.m_rtPart = rtTextBk; | |
164 | |
165 if (m_iCurSel >= 0) { | |
166 if (void* p = m_pListBox->GetItemData( | |
167 m_pListBox.get(), | |
168 m_pListBox->GetItem(m_pListBox.get(), m_iCurSel))) { | |
169 param.m_pData = p; | |
170 } | |
171 } | |
172 | |
173 if (m_pProperties->m_dwStates & FWL_WGTSTATE_Disabled) { | |
174 param.m_dwStates = CFWL_PartState_Disabled; | |
175 } else if ((m_pProperties->m_dwStates & FWL_WGTSTATE_Focused) && | |
176 (m_iCurSel >= 0)) { | |
177 param.m_dwStates = CFWL_PartState_Selected; | |
178 } else { | |
179 param.m_dwStates = CFWL_PartState_Normal; | |
180 } | |
181 pTheme->DrawBackground(¶m); | |
182 | |
183 if (m_iCurSel >= 0) { | |
184 if (!m_pListBox) | |
185 return; | |
186 | |
187 CFWL_ListItem* hItem = m_pListBox->GetItem(this, m_iCurSel); | |
188 CFX_WideString wsText = m_pListBox->GetDataProviderItemText(hItem); | |
189 | |
190 CFWL_ThemeText theme_text; | |
191 theme_text.m_pWidget = this; | |
192 theme_text.m_iPart = CFWL_Part::Caption; | |
193 theme_text.m_dwStates = m_iBtnState; | |
194 theme_text.m_pGraphics = pGraphics; | |
195 theme_text.m_matrix.Concat(*pMatrix); | |
196 theme_text.m_rtPart = rtTextBk; | |
197 theme_text.m_dwStates = (m_pProperties->m_dwStates & FWL_WGTSTATE_Focused) | |
198 ? CFWL_PartState_Selected | |
199 : CFWL_PartState_Normal; | |
200 theme_text.m_wsText = wsText; | |
201 theme_text.m_dwTTOStyles = FDE_TTOSTYLE_SingleLine; | |
202 theme_text.m_iTTOAlign = FDE_TTOALIGNMENT_CenterLeft; | |
203 pTheme->DrawText(&theme_text); | |
204 } | |
205 } | |
206 | |
207 CFWL_ThemeBackground param; | |
208 param.m_pWidget = this; | |
209 param.m_iPart = CFWL_Part::DropDownButton; | |
210 param.m_dwStates = (m_pProperties->m_dwStates & FWL_WGTSTATE_Disabled) | |
211 ? CFWL_PartState_Disabled | |
212 : m_iBtnState; | |
213 param.m_pGraphics = pGraphics; | |
214 param.m_matrix.Concat(*pMatrix); | |
215 param.m_rtPart = m_rtBtn; | |
216 pTheme->DrawBackground(¶m); | |
217 } | |
218 | |
219 void CFWL_ComboBox::SetThemeProvider(IFWL_ThemeProvider* pThemeProvider) { | |
220 if (!pThemeProvider) | |
221 return; | |
222 | |
223 m_pProperties->m_pThemeProvider = pThemeProvider; | |
224 if (m_pListBox) | |
225 m_pListBox->SetThemeProvider(pThemeProvider); | |
226 if (m_pEdit) | |
227 m_pEdit->SetThemeProvider(pThemeProvider); | |
228 } | |
229 | |
230 CFX_WideString CFWL_ComboBox::GetTextByIndex(int32_t iIndex) const { | |
231 CFWL_ListItem* pItem = static_cast<CFWL_ListItem*>( | |
232 m_pListBox->GetItem(m_pListBox.get(), iIndex)); | |
233 return pItem ? pItem->m_wsText : L""; | |
234 } | |
235 | |
236 void CFWL_ComboBox::SetCurSel(int32_t iSel) { | |
237 int32_t iCount = m_pListBox->CountItems(nullptr); | |
238 bool bClearSel = iSel < 0 || iSel >= iCount; | |
239 if (IsDropDownStyle() && m_pEdit) { | |
240 if (bClearSel) { | |
241 m_pEdit->SetText(CFX_WideString()); | |
242 } else { | |
243 CFWL_ListItem* hItem = m_pListBox->GetItem(this, iSel); | |
244 CFX_WideString wsText = m_pListBox->GetDataProviderItemText(hItem); | |
245 m_pEdit->SetText(wsText); | |
246 } | |
247 m_pEdit->Update(); | |
248 } | |
249 m_iCurSel = bClearSel ? -1 : iSel; | |
250 } | |
251 | |
252 void CFWL_ComboBox::SetStates(uint32_t dwStates) { | |
253 if (IsDropDownStyle() && m_pEdit) | |
254 m_pEdit->SetStates(dwStates); | |
255 if (m_pListBox) | |
256 m_pListBox->SetStates(dwStates); | |
257 CFWL_Widget::SetStates(dwStates); | |
258 } | |
259 | |
260 void CFWL_ComboBox::RemoveStates(uint32_t dwStates) { | |
261 if (IsDropDownStyle() && m_pEdit) | |
262 m_pEdit->RemoveStates(dwStates); | |
263 if (m_pListBox) | |
264 m_pListBox->RemoveStates(dwStates); | |
265 CFWL_Widget::RemoveStates(dwStates); | |
266 } | |
267 | |
268 void CFWL_ComboBox::SetEditText(const CFX_WideString& wsText) { | |
269 if (!m_pEdit) | |
270 return; | |
271 | |
272 m_pEdit->SetText(wsText); | |
273 m_pEdit->Update(); | |
274 } | |
275 | |
276 CFX_WideString CFWL_ComboBox::GetEditText() const { | |
277 if (m_pEdit) | |
278 return m_pEdit->GetText(); | |
279 if (!m_pListBox) | |
280 return L""; | |
281 | |
282 CFWL_ListItem* hItem = m_pListBox->GetItem(this, m_iCurSel); | |
283 return m_pListBox->GetDataProviderItemText(hItem); | |
284 } | |
285 | |
286 void CFWL_ComboBox::OpenDropDownList(bool bActivate) { | |
287 ShowDropList(bActivate); | |
288 } | |
289 | |
290 CFX_RectF CFWL_ComboBox::GetBBox() const { | |
291 if (m_pWidgetMgr->IsFormDisabled()) | |
292 return DisForm_GetBBox(); | |
293 | |
294 CFX_RectF rect = m_pProperties->m_rtWidget; | |
295 if (!m_pListBox || !IsDropListVisible()) | |
296 return rect; | |
297 | |
298 CFX_RectF rtList = m_pListBox->GetWidgetRect(); | |
299 rtList.Offset(rect.left, rect.top); | |
300 rect.Union(rtList); | |
301 return rect; | |
302 } | |
303 | |
304 void CFWL_ComboBox::EditModifyStylesEx(uint32_t dwStylesExAdded, | |
305 uint32_t dwStylesExRemoved) { | |
306 if (m_pEdit) | |
307 m_pEdit->ModifyStylesEx(dwStylesExAdded, dwStylesExRemoved); | |
308 } | |
309 | |
310 void CFWL_ComboBox::DrawStretchHandler(CFX_Graphics* pGraphics, | |
311 const CFX_Matrix* pMatrix) { | |
312 CFWL_ThemeBackground param; | |
313 param.m_pGraphics = pGraphics; | |
314 param.m_iPart = CFWL_Part::StretchHandler; | |
315 param.m_dwStates = CFWL_PartState_Normal; | |
316 param.m_pWidget = this; | |
317 if (pMatrix) | |
318 param.m_matrix.Concat(*pMatrix); | |
319 param.m_rtPart = m_rtHandler; | |
320 m_pProperties->m_pThemeProvider->DrawBackground(¶m); | |
321 } | |
322 | |
323 void CFWL_ComboBox::ShowDropList(bool bActivate) { | |
324 if (m_pWidgetMgr->IsFormDisabled()) | |
325 return DisForm_ShowDropList(bActivate); | |
326 if (IsDropListVisible() == bActivate) | |
327 return; | |
328 if (!m_pComboBoxProxy) | |
329 InitProxyForm(); | |
330 | |
331 m_pComboBoxProxy->Reset(); | |
332 if (!bActivate) { | |
333 m_pComboBoxProxy->EndDoModal(); | |
334 | |
335 m_bLButtonDown = false; | |
336 m_pListBox->SetNotifyOwner(true); | |
337 SetFocus(true); | |
338 return; | |
339 } | |
340 | |
341 m_pListBox->ChangeSelected(m_iCurSel); | |
342 ResetListItemAlignment(); | |
343 | |
344 uint32_t dwStyleAdd = m_pProperties->m_dwStyleExes & | |
345 (FWL_STYLEEXT_CMB_Sort | FWL_STYLEEXT_CMB_OwnerDraw); | |
346 m_pListBox->ModifyStylesEx(dwStyleAdd, 0); | |
347 m_rtList = m_pListBox->GetAutosizedWidgetRect(); | |
348 | |
349 CFX_RectF rtAnchor; | |
350 rtAnchor.Set(0, 0, m_pProperties->m_rtWidget.width, | |
351 m_pProperties->m_rtWidget.height); | |
352 | |
353 m_rtList.width = std::max(m_rtList.width, m_rtClient.width); | |
354 m_rtProxy = m_rtList; | |
355 if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_CMB_ListDrag) | |
356 m_rtProxy.height += m_fComboFormHandler; | |
357 | |
358 GetPopupPos(0, m_rtProxy.height, rtAnchor, m_rtProxy); | |
359 if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_CMB_ListDrag) { | |
360 FX_FLOAT fx = 0; | |
361 FX_FLOAT fy = m_rtClient.top + m_rtClient.height / 2; | |
362 TransformTo(nullptr, fx, fy); | |
363 | |
364 m_bUpFormHandler = fy > m_rtProxy.top; | |
365 if (m_bUpFormHandler) { | |
366 m_rtHandler.Set(0, 0, m_rtList.width, m_fComboFormHandler); | |
367 m_rtList.top = m_fComboFormHandler; | |
368 } else { | |
369 m_rtHandler.Set(0, m_rtList.height, m_rtList.width, m_fComboFormHandler); | |
370 } | |
371 } | |
372 m_pComboBoxProxy->SetWidgetRect(m_rtProxy); | |
373 m_pComboBoxProxy->Update(); | |
374 m_pListBox->SetWidgetRect(m_rtList); | |
375 m_pListBox->Update(); | |
376 | |
377 CFWL_Event ev(CFWL_Event::Type::PreDropDown, this); | |
378 DispatchEvent(&ev); | |
379 | |
380 m_fItemHeight = m_pListBox->GetItemHeight(); | |
381 m_pListBox->SetFocus(true); | |
382 m_pComboBoxProxy->DoModal(); | |
383 m_pListBox->SetFocus(false); | |
384 } | |
385 | |
386 void CFWL_ComboBox::MatchEditText() { | |
387 CFX_WideString wsText = m_pEdit->GetText(); | |
388 int32_t iMatch = m_pListBox->MatchItem(wsText); | |
389 if (iMatch != m_iCurSel) { | |
390 m_pListBox->ChangeSelected(iMatch); | |
391 if (iMatch >= 0) | |
392 SyncEditText(iMatch); | |
393 } else if (iMatch >= 0) { | |
394 m_pEdit->SetSelected(); | |
395 } | |
396 m_iCurSel = iMatch; | |
397 } | |
398 | |
399 void CFWL_ComboBox::SyncEditText(int32_t iListItem) { | |
400 CFWL_ListItem* hItem = m_pListBox->GetItem(this, iListItem); | |
401 CFX_WideString wsText = m_pListBox->GetDataProviderItemText(hItem); | |
402 m_pEdit->SetText(wsText); | |
403 m_pEdit->Update(); | |
404 m_pEdit->SetSelected(); | |
405 } | |
406 | |
407 void CFWL_ComboBox::Layout() { | |
408 if (m_pWidgetMgr->IsFormDisabled()) | |
409 return DisForm_Layout(); | |
410 | |
411 GetClientRect(m_rtClient); | |
412 FX_FLOAT* pFWidth = static_cast<FX_FLOAT*>( | |
413 GetThemeCapacity(CFWL_WidgetCapacity::ScrollBarWidth)); | |
414 if (!pFWidth) | |
415 return; | |
416 | |
417 FX_FLOAT fBtn = *pFWidth; | |
418 m_rtBtn.Set(m_rtClient.right() - fBtn, m_rtClient.top, fBtn, | |
419 m_rtClient.height); | |
420 if (!IsDropDownStyle() || !m_pEdit) | |
421 return; | |
422 | |
423 CFX_RectF rtEdit; | |
424 rtEdit.Set(m_rtClient.left, m_rtClient.top, m_rtClient.width - fBtn, | |
425 m_rtClient.height); | |
426 m_pEdit->SetWidgetRect(rtEdit); | |
427 | |
428 if (m_iCurSel >= 0) { | |
429 CFWL_ListItem* hItem = m_pListBox->GetItem(this, m_iCurSel); | |
430 CFX_WideString wsText = m_pListBox->GetDataProviderItemText(hItem); | |
431 m_pEdit->LockUpdate(); | |
432 m_pEdit->SetText(wsText); | |
433 m_pEdit->UnlockUpdate(); | |
434 } | |
435 m_pEdit->Update(); | |
436 } | |
437 | |
438 void CFWL_ComboBox::ResetTheme() { | |
439 IFWL_ThemeProvider* pTheme = m_pProperties->m_pThemeProvider; | |
440 if (!pTheme) { | |
441 pTheme = GetAvailableTheme(); | |
442 m_pProperties->m_pThemeProvider = pTheme; | |
443 } | |
444 if (m_pListBox && !m_pListBox->GetThemeProvider()) | |
445 m_pListBox->SetThemeProvider(pTheme); | |
446 if (m_pEdit && !m_pEdit->GetThemeProvider()) | |
447 m_pEdit->SetThemeProvider(pTheme); | |
448 } | |
449 | |
450 void CFWL_ComboBox::ResetEditAlignment() { | |
451 if (!m_pEdit) | |
452 return; | |
453 | |
454 uint32_t dwAdd = 0; | |
455 switch (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_CMB_EditHAlignMask) { | |
456 case FWL_STYLEEXT_CMB_EditHCenter: { | |
457 dwAdd |= FWL_STYLEEXT_EDT_HCenter; | |
458 break; | |
459 } | |
460 case FWL_STYLEEXT_CMB_EditHFar: { | |
461 dwAdd |= FWL_STYLEEXT_EDT_HFar; | |
462 break; | |
463 } | |
464 default: { dwAdd |= FWL_STYLEEXT_EDT_HNear; } | |
465 } | |
466 switch (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_CMB_EditVAlignMask) { | |
467 case FWL_STYLEEXT_CMB_EditVCenter: { | |
468 dwAdd |= FWL_STYLEEXT_EDT_VCenter; | |
469 break; | |
470 } | |
471 case FWL_STYLEEXT_CMB_EditVFar: { | |
472 dwAdd |= FWL_STYLEEXT_EDT_VFar; | |
473 break; | |
474 } | |
475 default: { | |
476 dwAdd |= FWL_STYLEEXT_EDT_VNear; | |
477 break; | |
478 } | |
479 } | |
480 if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_CMB_EditJustified) | |
481 dwAdd |= FWL_STYLEEXT_EDT_Justified; | |
482 if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_CMB_EditDistributed) | |
483 dwAdd |= FWL_STYLEEXT_EDT_Distributed; | |
484 | |
485 m_pEdit->ModifyStylesEx(dwAdd, FWL_STYLEEXT_EDT_HAlignMask | | |
486 FWL_STYLEEXT_EDT_HAlignModeMask | | |
487 FWL_STYLEEXT_EDT_VAlignMask); | |
488 } | |
489 | |
490 void CFWL_ComboBox::ResetListItemAlignment() { | |
491 if (!m_pListBox) | |
492 return; | |
493 | |
494 uint32_t dwAdd = 0; | |
495 switch (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_CMB_ListItemAlignMask) { | |
496 case FWL_STYLEEXT_CMB_ListItemCenterAlign: { | |
497 dwAdd |= FWL_STYLEEXT_LTB_CenterAlign; | |
498 break; | |
499 } | |
500 case FWL_STYLEEXT_CMB_ListItemRightAlign: { | |
501 dwAdd |= FWL_STYLEEXT_LTB_RightAlign; | |
502 break; | |
503 } | |
504 default: { | |
505 dwAdd |= FWL_STYLEEXT_LTB_LeftAlign; | |
506 break; | |
507 } | |
508 } | |
509 m_pListBox->ModifyStylesEx(dwAdd, FWL_STYLEEXT_CMB_ListItemAlignMask); | |
510 } | |
511 | |
512 void CFWL_ComboBox::ProcessSelChanged(bool bLButtonUp) { | |
513 m_iCurSel = m_pListBox->GetItemIndex(this, m_pListBox->GetSelItem(0)); | |
514 if (!IsDropDownStyle()) { | |
515 Repaint(&m_rtClient); | |
516 return; | |
517 } | |
518 | |
519 CFWL_ListItem* hItem = m_pListBox->GetItem(this, m_iCurSel); | |
520 if (!hItem) | |
521 return; | |
522 | |
523 CFX_WideString wsText = m_pListBox->GetItemText(this, hItem); | |
524 if (m_pEdit) { | |
525 m_pEdit->SetText(wsText); | |
526 m_pEdit->Update(); | |
527 m_pEdit->SetSelected(); | |
528 } | |
529 | |
530 CFWL_EvtSelectChanged ev(this); | |
531 ev.bLButtonUp = bLButtonUp; | |
532 DispatchEvent(&ev); | |
533 } | |
534 | |
535 void CFWL_ComboBox::InitProxyForm() { | |
536 if (m_pComboBoxProxy) | |
537 return; | |
538 if (!m_pListBox) | |
539 return; | |
540 | |
541 auto prop = pdfium::MakeUnique<CFWL_WidgetProperties>(); | |
542 prop->m_pOwner = this; | |
543 prop->m_dwStyles = FWL_WGTSTYLE_Popup; | |
544 prop->m_dwStates = FWL_WGTSTATE_Invisible; | |
545 | |
546 // TODO(dsinclair): Does this leak? I don't see a delete, but I'm not sure | |
547 // if the SetParent call is going to transfer ownership. | |
548 m_pComboBoxProxy = new CFWL_ComboBoxProxy(this, m_pOwnerApp, std::move(prop), | |
549 m_pListBox.get()); | |
550 m_pListBox->SetParent(m_pComboBoxProxy); | |
551 } | |
552 | |
553 void CFWL_ComboBox::DisForm_InitComboList() { | |
554 if (m_pListBox) | |
555 return; | |
556 | |
557 auto prop = pdfium::MakeUnique<CFWL_WidgetProperties>(); | |
558 prop->m_pParent = this; | |
559 prop->m_dwStyles = FWL_WGTSTYLE_Border | FWL_WGTSTYLE_VScroll; | |
560 prop->m_dwStates = FWL_WGTSTATE_Invisible; | |
561 prop->m_pThemeProvider = m_pProperties->m_pThemeProvider; | |
562 m_pListBox = | |
563 pdfium::MakeUnique<CFWL_ComboList>(m_pOwnerApp, std::move(prop), this); | |
564 } | |
565 | |
566 void CFWL_ComboBox::DisForm_InitComboEdit() { | |
567 if (m_pEdit) | |
568 return; | |
569 | |
570 auto prop = pdfium::MakeUnique<CFWL_WidgetProperties>(); | |
571 prop->m_pParent = this; | |
572 prop->m_pThemeProvider = m_pProperties->m_pThemeProvider; | |
573 | |
574 m_pEdit = | |
575 pdfium::MakeUnique<CFWL_ComboEdit>(m_pOwnerApp, std::move(prop), this); | |
576 m_pEdit->SetOuter(this); | |
577 } | |
578 | |
579 void CFWL_ComboBox::DisForm_ShowDropList(bool bActivate) { | |
580 if (DisForm_IsDropListVisible() == bActivate) | |
581 return; | |
582 | |
583 if (bActivate) { | |
584 CFWL_Event preEvent(CFWL_Event::Type::PreDropDown, this); | |
585 DispatchEvent(&preEvent); | |
586 | |
587 CFWL_ComboList* pComboList = m_pListBox.get(); | |
588 int32_t iItems = pComboList->CountItems(nullptr); | |
589 if (iItems < 1) | |
590 return; | |
591 | |
592 ResetListItemAlignment(); | |
593 pComboList->ChangeSelected(m_iCurSel); | |
594 | |
595 FX_FLOAT fItemHeight = pComboList->CalcItemHeight(); | |
596 FX_FLOAT fBorder = GetBorderSize(true); | |
597 FX_FLOAT fPopupMin = 0.0f; | |
598 if (iItems > 3) | |
599 fPopupMin = fItemHeight * 3 + fBorder * 2; | |
600 | |
601 FX_FLOAT fPopupMax = fItemHeight * iItems + fBorder * 2; | |
602 CFX_RectF rtList; | |
603 rtList.left = m_rtClient.left; | |
604 rtList.width = m_pProperties->m_rtWidget.width; | |
605 rtList.top = 0; | |
606 rtList.height = 0; | |
607 GetPopupPos(fPopupMin, fPopupMax, m_pProperties->m_rtWidget, rtList); | |
608 | |
609 m_pListBox->SetWidgetRect(rtList); | |
610 m_pListBox->Update(); | |
611 } else { | |
612 SetFocus(true); | |
613 } | |
614 | |
615 if (bActivate) { | |
616 m_pListBox->RemoveStates(FWL_WGTSTATE_Invisible); | |
617 CFWL_Event postEvent(CFWL_Event::Type::PostDropDown, this); | |
618 DispatchEvent(&postEvent); | |
619 } else { | |
620 m_pListBox->SetStates(FWL_WGTSTATE_Invisible); | |
621 } | |
622 | |
623 CFX_RectF rect = m_pListBox->GetWidgetRect(); | |
624 rect.Inflate(2, 2); | |
625 Repaint(&rect); | |
626 } | |
627 | |
628 void CFWL_ComboBox::DisForm_ModifyStylesEx(uint32_t dwStylesExAdded, | |
629 uint32_t dwStylesExRemoved) { | |
630 if (!m_pEdit) | |
631 DisForm_InitComboEdit(); | |
632 | |
633 bool bAddDropDown = !!(dwStylesExAdded & FWL_STYLEEXT_CMB_DropDown); | |
634 bool bDelDropDown = !!(dwStylesExRemoved & FWL_STYLEEXT_CMB_DropDown); | |
635 | |
636 dwStylesExRemoved &= ~FWL_STYLEEXT_CMB_DropDown; | |
637 m_pProperties->m_dwStyleExes |= FWL_STYLEEXT_CMB_DropDown; | |
638 | |
639 if (bAddDropDown) | |
640 m_pEdit->ModifyStylesEx(0, FWL_STYLEEXT_EDT_ReadOnly); | |
641 else if (bDelDropDown) | |
642 m_pEdit->ModifyStylesEx(FWL_STYLEEXT_EDT_ReadOnly, 0); | |
643 CFWL_Widget::ModifyStylesEx(dwStylesExAdded, dwStylesExRemoved); | |
644 } | |
645 | |
646 void CFWL_ComboBox::DisForm_Update() { | |
647 if (m_iLock) | |
648 return; | |
649 if (m_pEdit) | |
650 ResetEditAlignment(); | |
651 ResetTheme(); | |
652 Layout(); | |
653 } | |
654 | |
655 FWL_WidgetHit CFWL_ComboBox::DisForm_HitTest(FX_FLOAT fx, FX_FLOAT fy) { | |
656 CFX_RectF rect; | |
657 rect.Set(0, 0, m_pProperties->m_rtWidget.width - m_rtBtn.width, | |
658 m_pProperties->m_rtWidget.height); | |
659 if (rect.Contains(fx, fy)) | |
660 return FWL_WidgetHit::Edit; | |
661 if (m_rtBtn.Contains(fx, fy)) | |
662 return FWL_WidgetHit::Client; | |
663 if (DisForm_IsDropListVisible()) { | |
664 rect = m_pListBox->GetWidgetRect(); | |
665 if (rect.Contains(fx, fy)) | |
666 return FWL_WidgetHit::Client; | |
667 } | |
668 return FWL_WidgetHit::Unknown; | |
669 } | |
670 | |
671 void CFWL_ComboBox::DisForm_DrawWidget(CFX_Graphics* pGraphics, | |
672 const CFX_Matrix* pMatrix) { | |
673 IFWL_ThemeProvider* pTheme = m_pProperties->m_pThemeProvider; | |
674 CFX_Matrix mtOrg; | |
675 mtOrg.Set(1, 0, 0, 1, 0, 0); | |
676 if (pMatrix) | |
677 mtOrg = *pMatrix; | |
678 | |
679 pGraphics->SaveGraphState(); | |
680 pGraphics->ConcatMatrix(&mtOrg); | |
681 if (!m_rtBtn.IsEmpty(0.1f)) { | |
682 CFWL_ThemeBackground param; | |
683 param.m_pWidget = this; | |
684 param.m_iPart = CFWL_Part::DropDownButton; | |
685 param.m_dwStates = m_iBtnState; | |
686 param.m_pGraphics = pGraphics; | |
687 param.m_rtPart = m_rtBtn; | |
688 pTheme->DrawBackground(¶m); | |
689 } | |
690 pGraphics->RestoreGraphState(); | |
691 | |
692 if (m_pEdit) { | |
693 CFX_RectF rtEdit = m_pEdit->GetWidgetRect(); | |
694 CFX_Matrix mt; | |
695 mt.Set(1, 0, 0, 1, rtEdit.left, rtEdit.top); | |
696 mt.Concat(mtOrg); | |
697 m_pEdit->DrawWidget(pGraphics, &mt); | |
698 } | |
699 if (m_pListBox && DisForm_IsDropListVisible()) { | |
700 CFX_RectF rtList = m_pListBox->GetWidgetRect(); | |
701 CFX_Matrix mt; | |
702 mt.Set(1, 0, 0, 1, rtList.left, rtList.top); | |
703 mt.Concat(mtOrg); | |
704 m_pListBox->DrawWidget(pGraphics, &mt); | |
705 } | |
706 } | |
707 | |
708 CFX_RectF CFWL_ComboBox::DisForm_GetBBox() const { | |
709 CFX_RectF rect = m_pProperties->m_rtWidget; | |
710 if (!m_pListBox || !DisForm_IsDropListVisible()) | |
711 return rect; | |
712 | |
713 CFX_RectF rtList = m_pListBox->GetWidgetRect(); | |
714 rtList.Offset(rect.left, rect.top); | |
715 rect.Union(rtList); | |
716 return rect; | |
717 } | |
718 | |
719 void CFWL_ComboBox::DisForm_Layout() { | |
720 GetClientRect(m_rtClient); | |
721 m_rtContent = m_rtClient; | |
722 FX_FLOAT* pFWidth = static_cast<FX_FLOAT*>( | |
723 GetThemeCapacity(CFWL_WidgetCapacity::ScrollBarWidth)); | |
724 if (!pFWidth) | |
725 return; | |
726 | |
727 FX_FLOAT borderWidth = 1; | |
728 FX_FLOAT fBtn = *pFWidth; | |
729 if (!(GetStylesEx() & FWL_STYLEEXT_CMB_ReadOnly)) { | |
730 m_rtBtn.Set(m_rtClient.right() - fBtn, m_rtClient.top + borderWidth, | |
731 fBtn - borderWidth, m_rtClient.height - 2 * borderWidth); | |
732 } | |
733 | |
734 CFX_RectF* pUIMargin = | |
735 static_cast<CFX_RectF*>(GetThemeCapacity(CFWL_WidgetCapacity::UIMargin)); | |
736 if (pUIMargin) { | |
737 m_rtContent.Deflate(pUIMargin->left, pUIMargin->top, pUIMargin->width, | |
738 pUIMargin->height); | |
739 } | |
740 | |
741 if (!IsDropDownStyle() || !m_pEdit) | |
742 return; | |
743 | |
744 CFX_RectF rtEdit; | |
745 rtEdit.Set(m_rtContent.left, m_rtContent.top, m_rtContent.width - fBtn, | |
746 m_rtContent.height); | |
747 m_pEdit->SetWidgetRect(rtEdit); | |
748 | |
749 if (m_iCurSel >= 0) { | |
750 CFWL_ListItem* hItem = m_pListBox->GetItem(this, m_iCurSel); | |
751 CFX_WideString wsText = m_pListBox->GetDataProviderItemText(hItem); | |
752 m_pEdit->LockUpdate(); | |
753 m_pEdit->SetText(wsText); | |
754 m_pEdit->UnlockUpdate(); | |
755 } | |
756 m_pEdit->Update(); | |
757 } | |
758 | |
759 void CFWL_ComboBox::OnProcessMessage(CFWL_Message* pMessage) { | |
760 if (m_pWidgetMgr->IsFormDisabled()) { | |
761 DisForm_OnProcessMessage(pMessage); | |
762 return; | |
763 } | |
764 if (!pMessage) | |
765 return; | |
766 | |
767 switch (pMessage->GetType()) { | |
768 case CFWL_Message::Type::SetFocus: | |
769 OnFocusChanged(pMessage, true); | |
770 break; | |
771 case CFWL_Message::Type::KillFocus: | |
772 OnFocusChanged(pMessage, false); | |
773 break; | |
774 case CFWL_Message::Type::Mouse: { | |
775 CFWL_MsgMouse* pMsg = static_cast<CFWL_MsgMouse*>(pMessage); | |
776 switch (pMsg->m_dwCmd) { | |
777 case FWL_MouseCommand::LeftButtonDown: | |
778 OnLButtonDown(pMsg); | |
779 break; | |
780 case FWL_MouseCommand::LeftButtonUp: | |
781 OnLButtonUp(pMsg); | |
782 break; | |
783 case FWL_MouseCommand::Move: | |
784 OnMouseMove(pMsg); | |
785 break; | |
786 case FWL_MouseCommand::Leave: | |
787 OnMouseLeave(pMsg); | |
788 break; | |
789 default: | |
790 break; | |
791 } | |
792 break; | |
793 } | |
794 case CFWL_Message::Type::Key: | |
795 OnKey(static_cast<CFWL_MsgKey*>(pMessage)); | |
796 break; | |
797 default: | |
798 break; | |
799 } | |
800 | |
801 CFWL_Widget::OnProcessMessage(pMessage); | |
802 } | |
803 | |
804 void CFWL_ComboBox::OnProcessEvent(CFWL_Event* pEvent) { | |
805 CFWL_Event::Type type = pEvent->GetType(); | |
806 if (type == CFWL_Event::Type::Scroll) { | |
807 CFWL_EvtScroll* pScrollEvent = static_cast<CFWL_EvtScroll*>(pEvent); | |
808 CFWL_EvtScroll pScrollEv(this); | |
809 pScrollEv.m_iScrollCode = pScrollEvent->m_iScrollCode; | |
810 pScrollEv.m_fPos = pScrollEvent->m_fPos; | |
811 DispatchEvent(&pScrollEv); | |
812 } else if (type == CFWL_Event::Type::TextChanged) { | |
813 CFWL_Event pTemp(CFWL_Event::Type::EditChanged, this); | |
814 DispatchEvent(&pTemp); | |
815 } | |
816 } | |
817 | |
818 void CFWL_ComboBox::OnDrawWidget(CFX_Graphics* pGraphics, | |
819 const CFX_Matrix* pMatrix) { | |
820 DrawWidget(pGraphics, pMatrix); | |
821 } | |
822 | |
823 void CFWL_ComboBox::OnFocusChanged(CFWL_Message* pMsg, bool bSet) { | |
824 if (bSet) { | |
825 m_pProperties->m_dwStates |= FWL_WGTSTATE_Focused; | |
826 if (IsDropDownStyle() && pMsg->m_pSrcTarget != m_pListBox.get()) { | |
827 if (!m_pEdit) | |
828 return; | |
829 m_pEdit->SetSelected(); | |
830 return; | |
831 } | |
832 | |
833 Repaint(&m_rtClient); | |
834 return; | |
835 } | |
836 | |
837 m_pProperties->m_dwStates &= ~FWL_WGTSTATE_Focused; | |
838 if (!IsDropDownStyle() || pMsg->m_pDstTarget == m_pListBox.get()) { | |
839 Repaint(&m_rtClient); | |
840 return; | |
841 } | |
842 if (!m_pEdit) | |
843 return; | |
844 | |
845 m_pEdit->FlagFocus(false); | |
846 m_pEdit->ClearSelected(); | |
847 } | |
848 | |
849 void CFWL_ComboBox::OnLButtonDown(CFWL_MsgMouse* pMsg) { | |
850 if (m_pProperties->m_dwStates & FWL_WGTSTATE_Disabled) | |
851 return; | |
852 | |
853 CFX_RectF& rtBtn = IsDropDownStyle() ? m_rtBtn : m_rtClient; | |
854 if (!rtBtn.Contains(pMsg->m_fx, pMsg->m_fy)) | |
855 return; | |
856 | |
857 if (IsDropDownStyle() && m_pEdit) | |
858 MatchEditText(); | |
859 | |
860 m_bLButtonDown = true; | |
861 m_iBtnState = CFWL_PartState_Pressed; | |
862 Repaint(&m_rtClient); | |
863 | |
864 ShowDropList(true); | |
865 m_iBtnState = CFWL_PartState_Normal; | |
866 Repaint(&m_rtClient); | |
867 } | |
868 | |
869 void CFWL_ComboBox::OnLButtonUp(CFWL_MsgMouse* pMsg) { | |
870 m_bLButtonDown = false; | |
871 if (m_rtBtn.Contains(pMsg->m_fx, pMsg->m_fy)) | |
872 m_iBtnState = CFWL_PartState_Hovered; | |
873 else | |
874 m_iBtnState = CFWL_PartState_Normal; | |
875 | |
876 Repaint(&m_rtBtn); | |
877 } | |
878 | |
879 void CFWL_ComboBox::OnMouseMove(CFWL_MsgMouse* pMsg) { | |
880 int32_t iOldState = m_iBtnState; | |
881 if (m_rtBtn.Contains(pMsg->m_fx, pMsg->m_fy)) { | |
882 m_iBtnState = | |
883 m_bLButtonDown ? CFWL_PartState_Pressed : CFWL_PartState_Hovered; | |
884 } else { | |
885 m_iBtnState = CFWL_PartState_Normal; | |
886 } | |
887 if ((iOldState != m_iBtnState) && | |
888 !((m_pProperties->m_dwStates & FWL_WGTSTATE_Disabled) == | |
889 FWL_WGTSTATE_Disabled)) { | |
890 Repaint(&m_rtBtn); | |
891 } | |
892 } | |
893 | |
894 void CFWL_ComboBox::OnMouseLeave(CFWL_MsgMouse* pMsg) { | |
895 if (!IsDropListVisible() && | |
896 !((m_pProperties->m_dwStates & FWL_WGTSTATE_Disabled) == | |
897 FWL_WGTSTATE_Disabled)) { | |
898 m_iBtnState = CFWL_PartState_Normal; | |
899 Repaint(&m_rtBtn); | |
900 } | |
901 } | |
902 | |
903 void CFWL_ComboBox::OnKey(CFWL_MsgKey* pMsg) { | |
904 uint32_t dwKeyCode = pMsg->m_dwKeyCode; | |
905 if (dwKeyCode == FWL_VKEY_Tab) | |
906 return; | |
907 if (pMsg->m_pDstTarget == this) | |
908 DoSubCtrlKey(pMsg); | |
909 } | |
910 | |
911 void CFWL_ComboBox::DoSubCtrlKey(CFWL_MsgKey* pMsg) { | |
912 uint32_t dwKeyCode = pMsg->m_dwKeyCode; | |
913 const bool bUp = dwKeyCode == FWL_VKEY_Up; | |
914 const bool bDown = dwKeyCode == FWL_VKEY_Down; | |
915 if (bUp || bDown) { | |
916 int32_t iCount = m_pListBox->CountItems(nullptr); | |
917 if (iCount < 1) | |
918 return; | |
919 | |
920 bool bMatchEqual = false; | |
921 int32_t iCurSel = m_iCurSel; | |
922 bool bDropDown = IsDropDownStyle(); | |
923 if (bDropDown && m_pEdit) { | |
924 CFX_WideString wsText = m_pEdit->GetText(); | |
925 iCurSel = m_pListBox->MatchItem(wsText); | |
926 if (iCurSel >= 0) { | |
927 CFWL_ListItem* hItem = m_pListBox->GetItem(this, iCurSel); | |
928 CFX_WideString wsTemp = m_pListBox->GetDataProviderItemText(hItem); | |
929 bMatchEqual = wsText == wsTemp; | |
930 } | |
931 } | |
932 if (iCurSel < 0) { | |
933 iCurSel = 0; | |
934 } else if (!bDropDown || bMatchEqual) { | |
935 if ((bUp && iCurSel == 0) || (bDown && iCurSel == iCount - 1)) | |
936 return; | |
937 if (bUp) | |
938 iCurSel--; | |
939 else | |
940 iCurSel++; | |
941 } | |
942 m_iCurSel = iCurSel; | |
943 if (bDropDown && m_pEdit) | |
944 SyncEditText(m_iCurSel); | |
945 else | |
946 Repaint(&m_rtClient); | |
947 return; | |
948 } | |
949 | |
950 if (IsDropDownStyle()) | |
951 m_pEdit->GetDelegate()->OnProcessMessage(pMsg); | |
952 } | |
953 | |
954 void CFWL_ComboBox::DisForm_OnProcessMessage(CFWL_Message* pMessage) { | |
955 if (!pMessage) | |
956 return; | |
957 | |
958 bool backDefault = true; | |
959 switch (pMessage->GetType()) { | |
960 case CFWL_Message::Type::SetFocus: { | |
961 backDefault = false; | |
962 DisForm_OnFocusChanged(pMessage, true); | |
963 break; | |
964 } | |
965 case CFWL_Message::Type::KillFocus: { | |
966 backDefault = false; | |
967 DisForm_OnFocusChanged(pMessage, false); | |
968 break; | |
969 } | |
970 case CFWL_Message::Type::Mouse: { | |
971 backDefault = false; | |
972 CFWL_MsgMouse* pMsg = static_cast<CFWL_MsgMouse*>(pMessage); | |
973 switch (pMsg->m_dwCmd) { | |
974 case FWL_MouseCommand::LeftButtonDown: | |
975 DisForm_OnLButtonDown(pMsg); | |
976 break; | |
977 case FWL_MouseCommand::LeftButtonUp: | |
978 OnLButtonUp(pMsg); | |
979 break; | |
980 default: | |
981 break; | |
982 } | |
983 break; | |
984 } | |
985 case CFWL_Message::Type::Key: { | |
986 backDefault = false; | |
987 CFWL_MsgKey* pKey = static_cast<CFWL_MsgKey*>(pMessage); | |
988 if (pKey->m_dwCmd == FWL_KeyCommand::KeyUp) | |
989 break; | |
990 if (DisForm_IsDropListVisible() && | |
991 pKey->m_dwCmd == FWL_KeyCommand::KeyDown) { | |
992 bool bListKey = pKey->m_dwKeyCode == FWL_VKEY_Up || | |
993 pKey->m_dwKeyCode == FWL_VKEY_Down || | |
994 pKey->m_dwKeyCode == FWL_VKEY_Return || | |
995 pKey->m_dwKeyCode == FWL_VKEY_Escape; | |
996 if (bListKey) { | |
997 m_pListBox->GetDelegate()->OnProcessMessage(pMessage); | |
998 break; | |
999 } | |
1000 } | |
1001 DisForm_OnKey(pKey); | |
1002 break; | |
1003 } | |
1004 default: | |
1005 break; | |
1006 } | |
1007 if (backDefault) | |
1008 CFWL_Widget::OnProcessMessage(pMessage); | |
1009 } | |
1010 | |
1011 void CFWL_ComboBox::DisForm_OnLButtonDown(CFWL_MsgMouse* pMsg) { | |
1012 bool bDropDown = DisForm_IsDropListVisible(); | |
1013 CFX_RectF& rtBtn = bDropDown ? m_rtBtn : m_rtClient; | |
1014 if (!rtBtn.Contains(pMsg->m_fx, pMsg->m_fy)) | |
1015 return; | |
1016 | |
1017 if (DisForm_IsDropListVisible()) { | |
1018 DisForm_ShowDropList(false); | |
1019 return; | |
1020 } | |
1021 if (m_pEdit) | |
1022 MatchEditText(); | |
1023 DisForm_ShowDropList(true); | |
1024 } | |
1025 | |
1026 void CFWL_ComboBox::DisForm_OnFocusChanged(CFWL_Message* pMsg, bool bSet) { | |
1027 if (bSet) { | |
1028 m_pProperties->m_dwStates |= FWL_WGTSTATE_Focused; | |
1029 if ((m_pEdit->GetStates() & FWL_WGTSTATE_Focused) == 0) { | |
1030 CFWL_MsgSetFocus msg(nullptr, m_pEdit.get()); | |
1031 m_pEdit->GetDelegate()->OnProcessMessage(&msg); | |
1032 } | |
1033 } else { | |
1034 m_pProperties->m_dwStates &= ~FWL_WGTSTATE_Focused; | |
1035 DisForm_ShowDropList(false); | |
1036 CFWL_MsgKillFocus msg(m_pEdit.get()); | |
1037 m_pEdit->GetDelegate()->OnProcessMessage(&msg); | |
1038 } | |
1039 } | |
1040 | |
1041 void CFWL_ComboBox::DisForm_OnKey(CFWL_MsgKey* pMsg) { | |
1042 uint32_t dwKeyCode = pMsg->m_dwKeyCode; | |
1043 const bool bUp = dwKeyCode == FWL_VKEY_Up; | |
1044 const bool bDown = dwKeyCode == FWL_VKEY_Down; | |
1045 if (bUp || bDown) { | |
1046 CFWL_ComboList* pComboList = m_pListBox.get(); | |
1047 int32_t iCount = pComboList->CountItems(nullptr); | |
1048 if (iCount < 1) | |
1049 return; | |
1050 | |
1051 bool bMatchEqual = false; | |
1052 int32_t iCurSel = m_iCurSel; | |
1053 if (m_pEdit) { | |
1054 CFX_WideString wsText = m_pEdit->GetText(); | |
1055 iCurSel = pComboList->MatchItem(wsText); | |
1056 if (iCurSel >= 0) { | |
1057 CFWL_ListItem* item = m_pListBox->GetSelItem(iCurSel); | |
1058 CFX_WideString wsTemp = m_pListBox->GetDataProviderItemText(item); | |
1059 bMatchEqual = wsText == wsTemp; | |
1060 } | |
1061 } | |
1062 if (iCurSel < 0) { | |
1063 iCurSel = 0; | |
1064 } else if (bMatchEqual) { | |
1065 if ((bUp && iCurSel == 0) || (bDown && iCurSel == iCount - 1)) | |
1066 return; | |
1067 if (bUp) | |
1068 iCurSel--; | |
1069 else | |
1070 iCurSel++; | |
1071 } | |
1072 m_iCurSel = iCurSel; | |
1073 SyncEditText(m_iCurSel); | |
1074 return; | |
1075 } | |
1076 if (m_pEdit) | |
1077 m_pEdit->GetDelegate()->OnProcessMessage(pMsg); | |
1078 } | |
OLD | NEW |