Home | History | Annotate | Download | only in formfiller
      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