blob: b69f98906e0592827275f388c673d4f6658d8890 [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>
10
dsinclair74a34fc2016-09-29 16:41:42 -070011#include "core/fxge/cfx_pathdata.h"
12#include "core/fxge/cfx_renderdevice.h"
dsinclair0bb385b2016-09-29 17:03:59 -070013#include "fpdfsdk/fxedit/fxet_list.h"
Lei Zhang633a3b72017-06-02 15:27:22 -070014#include "fpdfsdk/pdfwindow/cpwl_edit.h"
15#include "fpdfsdk/pdfwindow/cpwl_edit_ctrl.h"
16#include "fpdfsdk/pdfwindow/cpwl_list_box.h"
17#include "fpdfsdk/pdfwindow/cpwl_utils.h"
18#include "fpdfsdk/pdfwindow/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
Nico Weber9d8ec5a2015-08-04 13:00:21 -070021#define PWLCB_DEFAULTFONTSIZE 12.0f
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070022
Dan Sinclairf528eee2017-02-14 11:52:07 -050023bool CPWL_CBListBox::OnLButtonUp(const CFX_PointF& point, uint32_t nFlag) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -070024 CPWL_Wnd::OnLButtonUp(point, nFlag);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070025
dsinclair36177512016-07-19 10:16:10 -070026 if (!m_bMouseDown)
tsepez4cf55152016-11-02 14:37:54 -070027 return true;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070028
dsinclair36177512016-07-19 10:16:10 -070029 ReleaseCapture();
tsepez4cf55152016-11-02 14:37:54 -070030 m_bMouseDown = false;
Lei Zhanga6d9f0e2015-06-13 00:48:38 -070031
dsinclair36177512016-07-19 10:16:10 -070032 if (!ClientHitTest(point))
tsepez4cf55152016-11-02 14:37:54 -070033 return true;
dsinclair36177512016-07-19 10:16:10 -070034 if (CPWL_Wnd* pParent = GetParentWindow())
35 pParent->OnNotify(this, PNM_LBUTTONUP, 0, PWL_MAKEDWORD(point.x, point.y));
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070036
tsepez4cf55152016-11-02 14:37:54 -070037 bool bExit = false;
38 OnNotifySelChanged(false, bExit, nFlag);
dsinclair36177512016-07-19 10:16:10 -070039
40 return !bExit;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070041}
42
tsepez4cf55152016-11-02 14:37:54 -070043bool CPWL_CBListBox::OnKeyDownWithExit(uint16_t nChar,
44 bool& bExit,
45 uint32_t nFlag) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -070046 switch (nChar) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -070047 case FWL_VKEY_Up:
48 case FWL_VKEY_Down:
49 case FWL_VKEY_Home:
50 case FWL_VKEY_Left:
51 case FWL_VKEY_End:
52 case FWL_VKEY_Right:
53 break;
dsinclair36177512016-07-19 10:16:10 -070054 default:
tsepez4cf55152016-11-02 14:37:54 -070055 return false;
Nico Weber9d8ec5a2015-08-04 13:00:21 -070056 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070057
Nico Weber9d8ec5a2015-08-04 13:00:21 -070058 switch (nChar) {
59 case FWL_VKEY_Up:
60 m_pList->OnVK_UP(IsSHIFTpressed(nFlag), IsCTRLpressed(nFlag));
61 break;
62 case FWL_VKEY_Down:
63 m_pList->OnVK_DOWN(IsSHIFTpressed(nFlag), IsCTRLpressed(nFlag));
64 break;
65 case FWL_VKEY_Home:
66 m_pList->OnVK_HOME(IsSHIFTpressed(nFlag), IsCTRLpressed(nFlag));
67 break;
68 case FWL_VKEY_Left:
69 m_pList->OnVK_LEFT(IsSHIFTpressed(nFlag), IsCTRLpressed(nFlag));
70 break;
71 case FWL_VKEY_End:
72 m_pList->OnVK_END(IsSHIFTpressed(nFlag), IsCTRLpressed(nFlag));
73 break;
74 case FWL_VKEY_Right:
75 m_pList->OnVK_RIGHT(IsSHIFTpressed(nFlag), IsCTRLpressed(nFlag));
76 break;
77 case FWL_VKEY_Delete:
78 break;
79 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070080
tsepez4cf55152016-11-02 14:37:54 -070081 OnNotifySelChanged(true, bExit, nFlag);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070082
tsepez4cf55152016-11-02 14:37:54 -070083 return true;
Nico Weber9d8ec5a2015-08-04 13:00:21 -070084}
85
tsepez4cf55152016-11-02 14:37:54 -070086bool CPWL_CBListBox::OnCharWithExit(uint16_t nChar,
87 bool& bExit,
88 uint32_t nFlag) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -070089 if (!m_pList->OnChar(nChar, IsSHIFTpressed(nFlag), IsCTRLpressed(nFlag)))
tsepez4cf55152016-11-02 14:37:54 -070090 return false;
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
tsepez4cf55152016-11-02 14:37:54 -070094 OnNotifySelChanged(true, bExit, nFlag);
Nico Weber9d8ec5a2015-08-04 13:00:21 -070095
tsepez4cf55152016-11-02 14:37:54 -070096 return true;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070097}
98
Nico Weber9d8ec5a2015-08-04 13:00:21 -070099void CPWL_CBButton::GetThisAppearanceStream(CFX_ByteTextBuf& sAppStream) {
100 CPWL_Wnd::GetThisAppearanceStream(sAppStream);
Lei Zhanga6d9f0e2015-06-13 00:48:38 -0700101
Tom Sepez281a9ea2016-02-26 14:24:28 -0800102 CFX_FloatRect rectWnd = CPWL_Wnd::GetWindowRect();
Lei Zhanga6d9f0e2015-06-13 00:48:38 -0700103
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700104 if (IsVisible() && !rectWnd.IsEmpty()) {
105 CFX_ByteTextBuf sButton;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700106
Dan Sinclairf528eee2017-02-14 11:52:07 -0500107 CFX_PointF ptCenter = GetCenterPoint();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700108
Dan Sinclairf528eee2017-02-14 11:52:07 -0500109 CFX_PointF pt1(ptCenter.x - PWL_CBBUTTON_TRIANGLE_HALFLEN,
110 ptCenter.y + PWL_CBBUTTON_TRIANGLE_HALFLEN * 0.5f);
111 CFX_PointF pt2(ptCenter.x + PWL_CBBUTTON_TRIANGLE_HALFLEN,
112 ptCenter.y + PWL_CBBUTTON_TRIANGLE_HALFLEN * 0.5f);
113 CFX_PointF pt3(ptCenter.x,
114 ptCenter.y - PWL_CBBUTTON_TRIANGLE_HALFLEN * 0.5f);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700115
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700116 if (IsFloatBigger(rectWnd.right - rectWnd.left,
117 PWL_CBBUTTON_TRIANGLE_HALFLEN * 2) &&
118 IsFloatBigger(rectWnd.top - rectWnd.bottom,
119 PWL_CBBUTTON_TRIANGLE_HALFLEN)) {
120 sButton << "0 g\n";
121 sButton << pt1.x << " " << pt1.y << " m\n";
122 sButton << pt2.x << " " << pt2.y << " l\n";
123 sButton << pt3.x << " " << pt3.y << " l\n";
124 sButton << pt1.x << " " << pt1.y << " l f\n";
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700125
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700126 sAppStream << "q\n" << sButton << "Q\n";
Tom Sepez2f2ffec2015-07-23 14:42:09 -0700127 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700128 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700129}
130
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700131void CPWL_CBButton::DrawThisAppearance(CFX_RenderDevice* pDevice,
Tom Sepez60d909e2015-12-10 15:34:55 -0800132 CFX_Matrix* pUser2Device) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700133 CPWL_Wnd::DrawThisAppearance(pDevice, pUser2Device);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700134
Tom Sepez281a9ea2016-02-26 14:24:28 -0800135 CFX_FloatRect rectWnd = CPWL_Wnd::GetWindowRect();
Lei Zhanga6d9f0e2015-06-13 00:48:38 -0700136
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700137 if (IsVisible() && !rectWnd.IsEmpty()) {
Dan Sinclairf528eee2017-02-14 11:52:07 -0500138 CFX_PointF ptCenter = GetCenterPoint();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700139
Dan Sinclairf528eee2017-02-14 11:52:07 -0500140 CFX_PointF pt1(ptCenter.x - PWL_CBBUTTON_TRIANGLE_HALFLEN,
141 ptCenter.y + PWL_CBBUTTON_TRIANGLE_HALFLEN * 0.5f);
142 CFX_PointF pt2(ptCenter.x + PWL_CBBUTTON_TRIANGLE_HALFLEN,
143 ptCenter.y + PWL_CBBUTTON_TRIANGLE_HALFLEN * 0.5f);
144 CFX_PointF pt3(ptCenter.x,
145 ptCenter.y - PWL_CBBUTTON_TRIANGLE_HALFLEN * 0.5f);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700146
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700147 if (IsFloatBigger(rectWnd.right - rectWnd.left,
148 PWL_CBBUTTON_TRIANGLE_HALFLEN * 2) &&
149 IsFloatBigger(rectWnd.top - rectWnd.bottom,
150 PWL_CBBUTTON_TRIANGLE_HALFLEN)) {
151 CFX_PathData path;
dan sinclairb147e072017-02-22 19:56:15 -0500152 path.AppendPoint(pt1, FXPT_TYPE::MoveTo, false);
153 path.AppendPoint(pt2, FXPT_TYPE::LineTo, false);
154 path.AppendPoint(pt3, FXPT_TYPE::LineTo, false);
155 path.AppendPoint(pt1, FXPT_TYPE::LineTo, false);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700156
thestig1cd352e2016-06-07 17:53:06 -0700157 pDevice->DrawPath(&path, pUser2Device, nullptr,
Dan Sinclairfc54e052017-02-23 09:59:05 -0500158 PWL_DEFAULT_BLACKCOLOR.ToFXColor(GetTransparency()), 0,
159 FXFILL_ALTERNATE);
Tom Sepez2f2ffec2015-07-23 14:42:09 -0700160 }
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
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700169 if (CPWL_Wnd* pParent = GetParentWindow()) {
170 pParent->OnNotify(this, PNM_LBUTTONDOWN, 0,
171 PWL_MAKEDWORD(point.x, point.y));
172 }
Lei Zhanga6d9f0e2015-06-13 00:48:38 -0700173
tsepez4cf55152016-11-02 14:37:54 -0700174 return true;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700175}
176
Dan Sinclairf528eee2017-02-14 11:52:07 -0500177bool CPWL_CBButton::OnLButtonUp(const CFX_PointF& point, uint32_t nFlag) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700178 CPWL_Wnd::OnLButtonUp(point, nFlag);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700179
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700180 ReleaseCapture();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700181
tsepez4cf55152016-11-02 14:37:54 -0700182 return true;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700183}
184
Lei Zhang35162562017-06-09 01:04:52 -0700185CPWL_ComboBox::CPWL_ComboBox() {}
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700186
Tom Sepezb084c1f2017-05-12 14:04:06 -0700187CPWL_ComboBox::~CPWL_ComboBox() {}
188
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700189CFX_ByteString CPWL_ComboBox::GetClassName() const {
190 return "CPWL_ComboBox";
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700191}
192
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700193void CPWL_ComboBox::OnCreate(PWL_CREATEPARAM& cp) {
194 cp.dwFlags &= ~PWS_HSCROLL;
195 cp.dwFlags &= ~PWS_VSCROLL;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700196}
197
Lei Zhang35162562017-06-09 01:04:52 -0700198void CPWL_ComboBox::OnDestroy() {
199 // Until cleanup takes place in the virtual destructor for CPWL_Wnd
200 // subclasses, implement the virtual OnDestroy method that does the
201 // cleanup first, then invokes the superclass OnDestroy ... gee,
202 // like a dtor would.
203 m_pList.Release();
204 m_pButton.Release();
205 m_pEdit.Release();
206 CPWL_Wnd::OnDestroy();
207}
208
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700209void CPWL_ComboBox::SetFocus() {
210 if (m_pEdit)
211 m_pEdit->SetFocus();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700212}
213
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700214void CPWL_ComboBox::KillFocus() {
tsepez4cf55152016-11-02 14:37:54 -0700215 SetPopup(false);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700216 CPWL_Wnd::KillFocus();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700217}
218
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700219CFX_WideString CPWL_ComboBox::GetText() const {
220 if (m_pEdit) {
221 return m_pEdit->GetText();
222 }
223 return CFX_WideString();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700224}
225
tsepez067990c2016-09-13 06:46:40 -0700226void CPWL_ComboBox::SetText(const CFX_WideString& text) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700227 if (m_pEdit)
228 m_pEdit->SetText(text);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700229}
230
tsepez067990c2016-09-13 06:46:40 -0700231void CPWL_ComboBox::AddString(const CFX_WideString& str) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700232 if (m_pList)
Dan Sinclair3ebd1212016-03-09 09:59:23 -0500233 m_pList->AddString(str);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700234}
235
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700236int32_t CPWL_ComboBox::GetSelect() const {
237 return m_nSelectItem;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700238}
239
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700240void CPWL_ComboBox::SetSelect(int32_t nItemIndex) {
241 if (m_pList)
242 m_pList->Select(nItemIndex);
243
tsepez067990c2016-09-13 06:46:40 -0700244 m_pEdit->SetText(m_pList->GetText());
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700245 m_nSelectItem = nItemIndex;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700246}
247
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700248void CPWL_ComboBox::SetEditSel(int32_t nStartChar, int32_t nEndChar) {
tsepez067990c2016-09-13 06:46:40 -0700249 if (m_pEdit)
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700250 m_pEdit->SetSel(nStartChar, nEndChar);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700251}
252
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700253void CPWL_ComboBox::GetEditSel(int32_t& nStartChar, int32_t& nEndChar) const {
254 nStartChar = -1;
255 nEndChar = -1;
256
tsepez067990c2016-09-13 06:46:40 -0700257 if (m_pEdit)
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700258 m_pEdit->GetSel(nStartChar, nEndChar);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700259}
260
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700261void CPWL_ComboBox::Clear() {
tsepez067990c2016-09-13 06:46:40 -0700262 if (m_pEdit)
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700263 m_pEdit->Clear();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700264}
265
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700266void CPWL_ComboBox::CreateChildWnd(const PWL_CREATEPARAM& cp) {
267 CreateEdit(cp);
268 CreateButton(cp);
269 CreateListBox(cp);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700270}
271
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700272void CPWL_ComboBox::CreateEdit(const PWL_CREATEPARAM& cp) {
Tom Sepezb084c1f2017-05-12 14:04:06 -0700273 if (m_pEdit)
274 return;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700275
Tom Sepez45b9ae12017-05-18 08:34:03 -0700276 m_pEdit = new CPWL_CBEdit();
Tom Sepezcc205132017-05-16 14:01:47 -0700277 m_pEdit->AttachFFLData(m_pFormFiller.Get());
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700278
Tom Sepezb084c1f2017-05-12 14:04:06 -0700279 PWL_CREATEPARAM ecp = cp;
280 ecp.pParentWnd = this;
281 ecp.dwFlags = PWS_VISIBLE | PWS_CHILD | PWS_BORDER | PES_CENTER |
282 PES_AUTOSCROLL | PES_UNDO;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700283
Tom Sepezb084c1f2017-05-12 14:04:06 -0700284 if (HasFlag(PWS_AUTOFONTSIZE))
285 ecp.dwFlags |= PWS_AUTOFONTSIZE;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700286
Tom Sepezb084c1f2017-05-12 14:04:06 -0700287 if (!HasFlag(PCBS_ALLOWCUSTOMTEXT))
288 ecp.dwFlags |= PWS_READONLY;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700289
Tom Sepezb084c1f2017-05-12 14:04:06 -0700290 ecp.rcRectWnd = CFX_FloatRect(0, 0, 0, 0);
291 ecp.dwBorderWidth = 0;
292 ecp.nBorderStyle = BorderStyle::SOLID;
293 m_pEdit->Create(ecp);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700294}
295
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700296void CPWL_ComboBox::CreateButton(const PWL_CREATEPARAM& cp) {
Tom Sepezb084c1f2017-05-12 14:04:06 -0700297 if (m_pButton)
298 return;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700299
Tom Sepez45b9ae12017-05-18 08:34:03 -0700300 m_pButton = new CPWL_CBButton;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700301
Tom Sepezb084c1f2017-05-12 14:04:06 -0700302 PWL_CREATEPARAM bcp = cp;
303 bcp.pParentWnd = this;
304 bcp.dwFlags = PWS_VISIBLE | PWS_CHILD | PWS_BORDER | PWS_BACKGROUND;
305 bcp.sBackgroundColor = PWL_SCROLLBAR_BKCOLOR;
306 bcp.sBorderColor = PWL_DEFAULT_BLACKCOLOR;
307 bcp.dwBorderWidth = 2;
308 bcp.nBorderStyle = BorderStyle::BEVELED;
309 bcp.eCursorType = FXCT_ARROW;
310 m_pButton->Create(bcp);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700311}
312
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700313void CPWL_ComboBox::CreateListBox(const PWL_CREATEPARAM& cp) {
Tom Sepezb084c1f2017-05-12 14:04:06 -0700314 if (m_pList)
315 return;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700316
Tom Sepez45b9ae12017-05-18 08:34:03 -0700317 m_pList = new CPWL_CBListBox();
Tom Sepezcc205132017-05-16 14:01:47 -0700318 m_pList->AttachFFLData(m_pFormFiller.Get());
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700319
Tom Sepezb084c1f2017-05-12 14:04:06 -0700320 PWL_CREATEPARAM lcp = cp;
321 lcp.pParentWnd = this;
322 lcp.dwFlags =
323 PWS_CHILD | PWS_BORDER | PWS_BACKGROUND | PLBS_HOVERSEL | PWS_VSCROLL;
324 lcp.nBorderStyle = BorderStyle::SOLID;
325 lcp.dwBorderWidth = 1;
326 lcp.eCursorType = FXCT_ARROW;
327 lcp.rcRectWnd = CFX_FloatRect(0, 0, 0, 0);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700328
Tom Sepezb084c1f2017-05-12 14:04:06 -0700329 if (cp.dwFlags & PWS_AUTOFONTSIZE)
330 lcp.fFontSize = PWLCB_DEFAULTFONTSIZE;
331 else
332 lcp.fFontSize = cp.fFontSize;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700333
Tom Sepezb084c1f2017-05-12 14:04:06 -0700334 if (cp.sBorderColor.nColorType == COLORTYPE_TRANSPARENT)
335 lcp.sBorderColor = PWL_DEFAULT_BLACKCOLOR;
336
337 if (cp.sBackgroundColor.nColorType == COLORTYPE_TRANSPARENT)
338 lcp.sBackgroundColor = PWL_DEFAULT_WHITECOLOR;
339
340 m_pList->Create(lcp);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700341}
342
343void CPWL_ComboBox::RePosChildWnd() {
Lei Zhang7bef7c82017-05-31 23:52:00 -0700344 const CFX_FloatRect rcClient = GetClientRect();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700345 if (m_bPopup) {
Lei Zhang7bef7c82017-05-31 23:52:00 -0700346 const float fOldWindowHeight = m_rcOldWindow.Height();
347 const float fOldClientHeight = fOldWindowHeight - GetBorderWidth() * 2;
348
Tom Sepez281a9ea2016-02-26 14:24:28 -0800349 CFX_FloatRect rcList = CPWL_Wnd::GetWindowRect();
Lei Zhang7bef7c82017-05-31 23:52:00 -0700350 CFX_FloatRect rcButton = rcClient;
351 rcButton.left =
352 std::max(rcButton.right - PWL_COMBOBOX_BUTTON_WIDTH, rcClient.left);
353 CFX_FloatRect rcEdit = rcClient;
354 rcEdit.right = std::max(rcButton.left - 1.0f, rcEdit.left);
355 if (m_bBottom) {
356 rcButton.bottom = rcButton.top - fOldClientHeight;
357 rcEdit.bottom = rcEdit.top - fOldClientHeight;
358 rcList.top -= fOldWindowHeight;
359 } else {
360 rcButton.top = rcButton.bottom + fOldClientHeight;
361 rcEdit.top = rcEdit.bottom + fOldClientHeight;
362 rcList.bottom += fOldWindowHeight;
Tom Sepez2f2ffec2015-07-23 14:42:09 -0700363 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700364
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700365 if (m_pButton)
tsepez4cf55152016-11-02 14:37:54 -0700366 m_pButton->Move(rcButton, true, false);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700367
368 if (m_pEdit)
tsepez4cf55152016-11-02 14:37:54 -0700369 m_pEdit->Move(rcEdit, true, false);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700370
371 if (m_pList) {
tsepez4cf55152016-11-02 14:37:54 -0700372 m_pList->SetVisible(true);
373 m_pList->Move(rcList, true, false);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700374 m_pList->ScrollToListItem(m_nSelectItem);
375 }
Lei Zhang7bef7c82017-05-31 23:52:00 -0700376 return;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700377 }
Lei Zhang7bef7c82017-05-31 23:52:00 -0700378
379 CFX_FloatRect rcButton = rcClient;
380 rcButton.left =
381 std::max(rcButton.right - PWL_COMBOBOX_BUTTON_WIDTH, rcClient.left);
382
383 if (m_pButton)
384 m_pButton->Move(rcButton, true, false);
385
386 CFX_FloatRect rcEdit = rcClient;
387 rcEdit.right = std::max(rcButton.left - 1.0f, rcEdit.left);
388
389 if (m_pEdit)
390 m_pEdit->Move(rcEdit, true, false);
391
392 if (m_pList)
393 m_pList->SetVisible(false);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700394}
395
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700396void CPWL_ComboBox::SelectAll() {
397 if (m_pEdit && HasFlag(PCBS_ALLOWCUSTOMTEXT))
Tom Sepez2f2ffec2015-07-23 14:42:09 -0700398 m_pEdit->SelectAll();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700399}
400
Tom Sepez281a9ea2016-02-26 14:24:28 -0800401CFX_FloatRect CPWL_ComboBox::GetFocusRect() const {
402 return CFX_FloatRect();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700403}
404
tsepez4cf55152016-11-02 14:37:54 -0700405void CPWL_ComboBox::SetPopup(bool bPopup) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700406 if (!m_pList)
407 return;
408 if (bPopup == m_bPopup)
409 return;
Dan Sinclair05df0752017-03-14 14:43:42 -0400410 float fListHeight = m_pList->GetContentRect().Height();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700411 if (!IsFloatBigger(fListHeight, 0.0f))
412 return;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700413
Lei Zhang7bef7c82017-05-31 23:52:00 -0700414 if (!bPopup) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700415 m_bPopup = bPopup;
tsepez4cf55152016-11-02 14:37:54 -0700416 Move(m_rcOldWindow, true, true);
Lei Zhang7bef7c82017-05-31 23:52:00 -0700417 return;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700418 }
Lei Zhang7bef7c82017-05-31 23:52:00 -0700419
420 if (!m_pFillerNotify)
421 return;
422
423#ifdef PDF_ENABLE_XFA
424 bool bExit = false;
425 m_pFillerNotify->OnPopupPreOpen(GetAttachedData(), bExit, 0);
426 if (bExit)
427 return;
428#endif // PDF_ENABLE_XFA
429
430 float fBorderWidth = m_pList->GetBorderWidth() * 2;
431 float fPopupMin = 0.0f;
432 if (m_pList->GetCount() > 3)
433 fPopupMin = m_pList->GetFirstHeight() * 3 + fBorderWidth;
434 float fPopupMax = fListHeight + fBorderWidth;
435
436 bool bBottom;
437 float fPopupRet;
438 m_pFillerNotify->QueryWherePopup(GetAttachedData(), fPopupMin, fPopupMax,
439 &bBottom, &fPopupRet);
440 if (!IsFloatBigger(fPopupRet, 0.0f))
441 return;
442
443 m_rcOldWindow = CPWL_Wnd::GetWindowRect();
444 m_bPopup = bPopup;
445 m_bBottom = bBottom;
446
447 CFX_FloatRect rcWindow = m_rcOldWindow;
448 if (bBottom)
449 rcWindow.bottom -= fPopupRet;
450 else
451 rcWindow.top += fPopupRet;
452
453 Move(rcWindow, true, true);
454#ifdef PDF_ENABLE_XFA
455 bExit = false;
456 m_pFillerNotify->OnPopupPostOpen(GetAttachedData(), bExit, 0);
457#endif // PDF_ENABLE_XFA
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700458}
459
tsepez4cf55152016-11-02 14:37:54 -0700460bool CPWL_ComboBox::OnKeyDown(uint16_t nChar, uint32_t nFlag) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700461 if (!m_pList)
tsepez4cf55152016-11-02 14:37:54 -0700462 return false;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700463 if (!m_pEdit)
tsepez4cf55152016-11-02 14:37:54 -0700464 return false;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700465
466 m_nSelectItem = -1;
467
468 switch (nChar) {
469 case FWL_VKEY_Up:
470 if (m_pList->GetCurSel() > 0) {
tsepez4cf55152016-11-02 14:37:54 -0700471 bool bExit = false;
Tom Sepez51da0932015-11-25 16:05:49 -0800472#ifdef PDF_ENABLE_XFA
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700473 if (m_pFillerNotify) {
474 m_pFillerNotify->OnPopupPreOpen(GetAttachedData(), bExit, nFlag);
475 if (bExit)
tsepez4cf55152016-11-02 14:37:54 -0700476 return false;
477 bExit = false;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700478 m_pFillerNotify->OnPopupPostOpen(GetAttachedData(), bExit, nFlag);
479 if (bExit)
tsepez4cf55152016-11-02 14:37:54 -0700480 return false;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700481 }
Tom Sepez40e9ff32015-11-30 12:39:54 -0800482#endif // PDF_ENABLE_XFA
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700483 if (m_pList->OnKeyDownWithExit(nChar, bExit, nFlag)) {
484 if (bExit)
tsepez4cf55152016-11-02 14:37:54 -0700485 return false;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700486 SetSelectText();
487 }
488 }
tsepez4cf55152016-11-02 14:37:54 -0700489 return true;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700490 case FWL_VKEY_Down:
491 if (m_pList->GetCurSel() < m_pList->GetCount() - 1) {
tsepez4cf55152016-11-02 14:37:54 -0700492 bool bExit = false;
Tom Sepez51da0932015-11-25 16:05:49 -0800493#ifdef PDF_ENABLE_XFA
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700494 if (m_pFillerNotify) {
495 m_pFillerNotify->OnPopupPreOpen(GetAttachedData(), bExit, nFlag);
496 if (bExit)
tsepez4cf55152016-11-02 14:37:54 -0700497 return false;
498 bExit = false;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700499 m_pFillerNotify->OnPopupPostOpen(GetAttachedData(), bExit, nFlag);
500 if (bExit)
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
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700504 if (m_pList->OnKeyDownWithExit(nChar, bExit, nFlag)) {
505 if (bExit)
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
tsepez4cf55152016-11-02 14:37:54 -0700530 bool bExit = false;
Tom Sepez51da0932015-11-25 16:05:49 -0800531#ifdef PDF_ENABLE_XFA
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700532 if (m_pFillerNotify) {
533 m_pFillerNotify->OnPopupPreOpen(GetAttachedData(), bExit, nFlag);
534 if (bExit)
tsepez4cf55152016-11-02 14:37:54 -0700535 return false;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700536
537 m_pFillerNotify->OnPopupPostOpen(GetAttachedData(), bExit, nFlag);
538 if (bExit)
tsepez4cf55152016-11-02 14:37:54 -0700539 return false;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700540 }
Tom Sepez40e9ff32015-11-30 12:39:54 -0800541#endif // PDF_ENABLE_XFA
tsepez4cf55152016-11-02 14:37:54 -0700542 return m_pList->OnCharWithExit(nChar, bExit, nFlag) ? bExit : false;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700543}
544
545void CPWL_ComboBox::OnNotify(CPWL_Wnd* pWnd,
tsepezc3255f52016-03-25 14:52:27 -0700546 uint32_t msg,
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700547 intptr_t wParam,
548 intptr_t lParam) {
549 switch (msg) {
550 case PNM_LBUTTONDOWN:
Tom Sepez45b9ae12017-05-18 08:34:03 -0700551 if (pWnd == m_pButton) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700552 SetPopup(!m_bPopup);
553 return;
554 }
555 break;
556 case PNM_LBUTTONUP:
557 if (m_pEdit && m_pList) {
Tom Sepez45b9ae12017-05-18 08:34:03 -0700558 if (pWnd == m_pList) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700559 SetSelectText();
560 SelectAll();
561 m_pEdit->SetFocus();
tsepez4cf55152016-11-02 14:37:54 -0700562 SetPopup(false);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700563 return;
564 }
565 }
Tom Sepezb084c1f2017-05-12 14:04:06 -0700566 break;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700567 }
568
569 CPWL_Wnd::OnNotify(pWnd, msg, wParam, lParam);
570}
571
tsepez4cf55152016-11-02 14:37:54 -0700572bool CPWL_ComboBox::IsPopup() const {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700573 return m_bPopup;
574}
575
576void CPWL_ComboBox::SetSelectText() {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700577 m_pEdit->SelectAll();
tsepez067990c2016-09-13 06:46:40 -0700578 m_pEdit->ReplaceSel(m_pList->GetText());
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700579 m_pEdit->SelectAll();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700580 m_nSelectItem = m_pList->GetCurSel();
581}
582
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700583void CPWL_ComboBox::SetFillerNotify(IPWL_Filler_Notify* pNotify) {
584 m_pFillerNotify = pNotify;
585
586 if (m_pEdit)
587 m_pEdit->SetFillerNotify(pNotify);
588
589 if (m_pList)
590 m_pList->SetFillerNotify(pNotify);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700591}