blob: acebfbe58ba649d1253ca2a23249a805af630c8c [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
Lei Zhang633a3b72017-06-02 15:27:22 -07007#include "fpdfsdk/pdfwindow/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"
dsinclair0bb385b2016-09-29 17:03:59 -070014#include "fpdfsdk/fxedit/fxet_list.h"
Lei Zhang633a3b72017-06-02 15:27:22 -070015#include "fpdfsdk/pdfwindow/cpwl_edit.h"
16#include "fpdfsdk/pdfwindow/cpwl_edit_ctrl.h"
17#include "fpdfsdk/pdfwindow/cpwl_list_box.h"
18#include "fpdfsdk/pdfwindow/cpwl_utils.h"
19#include "fpdfsdk/pdfwindow/cpwl_wnd.h"
Lei Zhangc2fb35f2016-01-05 16:46:58 -080020#include "public/fpdf_fwlevent.h"
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070021
Dan Sinclaira9e28432017-07-05 14:18:14 -040022namespace {
23
24constexpr float kDefaultFontSize = 12.0f;
25constexpr float kTriangleHalfLength = 3.0f;
26
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
tsepez4cf55152016-11-02 14:37:54 -070043 bool bExit = false;
44 OnNotifySelChanged(false, bExit, nFlag);
dsinclair36177512016-07-19 10:16:10 -070045
46 return !bExit;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070047}
48
Dan Sinclair07dbf432017-07-06 11:47:26 -040049bool CPWL_CBListBox::IsMovementKey(uint16_t nChar) const {
Nico Weber9d8ec5a2015-08-04 13:00:21 -070050 switch (nChar) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -070051 case FWL_VKEY_Up:
52 case FWL_VKEY_Down:
53 case FWL_VKEY_Home:
54 case FWL_VKEY_Left:
55 case FWL_VKEY_End:
56 case FWL_VKEY_Right:
Dan Sinclair07dbf432017-07-06 11:47:26 -040057 return true;
dsinclair36177512016-07-19 10:16:10 -070058 default:
tsepez4cf55152016-11-02 14:37:54 -070059 return false;
Nico Weber9d8ec5a2015-08-04 13:00:21 -070060 }
Dan Sinclair07dbf432017-07-06 11:47:26 -040061}
62
63bool CPWL_CBListBox::OnMovementKeyDown(uint16_t nChar, uint32_t nFlag) {
64 ASSERT(IsMovementKey(nChar));
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070065
Nico Weber9d8ec5a2015-08-04 13:00:21 -070066 switch (nChar) {
67 case FWL_VKEY_Up:
68 m_pList->OnVK_UP(IsSHIFTpressed(nFlag), IsCTRLpressed(nFlag));
69 break;
70 case FWL_VKEY_Down:
71 m_pList->OnVK_DOWN(IsSHIFTpressed(nFlag), IsCTRLpressed(nFlag));
72 break;
73 case FWL_VKEY_Home:
74 m_pList->OnVK_HOME(IsSHIFTpressed(nFlag), IsCTRLpressed(nFlag));
75 break;
76 case FWL_VKEY_Left:
77 m_pList->OnVK_LEFT(IsSHIFTpressed(nFlag), IsCTRLpressed(nFlag));
78 break;
79 case FWL_VKEY_End:
80 m_pList->OnVK_END(IsSHIFTpressed(nFlag), IsCTRLpressed(nFlag));
81 break;
82 case FWL_VKEY_Right:
83 m_pList->OnVK_RIGHT(IsSHIFTpressed(nFlag), IsCTRLpressed(nFlag));
84 break;
Nico Weber9d8ec5a2015-08-04 13:00:21 -070085 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070086
Dan Sinclair07dbf432017-07-06 11:47:26 -040087 bool bExit = false;
tsepez4cf55152016-11-02 14:37:54 -070088 OnNotifySelChanged(true, bExit, nFlag);
Dan Sinclair07dbf432017-07-06 11:47:26 -040089 return bExit;
Nico Weber9d8ec5a2015-08-04 13:00:21 -070090}
91
tsepez4cf55152016-11-02 14:37:54 -070092bool CPWL_CBListBox::OnCharWithExit(uint16_t nChar,
93 bool& bExit,
94 uint32_t nFlag) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -070095 if (!m_pList->OnChar(nChar, IsSHIFTpressed(nFlag), IsCTRLpressed(nFlag)))
tsepez4cf55152016-11-02 14:37:54 -070096 return false;
dsinclair36177512016-07-19 10:16:10 -070097 if (CPWL_ComboBox* pComboBox = (CPWL_ComboBox*)GetParentWindow())
Nico Weber9d8ec5a2015-08-04 13:00:21 -070098 pComboBox->SetSelectText();
Nico Weber9d8ec5a2015-08-04 13:00:21 -070099
tsepez4cf55152016-11-02 14:37:54 -0700100 OnNotifySelChanged(true, bExit, nFlag);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700101
tsepez4cf55152016-11-02 14:37:54 -0700102 return true;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700103}
104
Henrique Nakashimaf1eae2c2017-06-29 11:18:49 -0400105void CPWL_CBButton::GetThisAppearanceStream(std::ostringstream* psAppStream) {
106 CPWL_Wnd::GetThisAppearanceStream(psAppStream);
Lei Zhanga6d9f0e2015-06-13 00:48:38 -0700107
Tom Sepez281a9ea2016-02-26 14:24:28 -0800108 CFX_FloatRect rectWnd = CPWL_Wnd::GetWindowRect();
Lei Zhanga6d9f0e2015-06-13 00:48:38 -0700109
Henrique Nakashimaf1eae2c2017-06-29 11:18:49 -0400110 if (!IsVisible() || rectWnd.IsEmpty())
111 return;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700112
Henrique Nakashimaf1eae2c2017-06-29 11:18:49 -0400113 CFX_PointF ptCenter = GetCenterPoint();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700114
Dan Sinclaira9e28432017-07-05 14:18:14 -0400115 CFX_PointF pt1(ptCenter.x - kTriangleHalfLength,
116 ptCenter.y + kTriangleHalfLength * 0.5f);
117 CFX_PointF pt2(ptCenter.x + kTriangleHalfLength,
118 ptCenter.y + kTriangleHalfLength * 0.5f);
119 CFX_PointF pt3(ptCenter.x, ptCenter.y - kTriangleHalfLength * 0.5f);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700120
Dan Sinclaira9e28432017-07-05 14:18:14 -0400121 if (IsFloatBigger(rectWnd.right - rectWnd.left, kTriangleHalfLength * 2) &&
122 IsFloatBigger(rectWnd.top - rectWnd.bottom, kTriangleHalfLength)) {
Henrique Nakashimaf1eae2c2017-06-29 11:18:49 -0400123 *psAppStream << "q\n"
124 << "0 g\n"
125 << pt1.x << " " << pt1.y << " m\n"
126 << pt2.x << " " << pt2.y << " l\n"
127 << pt3.x << " " << pt3.y << " l\n"
128 << pt1.x << " " << pt1.y << " l f\n"
129 << "Q\n";
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700130 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700131}
132
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700133void CPWL_CBButton::DrawThisAppearance(CFX_RenderDevice* pDevice,
Tom Sepez60d909e2015-12-10 15:34:55 -0800134 CFX_Matrix* pUser2Device) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700135 CPWL_Wnd::DrawThisAppearance(pDevice, pUser2Device);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700136
Tom Sepez281a9ea2016-02-26 14:24:28 -0800137 CFX_FloatRect rectWnd = CPWL_Wnd::GetWindowRect();
Lei Zhanga6d9f0e2015-06-13 00:48:38 -0700138
Henrique Nakashimaf1eae2c2017-06-29 11:18:49 -0400139 if (!IsVisible() || rectWnd.IsEmpty())
140 return;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700141
Henrique Nakashimaf1eae2c2017-06-29 11:18:49 -0400142 CFX_PointF ptCenter = GetCenterPoint();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700143
Dan Sinclaira9e28432017-07-05 14:18:14 -0400144 CFX_PointF pt1(ptCenter.x - kTriangleHalfLength,
145 ptCenter.y + kTriangleHalfLength * 0.5f);
146 CFX_PointF pt2(ptCenter.x + kTriangleHalfLength,
147 ptCenter.y + kTriangleHalfLength * 0.5f);
148 CFX_PointF pt3(ptCenter.x, ptCenter.y - kTriangleHalfLength * 0.5f);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700149
Dan Sinclaira9e28432017-07-05 14:18:14 -0400150 if (IsFloatBigger(rectWnd.right - rectWnd.left, kTriangleHalfLength * 2) &&
151 IsFloatBigger(rectWnd.top - rectWnd.bottom, kTriangleHalfLength)) {
Henrique Nakashimaf1eae2c2017-06-29 11:18:49 -0400152 CFX_PathData path;
153 path.AppendPoint(pt1, FXPT_TYPE::MoveTo, false);
154 path.AppendPoint(pt2, FXPT_TYPE::LineTo, false);
155 path.AppendPoint(pt3, FXPT_TYPE::LineTo, false);
156 path.AppendPoint(pt1, FXPT_TYPE::LineTo, false);
157
158 pDevice->DrawPath(&path, pUser2Device, nullptr,
159 PWL_DEFAULT_BLACKCOLOR.ToFXColor(GetTransparency()), 0,
160 FXFILL_ALTERNATE);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700161 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700162}
163
Dan Sinclairf528eee2017-02-14 11:52:07 -0500164bool CPWL_CBButton::OnLButtonDown(const CFX_PointF& point, uint32_t nFlag) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700165 CPWL_Wnd::OnLButtonDown(point, nFlag);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700166
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700167 SetCapture();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700168
Dan Sinclair7f6bec92017-07-05 14:13:16 -0400169 if (CPWL_Wnd* pParent = GetParentWindow())
170 pParent->NotifyLButtonDown(this, point);
Lei Zhanga6d9f0e2015-06-13 00:48:38 -0700171
tsepez4cf55152016-11-02 14:37:54 -0700172 return true;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700173}
174
Dan Sinclairf528eee2017-02-14 11:52:07 -0500175bool CPWL_CBButton::OnLButtonUp(const CFX_PointF& point, uint32_t nFlag) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700176 CPWL_Wnd::OnLButtonUp(point, nFlag);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700177
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700178 ReleaseCapture();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700179
tsepez4cf55152016-11-02 14:37:54 -0700180 return true;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700181}
182
Lei Zhang35162562017-06-09 01:04:52 -0700183CPWL_ComboBox::CPWL_ComboBox() {}
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700184
Tom Sepezb084c1f2017-05-12 14:04:06 -0700185CPWL_ComboBox::~CPWL_ComboBox() {}
186
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700187CFX_ByteString CPWL_ComboBox::GetClassName() const {
188 return "CPWL_ComboBox";
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700189}
190
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700191void CPWL_ComboBox::OnCreate(PWL_CREATEPARAM& cp) {
192 cp.dwFlags &= ~PWS_HSCROLL;
193 cp.dwFlags &= ~PWS_VSCROLL;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700194}
195
Lei Zhang35162562017-06-09 01:04:52 -0700196void CPWL_ComboBox::OnDestroy() {
197 // Until cleanup takes place in the virtual destructor for CPWL_Wnd
198 // subclasses, implement the virtual OnDestroy method that does the
199 // cleanup first, then invokes the superclass OnDestroy ... gee,
200 // like a dtor would.
201 m_pList.Release();
202 m_pButton.Release();
203 m_pEdit.Release();
204 CPWL_Wnd::OnDestroy();
205}
206
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700207void CPWL_ComboBox::SetFocus() {
208 if (m_pEdit)
209 m_pEdit->SetFocus();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700210}
211
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700212void CPWL_ComboBox::KillFocus() {
tsepez4cf55152016-11-02 14:37:54 -0700213 SetPopup(false);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700214 CPWL_Wnd::KillFocus();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700215}
216
Diana Gagedce2d722017-06-20 11:17:11 -0700217CFX_WideString CPWL_ComboBox::GetSelectedText() {
218 if (m_pEdit)
219 return m_pEdit->GetSelectedText();
220
221 return CFX_WideString();
222}
223
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700224CFX_WideString CPWL_ComboBox::GetText() const {
225 if (m_pEdit) {
226 return m_pEdit->GetText();
227 }
228 return CFX_WideString();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700229}
230
tsepez067990c2016-09-13 06:46:40 -0700231void CPWL_ComboBox::SetText(const CFX_WideString& text) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700232 if (m_pEdit)
233 m_pEdit->SetText(text);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700234}
235
tsepez067990c2016-09-13 06:46:40 -0700236void CPWL_ComboBox::AddString(const CFX_WideString& str) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700237 if (m_pList)
Dan Sinclair3ebd1212016-03-09 09:59:23 -0500238 m_pList->AddString(str);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700239}
240
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700241int32_t CPWL_ComboBox::GetSelect() const {
242 return m_nSelectItem;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700243}
244
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700245void CPWL_ComboBox::SetSelect(int32_t nItemIndex) {
246 if (m_pList)
247 m_pList->Select(nItemIndex);
248
tsepez067990c2016-09-13 06:46:40 -0700249 m_pEdit->SetText(m_pList->GetText());
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700250 m_nSelectItem = nItemIndex;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700251}
252
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700253void CPWL_ComboBox::SetEditSel(int32_t nStartChar, int32_t nEndChar) {
tsepez067990c2016-09-13 06:46:40 -0700254 if (m_pEdit)
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700255 m_pEdit->SetSel(nStartChar, nEndChar);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700256}
257
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700258void CPWL_ComboBox::GetEditSel(int32_t& nStartChar, int32_t& nEndChar) const {
259 nStartChar = -1;
260 nEndChar = -1;
261
tsepez067990c2016-09-13 06:46:40 -0700262 if (m_pEdit)
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700263 m_pEdit->GetSel(nStartChar, nEndChar);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700264}
265
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700266void CPWL_ComboBox::Clear() {
tsepez067990c2016-09-13 06:46:40 -0700267 if (m_pEdit)
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700268 m_pEdit->Clear();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700269}
270
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700271void CPWL_ComboBox::CreateChildWnd(const PWL_CREATEPARAM& cp) {
272 CreateEdit(cp);
273 CreateButton(cp);
274 CreateListBox(cp);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700275}
276
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700277void CPWL_ComboBox::CreateEdit(const PWL_CREATEPARAM& cp) {
Tom Sepezb084c1f2017-05-12 14:04:06 -0700278 if (m_pEdit)
279 return;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700280
Dan Sinclair0fdd1ae2017-07-05 16:00:48 -0400281 m_pEdit = new CPWL_Edit();
Tom Sepezcc205132017-05-16 14:01:47 -0700282 m_pEdit->AttachFFLData(m_pFormFiller.Get());
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700283
Tom Sepezb084c1f2017-05-12 14:04:06 -0700284 PWL_CREATEPARAM ecp = cp;
285 ecp.pParentWnd = this;
286 ecp.dwFlags = PWS_VISIBLE | PWS_CHILD | PWS_BORDER | PES_CENTER |
287 PES_AUTOSCROLL | PES_UNDO;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700288
Tom Sepezb084c1f2017-05-12 14:04:06 -0700289 if (HasFlag(PWS_AUTOFONTSIZE))
290 ecp.dwFlags |= PWS_AUTOFONTSIZE;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700291
Tom Sepezb084c1f2017-05-12 14:04:06 -0700292 if (!HasFlag(PCBS_ALLOWCUSTOMTEXT))
293 ecp.dwFlags |= PWS_READONLY;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700294
Lei Zhangd24236a2017-06-29 18:28:58 -0700295 ecp.rcRectWnd = CFX_FloatRect();
Tom Sepezb084c1f2017-05-12 14:04:06 -0700296 ecp.dwBorderWidth = 0;
297 ecp.nBorderStyle = BorderStyle::SOLID;
298 m_pEdit->Create(ecp);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700299}
300
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700301void CPWL_ComboBox::CreateButton(const PWL_CREATEPARAM& cp) {
Tom Sepezb084c1f2017-05-12 14:04:06 -0700302 if (m_pButton)
303 return;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700304
Tom Sepez45b9ae12017-05-18 08:34:03 -0700305 m_pButton = new CPWL_CBButton;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700306
Tom Sepezb084c1f2017-05-12 14:04:06 -0700307 PWL_CREATEPARAM bcp = cp;
308 bcp.pParentWnd = this;
309 bcp.dwFlags = PWS_VISIBLE | PWS_CHILD | PWS_BORDER | PWS_BACKGROUND;
Dan Sinclaira9e28432017-07-05 14:18:14 -0400310 bcp.sBackgroundColor = CPWL_Color(COLORTYPE_RGB, 220.0f / 255.0f,
311 220.0f / 255.0f, 220.0f / 255.0f);
Tom Sepezb084c1f2017-05-12 14:04:06 -0700312 bcp.sBorderColor = PWL_DEFAULT_BLACKCOLOR;
313 bcp.dwBorderWidth = 2;
314 bcp.nBorderStyle = BorderStyle::BEVELED;
315 bcp.eCursorType = FXCT_ARROW;
316 m_pButton->Create(bcp);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700317}
318
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700319void CPWL_ComboBox::CreateListBox(const PWL_CREATEPARAM& cp) {
Tom Sepezb084c1f2017-05-12 14:04:06 -0700320 if (m_pList)
321 return;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700322
Tom Sepez45b9ae12017-05-18 08:34:03 -0700323 m_pList = new CPWL_CBListBox();
Tom Sepezcc205132017-05-16 14:01:47 -0700324 m_pList->AttachFFLData(m_pFormFiller.Get());
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700325
Tom Sepezb084c1f2017-05-12 14:04:06 -0700326 PWL_CREATEPARAM lcp = cp;
327 lcp.pParentWnd = this;
328 lcp.dwFlags =
329 PWS_CHILD | PWS_BORDER | PWS_BACKGROUND | PLBS_HOVERSEL | PWS_VSCROLL;
330 lcp.nBorderStyle = BorderStyle::SOLID;
331 lcp.dwBorderWidth = 1;
332 lcp.eCursorType = FXCT_ARROW;
Lei Zhangd24236a2017-06-29 18:28:58 -0700333 lcp.rcRectWnd = CFX_FloatRect();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700334
Tom Sepezb084c1f2017-05-12 14:04:06 -0700335 if (cp.dwFlags & PWS_AUTOFONTSIZE)
Dan Sinclaira9e28432017-07-05 14:18:14 -0400336 lcp.fFontSize = kDefaultFontSize;
Tom Sepezb084c1f2017-05-12 14:04:06 -0700337 else
338 lcp.fFontSize = cp.fFontSize;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700339
Tom Sepezb084c1f2017-05-12 14:04:06 -0700340 if (cp.sBorderColor.nColorType == COLORTYPE_TRANSPARENT)
341 lcp.sBorderColor = PWL_DEFAULT_BLACKCOLOR;
342
343 if (cp.sBackgroundColor.nColorType == COLORTYPE_TRANSPARENT)
344 lcp.sBackgroundColor = PWL_DEFAULT_WHITECOLOR;
345
346 m_pList->Create(lcp);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700347}
348
349void CPWL_ComboBox::RePosChildWnd() {
Lei Zhang7bef7c82017-05-31 23:52:00 -0700350 const CFX_FloatRect rcClient = GetClientRect();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700351 if (m_bPopup) {
Lei Zhang7bef7c82017-05-31 23:52:00 -0700352 const float fOldWindowHeight = m_rcOldWindow.Height();
353 const float fOldClientHeight = fOldWindowHeight - GetBorderWidth() * 2;
354
Tom Sepez281a9ea2016-02-26 14:24:28 -0800355 CFX_FloatRect rcList = CPWL_Wnd::GetWindowRect();
Lei Zhang7bef7c82017-05-31 23:52:00 -0700356 CFX_FloatRect rcButton = rcClient;
357 rcButton.left =
358 std::max(rcButton.right - PWL_COMBOBOX_BUTTON_WIDTH, rcClient.left);
359 CFX_FloatRect rcEdit = rcClient;
360 rcEdit.right = std::max(rcButton.left - 1.0f, rcEdit.left);
361 if (m_bBottom) {
362 rcButton.bottom = rcButton.top - fOldClientHeight;
363 rcEdit.bottom = rcEdit.top - fOldClientHeight;
364 rcList.top -= fOldWindowHeight;
365 } else {
366 rcButton.top = rcButton.bottom + fOldClientHeight;
367 rcEdit.top = rcEdit.bottom + fOldClientHeight;
368 rcList.bottom += fOldWindowHeight;
Tom Sepez2f2ffec2015-07-23 14:42:09 -0700369 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700370
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700371 if (m_pButton)
tsepez4cf55152016-11-02 14:37:54 -0700372 m_pButton->Move(rcButton, true, false);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700373
374 if (m_pEdit)
tsepez4cf55152016-11-02 14:37:54 -0700375 m_pEdit->Move(rcEdit, true, false);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700376
377 if (m_pList) {
tsepez4cf55152016-11-02 14:37:54 -0700378 m_pList->SetVisible(true);
379 m_pList->Move(rcList, true, false);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700380 m_pList->ScrollToListItem(m_nSelectItem);
381 }
Lei Zhang7bef7c82017-05-31 23:52:00 -0700382 return;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700383 }
Lei Zhang7bef7c82017-05-31 23:52:00 -0700384
385 CFX_FloatRect rcButton = rcClient;
386 rcButton.left =
387 std::max(rcButton.right - PWL_COMBOBOX_BUTTON_WIDTH, rcClient.left);
388
389 if (m_pButton)
390 m_pButton->Move(rcButton, true, false);
391
392 CFX_FloatRect rcEdit = rcClient;
393 rcEdit.right = std::max(rcButton.left - 1.0f, rcEdit.left);
394
395 if (m_pEdit)
396 m_pEdit->Move(rcEdit, true, false);
397
398 if (m_pList)
399 m_pList->SetVisible(false);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700400}
401
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700402void CPWL_ComboBox::SelectAll() {
403 if (m_pEdit && HasFlag(PCBS_ALLOWCUSTOMTEXT))
Tom Sepez2f2ffec2015-07-23 14:42:09 -0700404 m_pEdit->SelectAll();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700405}
406
Tom Sepez281a9ea2016-02-26 14:24:28 -0800407CFX_FloatRect CPWL_ComboBox::GetFocusRect() const {
408 return CFX_FloatRect();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700409}
410
tsepez4cf55152016-11-02 14:37:54 -0700411void CPWL_ComboBox::SetPopup(bool bPopup) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700412 if (!m_pList)
413 return;
414 if (bPopup == m_bPopup)
415 return;
Dan Sinclair05df0752017-03-14 14:43:42 -0400416 float fListHeight = m_pList->GetContentRect().Height();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700417 if (!IsFloatBigger(fListHeight, 0.0f))
418 return;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700419
Lei Zhang7bef7c82017-05-31 23:52:00 -0700420 if (!bPopup) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700421 m_bPopup = bPopup;
tsepez4cf55152016-11-02 14:37:54 -0700422 Move(m_rcOldWindow, true, true);
Lei Zhang7bef7c82017-05-31 23:52:00 -0700423 return;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700424 }
Lei Zhang7bef7c82017-05-31 23:52:00 -0700425
426 if (!m_pFillerNotify)
427 return;
428
429#ifdef PDF_ENABLE_XFA
Dan Sinclair5fe98082017-07-06 11:13:02 -0400430 if (m_pFillerNotify->OnPopupPreOpen(GetAttachedData(), 0))
Lei Zhang7bef7c82017-05-31 23:52:00 -0700431 return;
432#endif // PDF_ENABLE_XFA
433
434 float fBorderWidth = m_pList->GetBorderWidth() * 2;
435 float fPopupMin = 0.0f;
436 if (m_pList->GetCount() > 3)
437 fPopupMin = m_pList->GetFirstHeight() * 3 + fBorderWidth;
438 float fPopupMax = fListHeight + fBorderWidth;
439
440 bool bBottom;
441 float fPopupRet;
442 m_pFillerNotify->QueryWherePopup(GetAttachedData(), fPopupMin, fPopupMax,
443 &bBottom, &fPopupRet);
444 if (!IsFloatBigger(fPopupRet, 0.0f))
445 return;
446
447 m_rcOldWindow = CPWL_Wnd::GetWindowRect();
448 m_bPopup = bPopup;
449 m_bBottom = bBottom;
450
451 CFX_FloatRect rcWindow = m_rcOldWindow;
452 if (bBottom)
453 rcWindow.bottom -= fPopupRet;
454 else
455 rcWindow.top += fPopupRet;
456
457 Move(rcWindow, true, true);
458#ifdef PDF_ENABLE_XFA
Dan Sinclair5fe98082017-07-06 11:13:02 -0400459 m_pFillerNotify->OnPopupPostOpen(GetAttachedData(), 0);
Lei Zhang7bef7c82017-05-31 23:52:00 -0700460#endif // PDF_ENABLE_XFA
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700461}
462
tsepez4cf55152016-11-02 14:37:54 -0700463bool CPWL_ComboBox::OnKeyDown(uint16_t nChar, uint32_t nFlag) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700464 if (!m_pList)
tsepez4cf55152016-11-02 14:37:54 -0700465 return false;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700466 if (!m_pEdit)
tsepez4cf55152016-11-02 14:37:54 -0700467 return false;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700468
469 m_nSelectItem = -1;
470
471 switch (nChar) {
472 case FWL_VKEY_Up:
473 if (m_pList->GetCurSel() > 0) {
Tom Sepez51da0932015-11-25 16:05:49 -0800474#ifdef PDF_ENABLE_XFA
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700475 if (m_pFillerNotify) {
Dan Sinclair5fe98082017-07-06 11:13:02 -0400476 if (m_pFillerNotify->OnPopupPreOpen(GetAttachedData(), nFlag))
tsepez4cf55152016-11-02 14:37:54 -0700477 return false;
Dan Sinclair5fe98082017-07-06 11:13:02 -0400478 if (m_pFillerNotify->OnPopupPostOpen(GetAttachedData(), nFlag))
tsepez4cf55152016-11-02 14:37:54 -0700479 return false;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700480 }
Tom Sepez40e9ff32015-11-30 12:39:54 -0800481#endif // PDF_ENABLE_XFA
Dan Sinclair07dbf432017-07-06 11:47:26 -0400482 if (m_pList->IsMovementKey(nChar)) {
483 if (m_pList->OnMovementKeyDown(nChar, nFlag))
tsepez4cf55152016-11-02 14:37:54 -0700484 return false;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700485 SetSelectText();
486 }
487 }
tsepez4cf55152016-11-02 14:37:54 -0700488 return true;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700489 case FWL_VKEY_Down:
490 if (m_pList->GetCurSel() < m_pList->GetCount() - 1) {
Tom Sepez51da0932015-11-25 16:05:49 -0800491#ifdef PDF_ENABLE_XFA
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700492 if (m_pFillerNotify) {
Dan Sinclair5fe98082017-07-06 11:13:02 -0400493 if (m_pFillerNotify->OnPopupPreOpen(GetAttachedData(), nFlag))
tsepez4cf55152016-11-02 14:37:54 -0700494 return false;
Dan Sinclair5fe98082017-07-06 11:13:02 -0400495 if (m_pFillerNotify->OnPopupPostOpen(GetAttachedData(), nFlag))
tsepez4cf55152016-11-02 14:37:54 -0700496 return false;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700497 }
Tom Sepez40e9ff32015-11-30 12:39:54 -0800498#endif // PDF_ENABLE_XFA
Dan Sinclair07dbf432017-07-06 11:47:26 -0400499 if (m_pList->IsMovementKey(nChar)) {
500 if (m_pList->OnMovementKeyDown(nChar, nFlag))
tsepez4cf55152016-11-02 14:37:54 -0700501 return false;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700502 SetSelectText();
503 }
504 }
tsepez4cf55152016-11-02 14:37:54 -0700505 return true;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700506 }
507
508 if (HasFlag(PCBS_ALLOWCUSTOMTEXT))
509 return m_pEdit->OnKeyDown(nChar, nFlag);
510
tsepez4cf55152016-11-02 14:37:54 -0700511 return false;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700512}
513
tsepez4cf55152016-11-02 14:37:54 -0700514bool CPWL_ComboBox::OnChar(uint16_t nChar, uint32_t nFlag) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700515 if (!m_pList)
tsepez4cf55152016-11-02 14:37:54 -0700516 return false;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700517
518 if (!m_pEdit)
tsepez4cf55152016-11-02 14:37:54 -0700519 return false;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700520
521 m_nSelectItem = -1;
522 if (HasFlag(PCBS_ALLOWCUSTOMTEXT))
523 return m_pEdit->OnChar(nChar, nFlag);
524
Tom Sepez51da0932015-11-25 16:05:49 -0800525#ifdef PDF_ENABLE_XFA
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700526 if (m_pFillerNotify) {
Dan Sinclair5fe98082017-07-06 11:13:02 -0400527 if (m_pFillerNotify->OnPopupPreOpen(GetAttachedData(), nFlag))
tsepez4cf55152016-11-02 14:37:54 -0700528 return false;
Dan Sinclair5fe98082017-07-06 11:13:02 -0400529 if (m_pFillerNotify->OnPopupPostOpen(GetAttachedData(), nFlag))
tsepez4cf55152016-11-02 14:37:54 -0700530 return false;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700531 }
Tom Sepez40e9ff32015-11-30 12:39:54 -0800532#endif // PDF_ENABLE_XFA
Dan Sinclair5fe98082017-07-06 11:13:02 -0400533 bool bExit = false;
tsepez4cf55152016-11-02 14:37:54 -0700534 return m_pList->OnCharWithExit(nChar, bExit, nFlag) ? bExit : false;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700535}
536
Dan Sinclair7f6bec92017-07-05 14:13:16 -0400537void CPWL_ComboBox::NotifyLButtonDown(CPWL_Wnd* child, const CFX_PointF& pos) {
538 if (child == m_pButton)
539 SetPopup(!m_bPopup);
540}
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700541
Dan Sinclair7f6bec92017-07-05 14:13:16 -0400542void CPWL_ComboBox::NotifyLButtonUp(CPWL_Wnd* child, const CFX_PointF& pos) {
543 if (!m_pEdit || !m_pList || child != m_pList)
544 return;
545
546 SetSelectText();
547 SelectAll();
548 m_pEdit->SetFocus();
549 SetPopup(false);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700550}
551
tsepez4cf55152016-11-02 14:37:54 -0700552bool CPWL_ComboBox::IsPopup() const {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700553 return m_bPopup;
554}
555
556void CPWL_ComboBox::SetSelectText() {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700557 m_pEdit->SelectAll();
tsepez067990c2016-09-13 06:46:40 -0700558 m_pEdit->ReplaceSel(m_pList->GetText());
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700559 m_pEdit->SelectAll();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700560 m_nSelectItem = m_pList->GetCurSel();
561}
562
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700563void CPWL_ComboBox::SetFillerNotify(IPWL_Filler_Notify* pNotify) {
564 m_pFillerNotify = pNotify;
565
566 if (m_pEdit)
567 m_pEdit->SetFillerNotify(pNotify);
568
569 if (m_pList)
570 m_pList->SetFillerNotify(pNotify);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700571}