Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(251)

Side by Side Diff: xfa/fwl/core/cfwl_combobox.cpp

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

Powered by Google App Engine
This is Rietveld 408576698