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