• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2017 The PDFium Authors
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 "core/fxcrt/stl_util.h"
14 #include "third_party/base/check.h"
15 #include "v8/include/cppgc/visitor.h"
16 #include "xfa/fwl/cfwl_listbox.h"
17 #include "xfa/fwl/cfwl_notedriver.h"
18 #include "xfa/fwl/cfwl_widget.h"
19 #include "xfa/fxfa/cxfa_eventparam.h"
20 #include "xfa/fxfa/parser/cxfa_para.h"
21 
22 namespace {
23 
ToListBox(CFWL_Widget * widget)24 CFWL_ListBox* ToListBox(CFWL_Widget* widget) {
25   return static_cast<CFWL_ListBox*>(widget);
26 }
27 
28 }  // namespace
29 
CXFA_FFListBox(CXFA_Node * pNode)30 CXFA_FFListBox::CXFA_FFListBox(CXFA_Node* pNode) : CXFA_FFDropDown(pNode) {}
31 
32 CXFA_FFListBox::~CXFA_FFListBox() = default;
33 
PreFinalize()34 void CXFA_FFListBox::PreFinalize() {
35   if (GetNormalWidget()) {
36     CFWL_NoteDriver* pNoteDriver =
37         GetNormalWidget()->GetFWLApp()->GetNoteDriver();
38     pNoteDriver->UnregisterEventTarget(GetNormalWidget());
39   }
40 }
41 
Trace(cppgc::Visitor * visitor) const42 void CXFA_FFListBox::Trace(cppgc::Visitor* visitor) const {
43   CXFA_FFDropDown::Trace(visitor);
44   visitor->Trace(m_pOldDelegate);
45 }
46 
LoadWidget()47 bool CXFA_FFListBox::LoadWidget() {
48   DCHECK(!IsLoaded());
49 
50   CFWL_ListBox* pListBox = cppgc::MakeGarbageCollected<CFWL_ListBox>(
51       GetFWLApp()->GetHeap()->GetAllocationHandle(), GetFWLApp(),
52       CFWL_Widget::Properties(), nullptr);
53   pListBox->ModifyStyles(FWL_STYLE_WGT_VScroll | FWL_STYLE_WGT_NoBackground,
54                          0xFFFFFFFF);
55   SetNormalWidget(pListBox);
56   pListBox->SetAdapterIface(this);
57 
58   CFWL_NoteDriver* pNoteDriver = pListBox->GetFWLApp()->GetNoteDriver();
59   pNoteDriver->RegisterEventTarget(pListBox, pListBox);
60   m_pOldDelegate = pListBox->GetDelegate();
61   pListBox->SetDelegate(this);
62 
63   {
64     CFWL_Widget::ScopedUpdateLock update_lock(pListBox);
65     std::vector<WideString> displayables = m_pNode->GetChoiceListItems(false);
66     std::vector<WideString> settables = m_pNode->GetChoiceListItems(true);
67     if (displayables.size() > settables.size())
68       displayables.resize(settables.size());
69 
70     for (const auto& label : displayables)
71       pListBox->AddString(label);
72 
73     uint32_t dwExtendedStyle = FWL_STYLEEXT_LTB_ShowScrollBarFocus;
74     if (m_pNode->IsChoiceListMultiSelect())
75       dwExtendedStyle |= FWL_STYLEEXT_LTB_MultiSelection;
76 
77     dwExtendedStyle |= GetAlignment();
78     pListBox->ModifyStyleExts(dwExtendedStyle, 0xFFFFFFFF);
79     for (int32_t selected : m_pNode->GetSelectedItems())
80       pListBox->SetSelItem(pListBox->GetItem(nullptr, selected), true);
81   }
82 
83   return CXFA_FFField::LoadWidget();
84 }
85 
OnKillFocus(CXFA_FFWidget * pNewFocus)86 bool CXFA_FFListBox::OnKillFocus(CXFA_FFWidget* pNewFocus) {
87   if (!ProcessCommittedData())
88     UpdateFWLData();
89 
90   return pNewFocus && CXFA_FFField::OnKillFocus(pNewFocus);
91 }
92 
CommitData()93 bool CXFA_FFListBox::CommitData() {
94   auto* pListBox = ToListBox(GetNormalWidget());
95   std::vector<int32_t> iSelArray;
96   int32_t iSels = pListBox->CountSelItems();
97   for (int32_t i = 0; i < iSels; ++i)
98     iSelArray.push_back(pListBox->GetSelIndex(i));
99 
100   m_pNode->SetSelectedItems(iSelArray, true, false, true);
101   return true;
102 }
103 
IsDataChanged()104 bool CXFA_FFListBox::IsDataChanged() {
105   std::vector<int32_t> iSelArray = m_pNode->GetSelectedItems();
106   int32_t iOldSels = fxcrt::CollectionSize<int32_t>(iSelArray);
107   auto* pListBox = ToListBox(GetNormalWidget());
108   int32_t iSels = pListBox->CountSelItems();
109   if (iOldSels != iSels)
110     return true;
111 
112   for (int32_t i = 0; i < iSels; ++i) {
113     CFWL_ListBox::Item* hlistItem = pListBox->GetItem(nullptr, iSelArray[i]);
114     if (!hlistItem->IsSelected())
115       return true;
116   }
117   return false;
118 }
119 
GetAlignment()120 uint32_t CXFA_FFListBox::GetAlignment() {
121   CXFA_Para* para = m_pNode->GetParaIfExists();
122   if (!para)
123     return 0;
124 
125   uint32_t dwExtendedStyle = 0;
126   switch (para->GetHorizontalAlign()) {
127     case XFA_AttributeValue::Center:
128       dwExtendedStyle |= FWL_STYLEEXT_LTB_CenterAlign;
129       break;
130     case XFA_AttributeValue::Justify:
131       break;
132     case XFA_AttributeValue::JustifyAll:
133       break;
134     case XFA_AttributeValue::Radix:
135       break;
136     case XFA_AttributeValue::Right:
137       dwExtendedStyle |= FWL_STYLEEXT_LTB_RightAlign;
138       break;
139     default:
140       dwExtendedStyle |= FWL_STYLEEXT_LTB_LeftAlign;
141       break;
142   }
143   return dwExtendedStyle;
144 }
145 
UpdateFWLData()146 bool CXFA_FFListBox::UpdateFWLData() {
147   auto* pListBox = ToListBox(GetNormalWidget());
148   if (!pListBox)
149     return false;
150 
151   std::vector<int32_t> iSelArray = m_pNode->GetSelectedItems();
152   std::vector<CFWL_ListBox::Item*> selItemArray(iSelArray.size());
153   std::transform(iSelArray.begin(), iSelArray.end(), selItemArray.begin(),
154                  [pListBox](int32_t val) { return pListBox->GetSelItem(val); });
155 
156   pListBox->SetSelItem(pListBox->GetSelItem(-1), false);
157   for (CFWL_ListBox::Item* pItem : selItemArray)
158     pListBox->SetSelItem(pItem, true);
159 
160   GetNormalWidget()->Update();
161   return true;
162 }
163 
OnSelectChanged(CFWL_Widget * pWidget)164 void CXFA_FFListBox::OnSelectChanged(CFWL_Widget* pWidget) {
165   CXFA_EventParam eParam;
166   eParam.m_eType = XFA_EVENT_Change;
167   eParam.m_wsPrevText = m_pNode->GetValue(XFA_ValuePicture::kRaw);
168   m_pNode->ProcessEvent(GetDocView(), XFA_AttributeValue::Change, &eParam);
169 }
170 
SetItemState(int32_t nIndex,bool bSelected)171 void CXFA_FFListBox::SetItemState(int32_t nIndex, bool bSelected) {
172   auto* pListBox = ToListBox(GetNormalWidget());
173   pListBox->SetSelItem(pListBox->GetSelItem(nIndex), bSelected);
174   GetNormalWidget()->Update();
175   InvalidateRect();
176 }
177 
InsertItem(const WideString & wsLabel,int32_t nIndex)178 void CXFA_FFListBox::InsertItem(const WideString& wsLabel, int32_t nIndex) {
179   ToListBox(GetNormalWidget())->AddString(wsLabel);
180   GetNormalWidget()->Update();
181   InvalidateRect();
182 }
183 
DeleteItem(int32_t nIndex)184 void CXFA_FFListBox::DeleteItem(int32_t nIndex) {
185   auto* pListBox = ToListBox(GetNormalWidget());
186   if (nIndex < 0)
187     pListBox->DeleteAll();
188   else
189     pListBox->DeleteString(pListBox->GetItem(nullptr, nIndex));
190 
191   pListBox->Update();
192   InvalidateRect();
193 }
194 
OnProcessMessage(CFWL_Message * pMessage)195 void CXFA_FFListBox::OnProcessMessage(CFWL_Message* pMessage) {
196   m_pOldDelegate->OnProcessMessage(pMessage);
197 }
198 
OnProcessEvent(CFWL_Event * pEvent)199 void CXFA_FFListBox::OnProcessEvent(CFWL_Event* pEvent) {
200   CXFA_FFField::OnProcessEvent(pEvent);
201   switch (pEvent->GetType()) {
202     case CFWL_Event::Type::SelectChanged:
203       OnSelectChanged(GetNormalWidget());
204       break;
205     default:
206       break;
207   }
208   m_pOldDelegate->OnProcessEvent(pEvent);
209 }
210 
OnDrawWidget(CFGAS_GEGraphics * pGraphics,const CFX_Matrix & matrix)211 void CXFA_FFListBox::OnDrawWidget(CFGAS_GEGraphics* pGraphics,
212                                   const CFX_Matrix& matrix) {
213   m_pOldDelegate->OnDrawWidget(pGraphics, matrix);
214 }
215 
GetFormFieldType()216 FormFieldType CXFA_FFListBox::GetFormFieldType() {
217   return FormFieldType::kXFA_ListBox;
218 }
219