blob: 67d2d88f50ee8fcf6c8ee3525680fdaeee31d06c [file] [log] [blame]
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001// 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.
Lei Zhanga6d9f0e2015-06-13 00:48:38 -07004
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07005// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6
Dan Sinclairc411eb92017-07-25 09:39:30 -04007#include "fpdfsdk/pwl/cpwl_combo_box.h"
Lei Zhangc2fb35f2016-01-05 16:46:58 -08008
Lei Zhang7bef7c82017-05-31 23:52:00 -07009#include <algorithm>
Henrique Nakashimaf1eae2c2017-06-29 11:18:49 -040010#include <sstream>
Lei Zhang7bef7c82017-05-31 23:52:00 -070011
dsinclair74a34fc2016-09-29 16:41:42 -070012#include "core/fxge/cfx_pathdata.h"
13#include "core/fxge/cfx_renderdevice.h"
Dan Sinclairc411eb92017-07-25 09:39:30 -040014#include "fpdfsdk/pwl/cpwl_edit.h"
15#include "fpdfsdk/pwl/cpwl_edit_ctrl.h"
16#include "fpdfsdk/pwl/cpwl_list_box.h"
17#include "fpdfsdk/pwl/cpwl_list_impl.h"
18#include "fpdfsdk/pwl/cpwl_wnd.h"
Lei Zhangc2fb35f2016-01-05 16:46:58 -080019#include "public/fpdf_fwlevent.h"
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070020
Dan Sinclaira9e28432017-07-05 14:18:14 -040021namespace {
22
23constexpr float kDefaultFontSize = 12.0f;
24constexpr float kTriangleHalfLength = 3.0f;
Dan Sinclair951b1112017-10-02 10:38:55 -040025constexpr int kDefaultButtonWidth = 13;
Dan Sinclaira9e28432017-07-05 14:18:14 -040026
27} // namespace
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070028
Dan Sinclairf528eee2017-02-14 11:52:07 -050029bool CPWL_CBListBox::OnLButtonUp(const CFX_PointF& point, uint32_t nFlag) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -070030 CPWL_Wnd::OnLButtonUp(point, nFlag);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070031
dsinclair36177512016-07-19 10:16:10 -070032 if (!m_bMouseDown)
tsepez4cf55152016-11-02 14:37:54 -070033 return true;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070034
dsinclair36177512016-07-19 10:16:10 -070035 ReleaseCapture();
tsepez4cf55152016-11-02 14:37:54 -070036 m_bMouseDown = false;
Lei Zhanga6d9f0e2015-06-13 00:48:38 -070037
dsinclair36177512016-07-19 10:16:10 -070038 if (!ClientHitTest(point))
tsepez4cf55152016-11-02 14:37:54 -070039 return true;
dsinclair36177512016-07-19 10:16:10 -070040 if (CPWL_Wnd* pParent = GetParentWindow())
Dan Sinclair7f6bec92017-07-05 14:13:16 -040041 pParent->NotifyLButtonUp(this, point);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070042
Dan Sinclair2b444412017-07-06 13:56:35 -040043 return !OnNotifySelectionChanged(false, nFlag);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070044}
45
Dan Sinclair07dbf432017-07-06 11:47:26 -040046bool CPWL_CBListBox::IsMovementKey(uint16_t nChar) const {
Nico Weber9d8ec5a2015-08-04 13:00:21 -070047 switch (nChar) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -070048 case FWL_VKEY_Up:
49 case FWL_VKEY_Down:
50 case FWL_VKEY_Home:
51 case FWL_VKEY_Left:
52 case FWL_VKEY_End:
53 case FWL_VKEY_Right:
Dan Sinclair07dbf432017-07-06 11:47:26 -040054 return true;
dsinclair36177512016-07-19 10:16:10 -070055 default:
tsepez4cf55152016-11-02 14:37:54 -070056 return false;
Nico Weber9d8ec5a2015-08-04 13:00:21 -070057 }
Dan Sinclair07dbf432017-07-06 11:47:26 -040058}
59
60bool CPWL_CBListBox::OnMovementKeyDown(uint16_t nChar, uint32_t nFlag) {
61 ASSERT(IsMovementKey(nChar));
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070062
Nico Weber9d8ec5a2015-08-04 13:00:21 -070063 switch (nChar) {
64 case FWL_VKEY_Up:
65 m_pList->OnVK_UP(IsSHIFTpressed(nFlag), IsCTRLpressed(nFlag));
66 break;
67 case FWL_VKEY_Down:
68 m_pList->OnVK_DOWN(IsSHIFTpressed(nFlag), IsCTRLpressed(nFlag));
69 break;
70 case FWL_VKEY_Home:
71 m_pList->OnVK_HOME(IsSHIFTpressed(nFlag), IsCTRLpressed(nFlag));
72 break;
73 case FWL_VKEY_Left:
74 m_pList->OnVK_LEFT(IsSHIFTpressed(nFlag), IsCTRLpressed(nFlag));
75 break;
76 case FWL_VKEY_End:
77 m_pList->OnVK_END(IsSHIFTpressed(nFlag), IsCTRLpressed(nFlag));
78 break;
79 case FWL_VKEY_Right:
80 m_pList->OnVK_RIGHT(IsSHIFTpressed(nFlag), IsCTRLpressed(nFlag));
81 break;
Nico Weber9d8ec5a2015-08-04 13:00:21 -070082 }
Dan Sinclair2b444412017-07-06 13:56:35 -040083 return OnNotifySelectionChanged(true, nFlag);
Nico Weber9d8ec5a2015-08-04 13:00:21 -070084}
85
Dan Sinclair16fea942017-07-06 11:56:37 -040086bool CPWL_CBListBox::IsChar(uint16_t nChar, uint32_t nFlag) const {
87 return m_pList->OnChar(nChar, IsSHIFTpressed(nFlag), IsCTRLpressed(nFlag));
88}
89
90bool CPWL_CBListBox::OnCharNotify(uint16_t nChar, uint32_t nFlag) {
dsinclair36177512016-07-19 10:16:10 -070091 if (CPWL_ComboBox* pComboBox = (CPWL_ComboBox*)GetParentWindow())
Nico Weber9d8ec5a2015-08-04 13:00:21 -070092 pComboBox->SetSelectText();
Nico Weber9d8ec5a2015-08-04 13:00:21 -070093
Dan Sinclair2b444412017-07-06 13:56:35 -040094 return OnNotifySelectionChanged(true, nFlag);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070095}
96
Nico Weber9d8ec5a2015-08-04 13:00:21 -070097void CPWL_CBButton::DrawThisAppearance(CFX_RenderDevice* pDevice,
Lei Zhangeb14e042017-08-15 13:56:43 -070098 const CFX_Matrix& mtUser2Device) {
99 CPWL_Wnd::DrawThisAppearance(pDevice, mtUser2Device);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700100
Tom Sepez281a9ea2016-02-26 14:24:28 -0800101 CFX_FloatRect rectWnd = CPWL_Wnd::GetWindowRect();
Lei Zhanga6d9f0e2015-06-13 00:48:38 -0700102
Henrique Nakashimaf1eae2c2017-06-29 11:18:49 -0400103 if (!IsVisible() || rectWnd.IsEmpty())
104 return;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700105
Henrique Nakashimaf1eae2c2017-06-29 11:18:49 -0400106 CFX_PointF ptCenter = GetCenterPoint();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700107
Dan Sinclaira9e28432017-07-05 14:18:14 -0400108 CFX_PointF pt1(ptCenter.x - kTriangleHalfLength,
109 ptCenter.y + kTriangleHalfLength * 0.5f);
110 CFX_PointF pt2(ptCenter.x + kTriangleHalfLength,
111 ptCenter.y + kTriangleHalfLength * 0.5f);
112 CFX_PointF pt3(ptCenter.x, ptCenter.y - kTriangleHalfLength * 0.5f);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700113
Dan Sinclaira9e28432017-07-05 14:18:14 -0400114 if (IsFloatBigger(rectWnd.right - rectWnd.left, kTriangleHalfLength * 2) &&
115 IsFloatBigger(rectWnd.top - rectWnd.bottom, kTriangleHalfLength)) {
Henrique Nakashimaf1eae2c2017-06-29 11:18:49 -0400116 CFX_PathData path;
117 path.AppendPoint(pt1, FXPT_TYPE::MoveTo, false);
118 path.AppendPoint(pt2, FXPT_TYPE::LineTo, false);
119 path.AppendPoint(pt3, FXPT_TYPE::LineTo, false);
120 path.AppendPoint(pt1, FXPT_TYPE::LineTo, false);
121
Lei Zhangeb14e042017-08-15 13:56:43 -0700122 pDevice->DrawPath(&path, &mtUser2Device, nullptr,
Henrique Nakashimaf1eae2c2017-06-29 11:18:49 -0400123 PWL_DEFAULT_BLACKCOLOR.ToFXColor(GetTransparency()), 0,
124 FXFILL_ALTERNATE);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700125 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700126}
127
Dan Sinclairf528eee2017-02-14 11:52:07 -0500128bool CPWL_CBButton::OnLButtonDown(const CFX_PointF& point, uint32_t nFlag) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700129 CPWL_Wnd::OnLButtonDown(point, nFlag);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700130
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700131 SetCapture();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700132
Dan Sinclair7f6bec92017-07-05 14:13:16 -0400133 if (CPWL_Wnd* pParent = GetParentWindow())
134 pParent->NotifyLButtonDown(this, point);
Lei Zhanga6d9f0e2015-06-13 00:48:38 -0700135
tsepez4cf55152016-11-02 14:37:54 -0700136 return true;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700137}
138
Dan Sinclairf528eee2017-02-14 11:52:07 -0500139bool CPWL_CBButton::OnLButtonUp(const CFX_PointF& point, uint32_t nFlag) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700140 CPWL_Wnd::OnLButtonUp(point, nFlag);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700141
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700142 ReleaseCapture();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700143
tsepez4cf55152016-11-02 14:37:54 -0700144 return true;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700145}
146
Lei Zhang35162562017-06-09 01:04:52 -0700147CPWL_ComboBox::CPWL_ComboBox() {}
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700148
Tom Sepezb084c1f2017-05-12 14:04:06 -0700149CPWL_ComboBox::~CPWL_ComboBox() {}
150
Ryan Harrison275e2602017-09-18 14:23:18 -0400151ByteString CPWL_ComboBox::GetClassName() const {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700152 return "CPWL_ComboBox";
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700153}
154
Tom Sepezbf157302017-09-15 13:26:32 -0700155void CPWL_ComboBox::OnCreate(CreateParams* pParamsToAdjust) {
156 pParamsToAdjust->dwFlags &= ~PWS_HSCROLL;
157 pParamsToAdjust->dwFlags &= ~PWS_VSCROLL;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700158}
159
Lei Zhang35162562017-06-09 01:04:52 -0700160void CPWL_ComboBox::OnDestroy() {
161 // Until cleanup takes place in the virtual destructor for CPWL_Wnd
162 // subclasses, implement the virtual OnDestroy method that does the
163 // cleanup first, then invokes the superclass OnDestroy ... gee,
164 // like a dtor would.
165 m_pList.Release();
166 m_pButton.Release();
167 m_pEdit.Release();
168 CPWL_Wnd::OnDestroy();
169}
170
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700171void CPWL_ComboBox::SetFocus() {
172 if (m_pEdit)
173 m_pEdit->SetFocus();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700174}
175
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700176void CPWL_ComboBox::KillFocus() {
Henrique Nakashima55469ae2017-10-04 11:08:45 -0400177 if (!SetPopup(false))
178 return;
179
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700180 CPWL_Wnd::KillFocus();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700181}
182
Ryan Harrison275e2602017-09-18 14:23:18 -0400183WideString CPWL_ComboBox::GetSelectedText() {
Diana Gagedce2d722017-06-20 11:17:11 -0700184 if (m_pEdit)
185 return m_pEdit->GetSelectedText();
186
Ryan Harrison275e2602017-09-18 14:23:18 -0400187 return WideString();
Diana Gagedce2d722017-06-20 11:17:11 -0700188}
189
Ryan Harrison275e2602017-09-18 14:23:18 -0400190void CPWL_ComboBox::ReplaceSelection(const WideString& text) {
Diana Gage1c7f1422017-07-24 11:19:52 -0700191 if (m_pEdit)
Diana Gageab390972017-07-28 17:07:39 -0700192 m_pEdit->ReplaceSelection(text);
Diana Gage1c7f1422017-07-24 11:19:52 -0700193}
194
Ryan Harrison275e2602017-09-18 14:23:18 -0400195WideString CPWL_ComboBox::GetText() const {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700196 if (m_pEdit) {
197 return m_pEdit->GetText();
198 }
Ryan Harrison275e2602017-09-18 14:23:18 -0400199 return WideString();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700200}
201
Ryan Harrison275e2602017-09-18 14:23:18 -0400202void CPWL_ComboBox::SetText(const WideString& text) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700203 if (m_pEdit)
204 m_pEdit->SetText(text);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700205}
206
Ryan Harrison275e2602017-09-18 14:23:18 -0400207void CPWL_ComboBox::AddString(const WideString& str) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700208 if (m_pList)
Dan Sinclair3ebd1212016-03-09 09:59:23 -0500209 m_pList->AddString(str);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700210}
211
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700212int32_t CPWL_ComboBox::GetSelect() const {
213 return m_nSelectItem;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700214}
215
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700216void CPWL_ComboBox::SetSelect(int32_t nItemIndex) {
217 if (m_pList)
218 m_pList->Select(nItemIndex);
219
tsepez067990c2016-09-13 06:46:40 -0700220 m_pEdit->SetText(m_pList->GetText());
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700221 m_nSelectItem = nItemIndex;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700222}
223
Diana Gage4d02e902017-07-20 17:20:31 -0700224void CPWL_ComboBox::SetEditSelection(int32_t nStartChar, int32_t nEndChar) {
tsepez067990c2016-09-13 06:46:40 -0700225 if (m_pEdit)
Diana Gage4d02e902017-07-20 17:20:31 -0700226 m_pEdit->SetSelection(nStartChar, nEndChar);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700227}
228
Diana Gage4d02e902017-07-20 17:20:31 -0700229void CPWL_ComboBox::GetEditSelection(int32_t& nStartChar,
230 int32_t& nEndChar) const {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700231 nStartChar = -1;
232 nEndChar = -1;
233
tsepez067990c2016-09-13 06:46:40 -0700234 if (m_pEdit)
Diana Gage4d02e902017-07-20 17:20:31 -0700235 m_pEdit->GetSelection(nStartChar, nEndChar);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700236}
237
Diana Gage22bf7a52017-07-21 11:33:18 -0700238void CPWL_ComboBox::ClearSelection() {
tsepez067990c2016-09-13 06:46:40 -0700239 if (m_pEdit)
Diana Gage22bf7a52017-07-21 11:33:18 -0700240 m_pEdit->ClearSelection();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700241}
242
Tom Sepezbf157302017-09-15 13:26:32 -0700243void CPWL_ComboBox::CreateChildWnd(const CreateParams& cp) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700244 CreateEdit(cp);
245 CreateButton(cp);
246 CreateListBox(cp);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700247}
248
Tom Sepezbf157302017-09-15 13:26:32 -0700249void CPWL_ComboBox::CreateEdit(const CreateParams& cp) {
Tom Sepezb084c1f2017-05-12 14:04:06 -0700250 if (m_pEdit)
251 return;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700252
Dan Sinclair0fdd1ae2017-07-05 16:00:48 -0400253 m_pEdit = new CPWL_Edit();
Tom Sepezcc205132017-05-16 14:01:47 -0700254 m_pEdit->AttachFFLData(m_pFormFiller.Get());
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700255
Tom Sepezbf157302017-09-15 13:26:32 -0700256 CreateParams ecp = cp;
Tom Sepezb084c1f2017-05-12 14:04:06 -0700257 ecp.pParentWnd = this;
258 ecp.dwFlags = PWS_VISIBLE | PWS_CHILD | PWS_BORDER | PES_CENTER |
259 PES_AUTOSCROLL | PES_UNDO;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700260
Tom Sepezb084c1f2017-05-12 14:04:06 -0700261 if (HasFlag(PWS_AUTOFONTSIZE))
262 ecp.dwFlags |= PWS_AUTOFONTSIZE;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700263
Tom Sepezb084c1f2017-05-12 14:04:06 -0700264 if (!HasFlag(PCBS_ALLOWCUSTOMTEXT))
265 ecp.dwFlags |= PWS_READONLY;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700266
Lei Zhangd24236a2017-06-29 18:28:58 -0700267 ecp.rcRectWnd = CFX_FloatRect();
Tom Sepezb084c1f2017-05-12 14:04:06 -0700268 ecp.dwBorderWidth = 0;
269 ecp.nBorderStyle = BorderStyle::SOLID;
270 m_pEdit->Create(ecp);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700271}
272
Tom Sepezbf157302017-09-15 13:26:32 -0700273void CPWL_ComboBox::CreateButton(const CreateParams& cp) {
Tom Sepezb084c1f2017-05-12 14:04:06 -0700274 if (m_pButton)
275 return;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700276
Tom Sepez45b9ae12017-05-18 08:34:03 -0700277 m_pButton = new CPWL_CBButton;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700278
Tom Sepezbf157302017-09-15 13:26:32 -0700279 CreateParams bcp = cp;
Tom Sepezb084c1f2017-05-12 14:04:06 -0700280 bcp.pParentWnd = this;
281 bcp.dwFlags = PWS_VISIBLE | PWS_CHILD | PWS_BORDER | PWS_BACKGROUND;
Dan Sinclair8e7f9322017-10-16 11:35:42 -0400282 bcp.sBackgroundColor = CFX_Color(CFX_Color::kRGB, 220.0f / 255.0f,
Dan Sinclair7f55a542017-07-13 14:17:10 -0400283 220.0f / 255.0f, 220.0f / 255.0f);
Tom Sepezb084c1f2017-05-12 14:04:06 -0700284 bcp.sBorderColor = PWL_DEFAULT_BLACKCOLOR;
285 bcp.dwBorderWidth = 2;
286 bcp.nBorderStyle = BorderStyle::BEVELED;
287 bcp.eCursorType = FXCT_ARROW;
288 m_pButton->Create(bcp);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700289}
290
Tom Sepezbf157302017-09-15 13:26:32 -0700291void CPWL_ComboBox::CreateListBox(const CreateParams& cp) {
Tom Sepezb084c1f2017-05-12 14:04:06 -0700292 if (m_pList)
293 return;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700294
Tom Sepez45b9ae12017-05-18 08:34:03 -0700295 m_pList = new CPWL_CBListBox();
Tom Sepezcc205132017-05-16 14:01:47 -0700296 m_pList->AttachFFLData(m_pFormFiller.Get());
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700297
Tom Sepezbf157302017-09-15 13:26:32 -0700298 CreateParams lcp = cp;
Tom Sepezb084c1f2017-05-12 14:04:06 -0700299 lcp.pParentWnd = this;
300 lcp.dwFlags =
301 PWS_CHILD | PWS_BORDER | PWS_BACKGROUND | PLBS_HOVERSEL | PWS_VSCROLL;
302 lcp.nBorderStyle = BorderStyle::SOLID;
303 lcp.dwBorderWidth = 1;
304 lcp.eCursorType = FXCT_ARROW;
Lei Zhangd24236a2017-06-29 18:28:58 -0700305 lcp.rcRectWnd = CFX_FloatRect();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700306
Tom Sepezb084c1f2017-05-12 14:04:06 -0700307 if (cp.dwFlags & PWS_AUTOFONTSIZE)
Dan Sinclaira9e28432017-07-05 14:18:14 -0400308 lcp.fFontSize = kDefaultFontSize;
Tom Sepezb084c1f2017-05-12 14:04:06 -0700309 else
310 lcp.fFontSize = cp.fFontSize;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700311
Dan Sinclair8e7f9322017-10-16 11:35:42 -0400312 if (cp.sBorderColor.nColorType == CFX_Color::kTransparent)
Tom Sepezb084c1f2017-05-12 14:04:06 -0700313 lcp.sBorderColor = PWL_DEFAULT_BLACKCOLOR;
314
Dan Sinclair8e7f9322017-10-16 11:35:42 -0400315 if (cp.sBackgroundColor.nColorType == CFX_Color::kTransparent)
Tom Sepezb084c1f2017-05-12 14:04:06 -0700316 lcp.sBackgroundColor = PWL_DEFAULT_WHITECOLOR;
317
318 m_pList->Create(lcp);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700319}
320
Henrique Nakashima55469ae2017-10-04 11:08:45 -0400321bool CPWL_ComboBox::RePosChildWnd() {
322 ObservedPtr thisObserved(this);
323
Lei Zhang7bef7c82017-05-31 23:52:00 -0700324 const CFX_FloatRect rcClient = GetClientRect();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700325 if (m_bPopup) {
Lei Zhang7bef7c82017-05-31 23:52:00 -0700326 const float fOldWindowHeight = m_rcOldWindow.Height();
327 const float fOldClientHeight = fOldWindowHeight - GetBorderWidth() * 2;
328
Tom Sepez281a9ea2016-02-26 14:24:28 -0800329 CFX_FloatRect rcList = CPWL_Wnd::GetWindowRect();
Lei Zhang7bef7c82017-05-31 23:52:00 -0700330 CFX_FloatRect rcButton = rcClient;
331 rcButton.left =
Dan Sinclair951b1112017-10-02 10:38:55 -0400332 std::max(rcButton.right - kDefaultButtonWidth, rcClient.left);
Lei Zhang7bef7c82017-05-31 23:52:00 -0700333 CFX_FloatRect rcEdit = rcClient;
334 rcEdit.right = std::max(rcButton.left - 1.0f, rcEdit.left);
335 if (m_bBottom) {
336 rcButton.bottom = rcButton.top - fOldClientHeight;
337 rcEdit.bottom = rcEdit.top - fOldClientHeight;
338 rcList.top -= fOldWindowHeight;
339 } else {
340 rcButton.top = rcButton.bottom + fOldClientHeight;
341 rcEdit.top = rcEdit.bottom + fOldClientHeight;
342 rcList.bottom += fOldWindowHeight;
Tom Sepez2f2ffec2015-07-23 14:42:09 -0700343 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700344
Henrique Nakashima55469ae2017-10-04 11:08:45 -0400345 if (m_pButton) {
tsepez4cf55152016-11-02 14:37:54 -0700346 m_pButton->Move(rcButton, true, false);
Henrique Nakashima55469ae2017-10-04 11:08:45 -0400347 if (!thisObserved)
348 return false;
349 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700350
Henrique Nakashima55469ae2017-10-04 11:08:45 -0400351 if (m_pEdit) {
tsepez4cf55152016-11-02 14:37:54 -0700352 m_pEdit->Move(rcEdit, true, false);
Henrique Nakashima55469ae2017-10-04 11:08:45 -0400353 if (!thisObserved)
354 return false;
355 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700356
357 if (m_pList) {
Henrique Nakashima55469ae2017-10-04 11:08:45 -0400358 if (!m_pList->SetVisible(true) || !thisObserved)
359 return false;
360
361 if (!m_pList->Move(rcList, true, false) || !thisObserved)
362 return false;
363
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700364 m_pList->ScrollToListItem(m_nSelectItem);
Henrique Nakashima55469ae2017-10-04 11:08:45 -0400365 if (!thisObserved)
366 return false;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700367 }
Henrique Nakashima55469ae2017-10-04 11:08:45 -0400368 return true;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700369 }
Lei Zhang7bef7c82017-05-31 23:52:00 -0700370
371 CFX_FloatRect rcButton = rcClient;
Dan Sinclair951b1112017-10-02 10:38:55 -0400372 rcButton.left = std::max(rcButton.right - kDefaultButtonWidth, rcClient.left);
Lei Zhang7bef7c82017-05-31 23:52:00 -0700373
Henrique Nakashima55469ae2017-10-04 11:08:45 -0400374 if (m_pButton) {
Lei Zhang7bef7c82017-05-31 23:52:00 -0700375 m_pButton->Move(rcButton, true, false);
Henrique Nakashima55469ae2017-10-04 11:08:45 -0400376 if (!thisObserved)
377 return false;
378 }
Lei Zhang7bef7c82017-05-31 23:52:00 -0700379
380 CFX_FloatRect rcEdit = rcClient;
381 rcEdit.right = std::max(rcButton.left - 1.0f, rcEdit.left);
382
Henrique Nakashima55469ae2017-10-04 11:08:45 -0400383 if (m_pEdit) {
Lei Zhang7bef7c82017-05-31 23:52:00 -0700384 m_pEdit->Move(rcEdit, true, false);
Henrique Nakashima55469ae2017-10-04 11:08:45 -0400385 if (!thisObserved)
386 return false;
387 }
Lei Zhang7bef7c82017-05-31 23:52:00 -0700388
Henrique Nakashima55469ae2017-10-04 11:08:45 -0400389 if (m_pList) {
Lei Zhang7bef7c82017-05-31 23:52:00 -0700390 m_pList->SetVisible(false);
Henrique Nakashima55469ae2017-10-04 11:08:45 -0400391 if (!thisObserved)
392 return false;
393 }
394
395 return true;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700396}
397
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700398void CPWL_ComboBox::SelectAll() {
399 if (m_pEdit && HasFlag(PCBS_ALLOWCUSTOMTEXT))
Tom Sepez2f2ffec2015-07-23 14:42:09 -0700400 m_pEdit->SelectAll();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700401}
402
Tom Sepez281a9ea2016-02-26 14:24:28 -0800403CFX_FloatRect CPWL_ComboBox::GetFocusRect() const {
404 return CFX_FloatRect();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700405}
406
Henrique Nakashima55469ae2017-10-04 11:08:45 -0400407bool CPWL_ComboBox::SetPopup(bool bPopup) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700408 if (!m_pList)
Henrique Nakashima55469ae2017-10-04 11:08:45 -0400409 return true;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700410 if (bPopup == m_bPopup)
Henrique Nakashima55469ae2017-10-04 11:08:45 -0400411 return true;
Dan Sinclair05df0752017-03-14 14:43:42 -0400412 float fListHeight = m_pList->GetContentRect().Height();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700413 if (!IsFloatBigger(fListHeight, 0.0f))
Henrique Nakashima55469ae2017-10-04 11:08:45 -0400414 return true;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700415
Lei Zhang7bef7c82017-05-31 23:52:00 -0700416 if (!bPopup) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700417 m_bPopup = bPopup;
Henrique Nakashima55469ae2017-10-04 11:08:45 -0400418 return Move(m_rcOldWindow, true, true);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700419 }
Lei Zhang7bef7c82017-05-31 23:52:00 -0700420
421 if (!m_pFillerNotify)
Henrique Nakashima55469ae2017-10-04 11:08:45 -0400422 return true;
423
424 ObservedPtr thisObserved(this);
Lei Zhang7bef7c82017-05-31 23:52:00 -0700425
426#ifdef PDF_ENABLE_XFA
Dan Sinclair5fe98082017-07-06 11:13:02 -0400427 if (m_pFillerNotify->OnPopupPreOpen(GetAttachedData(), 0))
Henrique Nakashima55469ae2017-10-04 11:08:45 -0400428 return !!thisObserved;
429 if (!thisObserved)
430 return false;
Lei Zhang7bef7c82017-05-31 23:52:00 -0700431#endif // PDF_ENABLE_XFA
432
433 float fBorderWidth = m_pList->GetBorderWidth() * 2;
434 float fPopupMin = 0.0f;
435 if (m_pList->GetCount() > 3)
436 fPopupMin = m_pList->GetFirstHeight() * 3 + fBorderWidth;
437 float fPopupMax = fListHeight + fBorderWidth;
438
439 bool bBottom;
440 float fPopupRet;
441 m_pFillerNotify->QueryWherePopup(GetAttachedData(), fPopupMin, fPopupMax,
442 &bBottom, &fPopupRet);
443 if (!IsFloatBigger(fPopupRet, 0.0f))
Henrique Nakashima55469ae2017-10-04 11:08:45 -0400444 return true;
Lei Zhang7bef7c82017-05-31 23:52:00 -0700445
446 m_rcOldWindow = CPWL_Wnd::GetWindowRect();
447 m_bPopup = bPopup;
448 m_bBottom = bBottom;
449
450 CFX_FloatRect rcWindow = m_rcOldWindow;
451 if (bBottom)
452 rcWindow.bottom -= fPopupRet;
453 else
454 rcWindow.top += fPopupRet;
455
Henrique Nakashima55469ae2017-10-04 11:08:45 -0400456 if (!Move(rcWindow, true, true))
457 return false;
458
Lei Zhang7bef7c82017-05-31 23:52:00 -0700459#ifdef PDF_ENABLE_XFA
Dan Sinclair5fe98082017-07-06 11:13:02 -0400460 m_pFillerNotify->OnPopupPostOpen(GetAttachedData(), 0);
Henrique Nakashima55469ae2017-10-04 11:08:45 -0400461 if (!thisObserved)
462 return false;
Lei Zhang7bef7c82017-05-31 23:52:00 -0700463#endif // PDF_ENABLE_XFA
Henrique Nakashima55469ae2017-10-04 11:08:45 -0400464
465 return !!thisObserved;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700466}
467
tsepez4cf55152016-11-02 14:37:54 -0700468bool CPWL_ComboBox::OnKeyDown(uint16_t nChar, uint32_t nFlag) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700469 if (!m_pList)
tsepez4cf55152016-11-02 14:37:54 -0700470 return false;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700471 if (!m_pEdit)
tsepez4cf55152016-11-02 14:37:54 -0700472 return false;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700473
474 m_nSelectItem = -1;
475
476 switch (nChar) {
477 case FWL_VKEY_Up:
478 if (m_pList->GetCurSel() > 0) {
Tom Sepez51da0932015-11-25 16:05:49 -0800479#ifdef PDF_ENABLE_XFA
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700480 if (m_pFillerNotify) {
Dan Sinclair5fe98082017-07-06 11:13:02 -0400481 if (m_pFillerNotify->OnPopupPreOpen(GetAttachedData(), nFlag))
tsepez4cf55152016-11-02 14:37:54 -0700482 return false;
Dan Sinclair5fe98082017-07-06 11:13:02 -0400483 if (m_pFillerNotify->OnPopupPostOpen(GetAttachedData(), nFlag))
tsepez4cf55152016-11-02 14:37:54 -0700484 return false;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700485 }
Tom Sepez40e9ff32015-11-30 12:39:54 -0800486#endif // PDF_ENABLE_XFA
Dan Sinclair07dbf432017-07-06 11:47:26 -0400487 if (m_pList->IsMovementKey(nChar)) {
488 if (m_pList->OnMovementKeyDown(nChar, nFlag))
tsepez4cf55152016-11-02 14:37:54 -0700489 return false;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700490 SetSelectText();
491 }
492 }
tsepez4cf55152016-11-02 14:37:54 -0700493 return true;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700494 case FWL_VKEY_Down:
495 if (m_pList->GetCurSel() < m_pList->GetCount() - 1) {
Tom Sepez51da0932015-11-25 16:05:49 -0800496#ifdef PDF_ENABLE_XFA
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700497 if (m_pFillerNotify) {
Dan Sinclair5fe98082017-07-06 11:13:02 -0400498 if (m_pFillerNotify->OnPopupPreOpen(GetAttachedData(), nFlag))
tsepez4cf55152016-11-02 14:37:54 -0700499 return false;
Dan Sinclair5fe98082017-07-06 11:13:02 -0400500 if (m_pFillerNotify->OnPopupPostOpen(GetAttachedData(), nFlag))
tsepez4cf55152016-11-02 14:37:54 -0700501 return false;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700502 }
Tom Sepez40e9ff32015-11-30 12:39:54 -0800503#endif // PDF_ENABLE_XFA
Dan Sinclair07dbf432017-07-06 11:47:26 -0400504 if (m_pList->IsMovementKey(nChar)) {
505 if (m_pList->OnMovementKeyDown(nChar, nFlag))
tsepez4cf55152016-11-02 14:37:54 -0700506 return false;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700507 SetSelectText();
508 }
509 }
tsepez4cf55152016-11-02 14:37:54 -0700510 return true;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700511 }
512
513 if (HasFlag(PCBS_ALLOWCUSTOMTEXT))
514 return m_pEdit->OnKeyDown(nChar, nFlag);
515
tsepez4cf55152016-11-02 14:37:54 -0700516 return false;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700517}
518
tsepez4cf55152016-11-02 14:37:54 -0700519bool CPWL_ComboBox::OnChar(uint16_t nChar, uint32_t nFlag) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700520 if (!m_pList)
tsepez4cf55152016-11-02 14:37:54 -0700521 return false;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700522
523 if (!m_pEdit)
tsepez4cf55152016-11-02 14:37:54 -0700524 return false;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700525
526 m_nSelectItem = -1;
527 if (HasFlag(PCBS_ALLOWCUSTOMTEXT))
528 return m_pEdit->OnChar(nChar, nFlag);
529
Tom Sepez51da0932015-11-25 16:05:49 -0800530#ifdef PDF_ENABLE_XFA
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700531 if (m_pFillerNotify) {
Dan Sinclair5fe98082017-07-06 11:13:02 -0400532 if (m_pFillerNotify->OnPopupPreOpen(GetAttachedData(), nFlag))
tsepez4cf55152016-11-02 14:37:54 -0700533 return false;
Dan Sinclair5fe98082017-07-06 11:13:02 -0400534 if (m_pFillerNotify->OnPopupPostOpen(GetAttachedData(), nFlag))
tsepez4cf55152016-11-02 14:37:54 -0700535 return false;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700536 }
Tom Sepez40e9ff32015-11-30 12:39:54 -0800537#endif // PDF_ENABLE_XFA
Dan Sinclair16fea942017-07-06 11:56:37 -0400538 if (!m_pList->IsChar(nChar, nFlag))
539 return false;
540 return m_pList->OnCharNotify(nChar, nFlag);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700541}
542
Dan Sinclair7f6bec92017-07-05 14:13:16 -0400543void CPWL_ComboBox::NotifyLButtonDown(CPWL_Wnd* child, const CFX_PointF& pos) {
Henrique Nakashima55469ae2017-10-04 11:08:45 -0400544 if (child == m_pButton) {
Dan Sinclair7f6bec92017-07-05 14:13:16 -0400545 SetPopup(!m_bPopup);
Henrique Nakashima55469ae2017-10-04 11:08:45 -0400546 // Note, |this| may no longer be viable at this point. If more work needs to
547 // be done, check the return value of SetPopup().
548 }
Dan Sinclair7f6bec92017-07-05 14:13:16 -0400549}
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700550
Dan Sinclair7f6bec92017-07-05 14:13:16 -0400551void CPWL_ComboBox::NotifyLButtonUp(CPWL_Wnd* child, const CFX_PointF& pos) {
552 if (!m_pEdit || !m_pList || child != m_pList)
553 return;
554
555 SetSelectText();
556 SelectAll();
557 m_pEdit->SetFocus();
558 SetPopup(false);
Henrique Nakashima55469ae2017-10-04 11:08:45 -0400559 // Note, |this| may no longer be viable at this point. If more work needs to
560 // be done, check the return value of SetPopup().
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700561}
562
tsepez4cf55152016-11-02 14:37:54 -0700563bool CPWL_ComboBox::IsPopup() const {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700564 return m_bPopup;
565}
566
567void CPWL_ComboBox::SetSelectText() {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700568 m_pEdit->SelectAll();
tsepez067990c2016-09-13 06:46:40 -0700569 m_pEdit->ReplaceSel(m_pList->GetText());
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700570 m_pEdit->SelectAll();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700571 m_nSelectItem = m_pList->GetCurSel();
572}
573
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700574void CPWL_ComboBox::SetFillerNotify(IPWL_Filler_Notify* pNotify) {
575 m_pFillerNotify = pNotify;
576
577 if (m_pEdit)
578 m_pEdit->SetFillerNotify(pNotify);
579
580 if (m_pList)
581 m_pList->SetFillerNotify(pNotify);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700582}