cffl_listbox.cpp revision 5ae9d0c6fd838a2967cca72aa5751b51dadc2769
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_listbox.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_ListBox.h"
16#include "third_party/base/ptr_util.h"
17
18#define FFL_DEFAULTLISTBOXFONTSIZE 12.0f
19
20CFFL_ListBox::CFFL_ListBox(CPDFSDK_FormFillEnvironment* pApp,
21                           CPDFSDK_Annot* pWidget)
22    : CFFL_FormFiller(pApp, pWidget) {}
23
24CFFL_ListBox::~CFFL_ListBox() {}
25
26PWL_CREATEPARAM CFFL_ListBox::GetCreateParam() {
27  PWL_CREATEPARAM cp = CFFL_FormFiller::GetCreateParam();
28
29  uint32_t dwFieldFlag = m_pWidget->GetFieldFlags();
30
31  if (dwFieldFlag & FIELDFLAG_MULTISELECT) {
32    cp.dwFlags |= PLBS_MULTIPLESEL;
33  }
34
35  cp.dwFlags |= PWS_VSCROLL;
36
37  if (cp.dwFlags & PWS_AUTOFONTSIZE)
38    cp.fFontSize = FFL_DEFAULTLISTBOXFONTSIZE;
39
40  if (!m_pFontMap) {
41    m_pFontMap = pdfium::MakeUnique<CBA_FontMap>(
42        m_pWidget, m_pFormFillEnv->GetSysHandler());
43  }
44  cp.pFontMap = m_pFontMap.get();
45
46  return cp;
47}
48
49CPWL_Wnd* CFFL_ListBox::NewPDFWindow(const PWL_CREATEPARAM& cp,
50                                     CPDFSDK_PageView* pPageView) {
51  CPWL_ListBox* pWnd = new CPWL_ListBox();
52  pWnd->AttachFFLData(this);
53  pWnd->Create(cp);
54  pWnd->SetFillerNotify(m_pFormFillEnv->GetInteractiveFormFiller());
55
56  for (int32_t i = 0, sz = m_pWidget->CountOptions(); i < sz; i++)
57    pWnd->AddString(m_pWidget->GetOptionLabel(i));
58
59  if (pWnd->HasFlag(PLBS_MULTIPLESEL)) {
60    m_OriginSelections.clear();
61
62    bool bSetCaret = false;
63    for (int32_t i = 0, sz = m_pWidget->CountOptions(); i < sz; i++) {
64      if (m_pWidget->IsOptionSelected(i)) {
65        if (!bSetCaret) {
66          pWnd->SetCaret(i);
67          bSetCaret = true;
68        }
69        pWnd->Select(i);
70        m_OriginSelections.insert(i);
71      }
72    }
73  } else {
74    for (int i = 0, sz = m_pWidget->CountOptions(); i < sz; i++) {
75      if (m_pWidget->IsOptionSelected(i)) {
76        pWnd->Select(i);
77        break;
78      }
79    }
80  }
81
82  pWnd->SetTopVisibleIndex(m_pWidget->GetTopVisibleIndex());
83
84  return pWnd;
85}
86
87bool CFFL_ListBox::OnChar(CPDFSDK_Annot* pAnnot,
88                          uint32_t nChar,
89                          uint32_t nFlags) {
90  return CFFL_FormFiller::OnChar(pAnnot, nChar, nFlags);
91}
92
93bool CFFL_ListBox::IsDataChanged(CPDFSDK_PageView* pPageView) {
94  CPWL_ListBox* pListBox = (CPWL_ListBox*)GetPDFWindow(pPageView, false);
95  if (!pListBox)
96    return false;
97
98  if (m_pWidget->GetFieldFlags() & FIELDFLAG_MULTISELECT) {
99    size_t nSelCount = 0;
100    for (int32_t i = 0, sz = pListBox->GetCount(); i < sz; ++i) {
101      if (pListBox->IsItemSelected(i)) {
102        if (m_OriginSelections.count(i) == 0)
103          return true;
104
105        ++nSelCount;
106      }
107    }
108
109    return nSelCount != m_OriginSelections.size();
110  }
111  return pListBox->GetCurSel() != m_pWidget->GetSelectedIndex(0);
112}
113
114void CFFL_ListBox::SaveData(CPDFSDK_PageView* pPageView) {
115  CPWL_ListBox* pListBox =
116      static_cast<CPWL_ListBox*>(GetPDFWindow(pPageView, false));
117  if (!pListBox)
118    return;
119
120  int32_t nNewTopIndex = pListBox->GetTopVisibleIndex();
121  m_pWidget->ClearSelection(false);
122  if (m_pWidget->GetFieldFlags() & FIELDFLAG_MULTISELECT) {
123    for (int32_t i = 0, sz = pListBox->GetCount(); i < sz; i++) {
124      if (pListBox->IsItemSelected(i))
125        m_pWidget->SetOptionSelection(i, true, false);
126    }
127  } else {
128    m_pWidget->SetOptionSelection(pListBox->GetCurSel(), true, false);
129  }
130  m_pWidget->SetTopVisibleIndex(nNewTopIndex);
131  m_pWidget->ResetFieldAppearance(true);
132  m_pWidget->UpdateField();
133  SetChangeMark();
134}
135
136void CFFL_ListBox::GetActionData(CPDFSDK_PageView* pPageView,
137                                 CPDF_AAction::AActionType type,
138                                 PDFSDK_FieldAction& fa) {
139  switch (type) {
140    case CPDF_AAction::Validate:
141      if (m_pWidget->GetFieldFlags() & FIELDFLAG_MULTISELECT) {
142        fa.sValue = L"";
143      } else {
144        if (CPWL_ListBox* pListBox =
145                (CPWL_ListBox*)GetPDFWindow(pPageView, false)) {
146          int32_t nCurSel = pListBox->GetCurSel();
147          if (nCurSel >= 0)
148            fa.sValue = m_pWidget->GetOptionLabel(nCurSel);
149        }
150      }
151      break;
152    case CPDF_AAction::LoseFocus:
153    case CPDF_AAction::GetFocus:
154      if (m_pWidget->GetFieldFlags() & FIELDFLAG_MULTISELECT) {
155        fa.sValue = L"";
156      } else {
157        int32_t nCurSel = m_pWidget->GetSelectedIndex(0);
158        if (nCurSel >= 0)
159          fa.sValue = m_pWidget->GetOptionLabel(nCurSel);
160      }
161      break;
162    default:
163      break;
164  }
165}
166
167void CFFL_ListBox::SaveState(CPDFSDK_PageView* pPageView) {
168  ASSERT(pPageView);
169
170  CPWL_ListBox* pListBox =
171      static_cast<CPWL_ListBox*>(GetPDFWindow(pPageView, false));
172  if (!pListBox)
173    return;
174
175  for (int32_t i = 0, sz = pListBox->GetCount(); i < sz; i++) {
176    if (pListBox->IsItemSelected(i))
177      m_State.push_back(i);
178  }
179}
180
181void CFFL_ListBox::RestoreState(CPDFSDK_PageView* pPageView) {
182  CPWL_ListBox* pListBox =
183      static_cast<CPWL_ListBox*>(GetPDFWindow(pPageView, false));
184  if (!pListBox)
185    return;
186
187  for (const auto& item : m_State)
188    pListBox->Select(item);
189}
190
191CPWL_Wnd* CFFL_ListBox::ResetPDFWindow(CPDFSDK_PageView* pPageView,
192                                       bool bRestoreValue) {
193  if (bRestoreValue)
194    SaveState(pPageView);
195
196  DestroyPDFWindow(pPageView);
197
198  CPWL_Wnd* pRet = nullptr;
199
200  if (bRestoreValue) {
201    RestoreState(pPageView);
202    pRet = GetPDFWindow(pPageView, false);
203  } else {
204    pRet = GetPDFWindow(pPageView, true);
205  }
206
207  m_pWidget->UpdateField();
208
209  return pRet;
210}
211