• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
ToListBox(CFWL_Widget * widget)21 CFWL_ListBox* ToListBox(CFWL_Widget* widget) {
22   return static_cast<CFWL_ListBox*>(widget);
23 }
24 
25 }  // namespace
26 
CXFA_FFListBox(CXFA_Node * pNode)27 CXFA_FFListBox::CXFA_FFListBox(CXFA_Node* pNode)
28     : CXFA_FFField(pNode), m_pOldDelegate(nullptr) {}
29 
~CXFA_FFListBox()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 
LoadWidget()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 
OnKillFocus(CXFA_FFWidget * pNewFocus)72 bool CXFA_FFListBox::OnKillFocus(CXFA_FFWidget* pNewFocus) {
73   if (!ProcessCommittedData())
74     UpdateFWLData();
75 
76   CXFA_FFField::OnKillFocus(pNewFocus);
77   return true;
78 }
79 
CommitData()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 
IsDataChanged()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 
GetAlignment()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 
UpdateFWLData()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 
OnSelectChanged(CFWL_Widget * pWidget)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 
SetItemState(int32_t nIndex,bool bSelected)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 
InsertItem(const WideStringView & wsLabel,int32_t nIndex)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 
DeleteItem(int32_t nIndex)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 
OnProcessMessage(CFWL_Message * pMessage)191 void CXFA_FFListBox::OnProcessMessage(CFWL_Message* pMessage) {
192   m_pOldDelegate->OnProcessMessage(pMessage);
193 }
194 
OnProcessEvent(CFWL_Event * pEvent)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 
OnDrawWidget(CXFA_Graphics * pGraphics,const CFX_Matrix & matrix)207 void CXFA_FFListBox::OnDrawWidget(CXFA_Graphics* pGraphics,
208                                   const CFX_Matrix& matrix) {
209   m_pOldDelegate->OnDrawWidget(pGraphics, matrix);
210 }
211 
GetFormFieldType()212 FormFieldType CXFA_FFListBox::GetFormFieldType() {
213   return FormFieldType::kXFA_ListBox;
214 }
215