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