cffl_combobox.cpp revision 4d3acf4ec42bf6e838f9060103aff98fbf170794
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 "fpdfsdk/formfiller/cffl_combobox.h"
8
9#include "fpdfsdk/cpdfsdk_formfillenvironment.h"
10#include "fpdfsdk/cpdfsdk_widget.h"
11#include "fpdfsdk/formfiller/cba_fontmap.h"
12#include "fpdfsdk/formfiller/cffl_formfiller.h"
13#include "fpdfsdk/formfiller/cffl_interactiveformfiller.h"
14#include "fpdfsdk/fsdk_common.h"
15#include "fpdfsdk/pdfwindow/PWL_ComboBox.h"
16
17CFFL_ComboBox::CFFL_ComboBox(CPDFSDK_FormFillEnvironment* pApp,
18                             CPDFSDK_Annot* pAnnot)
19    : CFFL_FormFiller(pApp, pAnnot), m_pFontMap(nullptr) {
20  m_State.nIndex = 0;
21  m_State.nStart = 0;
22  m_State.nEnd = 0;
23}
24
25CFFL_ComboBox::~CFFL_ComboBox() {
26  for (const auto& it : m_Maps)
27    it.second->InvalidateFocusHandler(this);
28
29  // See comment in cffl_formfiller.h.
30  // The font map should be stored somewhere more appropriate so it will live
31  // until the PWL_Edit is done with it. pdfium:566
32  DestroyWindows();
33  delete m_pFontMap;
34}
35
36PWL_CREATEPARAM CFFL_ComboBox::GetCreateParam() {
37  PWL_CREATEPARAM cp = CFFL_FormFiller::GetCreateParam();
38
39  int nFlags = m_pWidget->GetFieldFlags();
40  if (nFlags & FIELDFLAG_EDIT) {
41    cp.dwFlags |= PCBS_ALLOWCUSTOMTEXT;
42  }
43
44  if (!m_pFontMap)
45    m_pFontMap = new CBA_FontMap(m_pWidget, GetSystemHandler());
46  cp.pFontMap = m_pFontMap;
47  cp.pFocusHandler = this;
48
49  return cp;
50}
51
52CPWL_Wnd* CFFL_ComboBox::NewPDFWindow(const PWL_CREATEPARAM& cp,
53                                      CPDFSDK_PageView* pPageView) {
54  CPWL_ComboBox* pWnd = new CPWL_ComboBox();
55  pWnd->AttachFFLData(this);
56  pWnd->Create(cp);
57
58  CFFL_InteractiveFormFiller* pFormFiller =
59      m_pFormFillEnv->GetInteractiveFormFiller();
60  pWnd->SetFillerNotify(pFormFiller);
61
62  int32_t nCurSel = m_pWidget->GetSelectedIndex(0);
63  CFX_WideString swText;
64  if (nCurSel < 0)
65    swText = m_pWidget->GetValue();
66  else
67    swText = m_pWidget->GetOptionLabel(nCurSel);
68
69  for (int32_t i = 0, sz = m_pWidget->CountOptions(); i < sz; i++) {
70    pWnd->AddString(m_pWidget->GetOptionLabel(i));
71  }
72
73  pWnd->SetSelect(nCurSel);
74  pWnd->SetText(swText);
75  return pWnd;
76}
77
78bool CFFL_ComboBox::OnChar(CPDFSDK_Annot* pAnnot,
79                           uint32_t nChar,
80                           uint32_t nFlags) {
81  return CFFL_FormFiller::OnChar(pAnnot, nChar, nFlags);
82}
83
84bool CFFL_ComboBox::IsDataChanged(CPDFSDK_PageView* pPageView) {
85  CPWL_ComboBox* pWnd = (CPWL_ComboBox*)GetPDFWindow(pPageView, false);
86  if (!pWnd)
87    return false;
88
89  int32_t nCurSel = pWnd->GetSelect();
90  if (!(m_pWidget->GetFieldFlags() & FIELDFLAG_EDIT))
91    return nCurSel != m_pWidget->GetSelectedIndex(0);
92
93  if (nCurSel >= 0)
94    return nCurSel != m_pWidget->GetSelectedIndex(0);
95
96  return pWnd->GetText() != m_pWidget->GetValue();
97}
98
99void CFFL_ComboBox::SaveData(CPDFSDK_PageView* pPageView) {
100  CPWL_ComboBox* pWnd =
101      static_cast<CPWL_ComboBox*>(GetPDFWindow(pPageView, false));
102  if (!pWnd)
103    return;
104
105  CFX_WideString swText = pWnd->GetText();
106  int32_t nCurSel = pWnd->GetSelect();
107
108  bool bSetValue = false;
109
110  if (m_pWidget->GetFieldFlags() & FIELDFLAG_EDIT)
111    bSetValue = (nCurSel < 0) || (swText != m_pWidget->GetOptionLabel(nCurSel));
112
113  if (bSetValue) {
114    m_pWidget->SetValue(swText, false);
115  } else {
116    m_pWidget->GetSelectedIndex(0);
117    m_pWidget->SetOptionSelection(nCurSel, true, false);
118  }
119
120  m_pWidget->ResetFieldAppearance(true);
121  m_pWidget->UpdateField();
122  SetChangeMark();
123
124  m_pWidget->GetPDFPage();
125}
126
127void CFFL_ComboBox::GetActionData(CPDFSDK_PageView* pPageView,
128                                  CPDF_AAction::AActionType type,
129                                  PDFSDK_FieldAction& fa) {
130  switch (type) {
131    case CPDF_AAction::KeyStroke:
132      if (CPWL_ComboBox* pComboBox =
133              static_cast<CPWL_ComboBox*>(GetPDFWindow(pPageView, false))) {
134        if (CPWL_Edit* pEdit = pComboBox->GetEdit()) {
135          fa.bFieldFull = pEdit->IsTextFull();
136          int nSelStart = 0;
137          int nSelEnd = 0;
138          pEdit->GetSel(nSelStart, nSelEnd);
139          fa.nSelEnd = nSelEnd;
140          fa.nSelStart = nSelStart;
141          fa.sValue = pEdit->GetText();
142          fa.sChangeEx = GetSelectExportText();
143
144          if (fa.bFieldFull) {
145            fa.sChange = L"";
146            fa.sChangeEx = L"";
147          }
148        }
149      }
150      break;
151    case CPDF_AAction::Validate:
152      if (CPWL_ComboBox* pComboBox =
153              static_cast<CPWL_ComboBox*>(GetPDFWindow(pPageView, false))) {
154        if (CPWL_Edit* pEdit = pComboBox->GetEdit()) {
155          fa.sValue = pEdit->GetText();
156        }
157      }
158      break;
159    case CPDF_AAction::LoseFocus:
160    case CPDF_AAction::GetFocus:
161      fa.sValue = m_pWidget->GetValue();
162      break;
163    default:
164      break;
165  }
166}
167
168void CFFL_ComboBox::SetActionData(CPDFSDK_PageView* pPageView,
169                                  CPDF_AAction::AActionType type,
170                                  const PDFSDK_FieldAction& fa) {
171  switch (type) {
172    case CPDF_AAction::KeyStroke:
173      if (CPWL_ComboBox* pComboBox =
174              static_cast<CPWL_ComboBox*>(GetPDFWindow(pPageView, false))) {
175        if (CPWL_Edit* pEdit = pComboBox->GetEdit()) {
176          pEdit->SetSel(fa.nSelStart, fa.nSelEnd);
177          pEdit->ReplaceSel(fa.sChange);
178        }
179      }
180      break;
181    default:
182      break;
183  }
184}
185
186bool CFFL_ComboBox::IsActionDataChanged(CPDF_AAction::AActionType type,
187                                        const PDFSDK_FieldAction& faOld,
188                                        const PDFSDK_FieldAction& faNew) {
189  switch (type) {
190    case CPDF_AAction::KeyStroke:
191      return (!faOld.bFieldFull && faOld.nSelEnd != faNew.nSelEnd) ||
192             faOld.nSelStart != faNew.nSelStart ||
193             faOld.sChange != faNew.sChange;
194    default:
195      break;
196  }
197
198  return false;
199}
200
201void CFFL_ComboBox::SaveState(CPDFSDK_PageView* pPageView) {
202  ASSERT(pPageView);
203
204  if (CPWL_ComboBox* pComboBox =
205          static_cast<CPWL_ComboBox*>(GetPDFWindow(pPageView, false))) {
206    m_State.nIndex = pComboBox->GetSelect();
207
208    if (CPWL_Edit* pEdit = pComboBox->GetEdit()) {
209      pEdit->GetSel(m_State.nStart, m_State.nEnd);
210      m_State.sValue = pEdit->GetText();
211    }
212  }
213}
214
215void CFFL_ComboBox::RestoreState(CPDFSDK_PageView* pPageView) {
216  ASSERT(pPageView);
217
218  if (CPWL_ComboBox* pComboBox =
219          static_cast<CPWL_ComboBox*>(GetPDFWindow(pPageView, true))) {
220    if (m_State.nIndex >= 0) {
221      pComboBox->SetSelect(m_State.nIndex);
222    } else {
223      if (CPWL_Edit* pEdit = pComboBox->GetEdit()) {
224        pEdit->SetText(m_State.sValue);
225        pEdit->SetSel(m_State.nStart, m_State.nEnd);
226      }
227    }
228  }
229}
230
231CPWL_Wnd* CFFL_ComboBox::ResetPDFWindow(CPDFSDK_PageView* pPageView,
232                                        bool bRestoreValue) {
233  if (bRestoreValue)
234    SaveState(pPageView);
235
236  DestroyPDFWindow(pPageView);
237
238  CPWL_Wnd* pRet = nullptr;
239
240  if (bRestoreValue) {
241    RestoreState(pPageView);
242    pRet = GetPDFWindow(pPageView, false);
243  } else {
244    pRet = GetPDFWindow(pPageView, true);
245  }
246
247  m_pWidget->UpdateField();
248
249  return pRet;
250}
251
252#ifdef PDF_ENABLE_XFA
253bool CFFL_ComboBox::IsFieldFull(CPDFSDK_PageView* pPageView) {
254  if (CPWL_ComboBox* pComboBox =
255          static_cast<CPWL_ComboBox*>(GetPDFWindow(pPageView, false))) {
256    if (CPWL_Edit* pEdit = pComboBox->GetEdit())
257      return pEdit->IsTextFull();
258  }
259  return false;
260}
261#endif  // PDF_ENABLE_XFA
262
263void CFFL_ComboBox::OnSetFocus(CPWL_Wnd* pWnd) {
264  ASSERT(m_pFormFillEnv);
265
266  if (pWnd->GetClassName() == PWL_CLASSNAME_EDIT) {
267    CPWL_Edit* pEdit = (CPWL_Edit*)pWnd;
268    pEdit->SetCharSet(FXFONT_GB2312_CHARSET);
269    pEdit->SetCodePage(936);
270
271    pEdit->SetReadyToInput();
272    CFX_WideString wsText = pEdit->GetText();
273    int nCharacters = wsText.GetLength();
274    CFX_ByteString bsUTFText = wsText.UTF16LE_Encode();
275    unsigned short* pBuffer = (unsigned short*)bsUTFText.c_str();
276    m_pFormFillEnv->OnSetFieldInputFocus(pBuffer, nCharacters, true);
277  }
278}
279
280CFX_WideString CFFL_ComboBox::GetSelectExportText() {
281  CFX_WideString swRet;
282
283  int nExport = -1;
284  CPDFSDK_PageView* pPageView = GetCurPageView(true);
285  if (CPWL_ComboBox* pComboBox =
286          (CPWL_ComboBox*)GetPDFWindow(pPageView, false)) {
287    nExport = pComboBox->GetSelect();
288  }
289
290  if (nExport >= 0) {
291    if (CPDF_FormField* pFormField = m_pWidget->GetFormField()) {
292      swRet = pFormField->GetOptionValue(nExport);
293      if (swRet.IsEmpty())
294        swRet = pFormField->GetOptionLabel(nExport);
295    }
296  }
297
298  return swRet;
299}
300