Home | History | Annotate | Download | only in fxfa
      1 // Copyright 2017 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 "xfa/fxfa/cxfa_fflistbox.h"
      8 
      9 #include <algorithm>
     10 #include <utility>
     11 #include <vector>
     12 
     13 #include "xfa/fwl/cfwl_listbox.h"
     14 #include "xfa/fwl/cfwl_notedriver.h"
     15 #include "xfa/fwl/cfwl_widget.h"
     16 #include "xfa/fxfa/cxfa_eventparam.h"
     17 #include "xfa/fxfa/parser/cxfa_para.h"
     18 
     19 namespace {
     20 
     21 CFWL_ListBox* ToListBox(CFWL_Widget* widget) {
     22   return static_cast<CFWL_ListBox*>(widget);
     23 }
     24 
     25 }  // namespace
     26 
     27 CXFA_FFListBox::CXFA_FFListBox(CXFA_Node* pNode)
     28     : CXFA_FFField(pNode), m_pOldDelegate(nullptr) {}
     29 
     30 CXFA_FFListBox::~CXFA_FFListBox() {
     31   if (!m_pNormalWidget)
     32     return;
     33 
     34   CFWL_NoteDriver* pNoteDriver =
     35       m_pNormalWidget->GetOwnerApp()->GetNoteDriver();
     36   pNoteDriver->UnregisterEventTarget(m_pNormalWidget.get());
     37 }
     38 
     39 bool CXFA_FFListBox::LoadWidget() {
     40   auto pNew = pdfium::MakeUnique<CFWL_ListBox>(
     41       GetFWLApp(), pdfium::MakeUnique<CFWL_WidgetProperties>(), nullptr);
     42   CFWL_ListBox* pListBox = pNew.get();
     43   pListBox->ModifyStyles(FWL_WGTSTYLE_VScroll | FWL_WGTSTYLE_NoBackground,
     44                          0xFFFFFFFF);
     45   m_pNormalWidget = std::move(pNew);
     46   m_pNormalWidget->SetLayoutItem(this);
     47 
     48   CFWL_NoteDriver* pNoteDriver =
     49       m_pNormalWidget->GetOwnerApp()->GetNoteDriver();
     50   pNoteDriver->RegisterEventTarget(m_pNormalWidget.get(),
     51                                    m_pNormalWidget.get());
     52   m_pOldDelegate = m_pNormalWidget->GetDelegate();
     53   m_pNormalWidget->SetDelegate(this);
     54   m_pNormalWidget->LockUpdate();
     55 
     56   for (const auto& label : m_pNode->GetWidgetAcc()->GetChoiceListItems(false))
     57     pListBox->AddString(label.AsStringView());
     58 
     59   uint32_t dwExtendedStyle = FWL_STYLEEXT_LTB_ShowScrollBarFocus;
     60   if (m_pNode->GetWidgetAcc()->IsChoiceListMultiSelect())
     61     dwExtendedStyle |= FWL_STYLEEXT_LTB_MultiSelection;
     62 
     63   dwExtendedStyle |= GetAlignment();
     64   m_pNormalWidget->ModifyStylesEx(dwExtendedStyle, 0xFFFFFFFF);
     65   for (int32_t selected : m_pNode->GetWidgetAcc()->GetSelectedItems())
     66     pListBox->SetSelItem(pListBox->GetItem(nullptr, selected), true);
     67 
     68   m_pNormalWidget->UnlockUpdate();
     69   return CXFA_FFField::LoadWidget();
     70 }
     71 
     72 bool CXFA_FFListBox::OnKillFocus(CXFA_FFWidget* pNewFocus) {
     73   if (!ProcessCommittedData())
     74     UpdateFWLData();
     75 
     76   CXFA_FFField::OnKillFocus(pNewFocus);
     77   return true;
     78 }
     79 
     80 bool CXFA_FFListBox::CommitData() {
     81   auto* pListBox = ToListBox(m_pNormalWidget.get());
     82   std::vector<int32_t> iSelArray;
     83   int32_t iSels = pListBox->CountSelItems();
     84   for (int32_t i = 0; i < iSels; ++i)
     85     iSelArray.push_back(pListBox->GetSelIndex(i));
     86 
     87   m_pNode->GetWidgetAcc()->SetSelectedItems(iSelArray, true, false, true);
     88   return true;
     89 }
     90 
     91 bool CXFA_FFListBox::IsDataChanged() {
     92   std::vector<int32_t> iSelArray = m_pNode->GetWidgetAcc()->GetSelectedItems();
     93   int32_t iOldSels = pdfium::CollectionSize<int32_t>(iSelArray);
     94   auto* pListBox = ToListBox(m_pNormalWidget.get());
     95   int32_t iSels = pListBox->CountSelItems();
     96   if (iOldSels != iSels)
     97     return true;
     98 
     99   for (int32_t i = 0; i < iSels; ++i) {
    100     CFWL_ListItem* hlistItem = pListBox->GetItem(nullptr, iSelArray[i]);
    101     if (!(hlistItem->GetStates() & FWL_ITEMSTATE_LTB_Selected))
    102       return true;
    103   }
    104   return false;
    105 }
    106 
    107 uint32_t CXFA_FFListBox::GetAlignment() {
    108   CXFA_Para* para = m_pNode->GetParaIfExists();
    109   if (!para)
    110     return 0;
    111 
    112   uint32_t dwExtendedStyle = 0;
    113   switch (para->GetHorizontalAlign()) {
    114     case XFA_AttributeEnum::Center:
    115       dwExtendedStyle |= FWL_STYLEEXT_LTB_CenterAlign;
    116       break;
    117     case XFA_AttributeEnum::Justify:
    118       break;
    119     case XFA_AttributeEnum::JustifyAll:
    120       break;
    121     case XFA_AttributeEnum::Radix:
    122       break;
    123     case XFA_AttributeEnum::Right:
    124       dwExtendedStyle |= FWL_STYLEEXT_LTB_RightAlign;
    125       break;
    126     default:
    127       dwExtendedStyle |= FWL_STYLEEXT_LTB_LeftAlign;
    128       break;
    129   }
    130   return dwExtendedStyle;
    131 }
    132 
    133 bool CXFA_FFListBox::UpdateFWLData() {
    134   if (!m_pNormalWidget)
    135     return false;
    136 
    137   auto* pListBox = ToListBox(m_pNormalWidget.get());
    138   std::vector<int32_t> iSelArray = m_pNode->GetWidgetAcc()->GetSelectedItems();
    139   std::vector<CFWL_ListItem*> selItemArray(iSelArray.size());
    140   std::transform(iSelArray.begin(), iSelArray.end(), selItemArray.begin(),
    141                  [pListBox](int32_t val) { return pListBox->GetSelItem(val); });
    142 
    143   pListBox->SetSelItem(pListBox->GetSelItem(-1), false);
    144   for (CFWL_ListItem* pItem : selItemArray)
    145     pListBox->SetSelItem(pItem, true);
    146 
    147   m_pNormalWidget->Update();
    148   return true;
    149 }
    150 
    151 void CXFA_FFListBox::OnSelectChanged(CFWL_Widget* pWidget) {
    152   CXFA_EventParam eParam;
    153   eParam.m_eType = XFA_EVENT_Change;
    154   eParam.m_pTarget = m_pNode->GetWidgetAcc();
    155   eParam.m_wsPrevText = m_pNode->GetWidgetAcc()->GetValue(XFA_VALUEPICTURE_Raw);
    156 
    157   auto* pListBox = ToListBox(m_pNormalWidget.get());
    158   int32_t iSels = pListBox->CountSelItems();
    159   if (iSels > 0) {
    160     CFWL_ListItem* item = pListBox->GetSelItem(0);
    161     eParam.m_wsNewText = item ? item->GetText() : L"";
    162   }
    163   m_pNode->ProcessEvent(GetDocView(), XFA_AttributeEnum::Change, &eParam);
    164 }
    165 
    166 void CXFA_FFListBox::SetItemState(int32_t nIndex, bool bSelected) {
    167   auto* pListBox = ToListBox(m_pNormalWidget.get());
    168   pListBox->SetSelItem(pListBox->GetSelItem(nIndex), bSelected);
    169   m_pNormalWidget->Update();
    170   AddInvalidateRect();
    171 }
    172 
    173 void CXFA_FFListBox::InsertItem(const WideStringView& wsLabel, int32_t nIndex) {
    174   WideString wsTemp(wsLabel);
    175   ToListBox(m_pNormalWidget.get())->AddString(wsTemp.AsStringView());
    176   m_pNormalWidget->Update();
    177   AddInvalidateRect();
    178 }
    179 
    180 void CXFA_FFListBox::DeleteItem(int32_t nIndex) {
    181   auto* pListBox = ToListBox(m_pNormalWidget.get());
    182   if (nIndex < 0)
    183     pListBox->DeleteAll();
    184   else
    185     pListBox->DeleteString(pListBox->GetItem(nullptr, nIndex));
    186 
    187   pListBox->Update();
    188   AddInvalidateRect();
    189 }
    190 
    191 void CXFA_FFListBox::OnProcessMessage(CFWL_Message* pMessage) {
    192   m_pOldDelegate->OnProcessMessage(pMessage);
    193 }
    194 
    195 void CXFA_FFListBox::OnProcessEvent(CFWL_Event* pEvent) {
    196   CXFA_FFField::OnProcessEvent(pEvent);
    197   switch (pEvent->GetType()) {
    198     case CFWL_Event::Type::SelectChanged:
    199       OnSelectChanged(m_pNormalWidget.get());
    200       break;
    201     default:
    202       break;
    203   }
    204   m_pOldDelegate->OnProcessEvent(pEvent);
    205 }
    206 
    207 void CXFA_FFListBox::OnDrawWidget(CXFA_Graphics* pGraphics,
    208                                   const CFX_Matrix& matrix) {
    209   m_pOldDelegate->OnDrawWidget(pGraphics, matrix);
    210 }
    211 
    212 FormFieldType CXFA_FFListBox::GetFormFieldType() {
    213   return FormFieldType::kXFA_ListBox;
    214 }
    215