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

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

Issue 2559173002: Move xfa/fwl/core to xfa/fwl. (Closed)
Patch Set: 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
« no previous file with comments | « xfa/fwl/core/cfwl_combobox.h ('k') | xfa/fwl/core/cfwl_comboboxproxy.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(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(&param);
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(&param);
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(&param);
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(&param);
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 }
OLDNEW
« no previous file with comments | « xfa/fwl/core/cfwl_combobox.h ('k') | xfa/fwl/core/cfwl_comboboxproxy.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698