• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "xfa/fxfa/cxfa_ffcombobox.h"
8 
9 #include <utility>
10 #include <vector>
11 
12 #include "xfa/fwl/cfwl_combobox.h"
13 #include "xfa/fwl/cfwl_eventselectchanged.h"
14 #include "xfa/fwl/cfwl_notedriver.h"
15 #include "xfa/fxfa/cxfa_eventparam.h"
16 #include "xfa/fxfa/cxfa_ffdocview.h"
17 #include "xfa/fxfa/parser/cxfa_para.h"
18 
19 namespace {
20 
ToComboBox(CFWL_Widget * widget)21 CFWL_ComboBox* ToComboBox(CFWL_Widget* widget) {
22   return static_cast<CFWL_ComboBox*>(widget);
23 }
24 
25 }  // namespace
26 
CXFA_FFComboBox(CXFA_Node * pNode)27 CXFA_FFComboBox::CXFA_FFComboBox(CXFA_Node* pNode)
28     : CXFA_FFField(pNode), m_pOldDelegate(nullptr) {}
29 
~CXFA_FFComboBox()30 CXFA_FFComboBox::~CXFA_FFComboBox() {}
31 
GetBBox(uint32_t dwStatus,bool bDrawFocus)32 CFX_RectF CXFA_FFComboBox::GetBBox(uint32_t dwStatus, bool bDrawFocus) {
33   return bDrawFocus ? CFX_RectF() : CXFA_FFWidget::GetBBox(dwStatus);
34 }
35 
PtInActiveRect(const CFX_PointF & point)36 bool CXFA_FFComboBox::PtInActiveRect(const CFX_PointF& point) {
37   auto* pComboBox = ToComboBox(m_pNormalWidget.get());
38   return pComboBox && pComboBox->GetBBox().Contains(point);
39 }
40 
LoadWidget()41 bool CXFA_FFComboBox::LoadWidget() {
42   auto pNew = pdfium::MakeUnique<CFWL_ComboBox>(GetFWLApp());
43   CFWL_ComboBox* pComboBox = pNew.get();
44   m_pNormalWidget = std::move(pNew);
45   m_pNormalWidget->SetLayoutItem(this);
46 
47   CFWL_NoteDriver* pNoteDriver =
48       m_pNormalWidget->GetOwnerApp()->GetNoteDriver();
49   pNoteDriver->RegisterEventTarget(m_pNormalWidget.get(),
50                                    m_pNormalWidget.get());
51   m_pOldDelegate = m_pNormalWidget->GetDelegate();
52   m_pNormalWidget->SetDelegate(this);
53   m_pNormalWidget->LockUpdate();
54 
55   for (const auto& label : m_pNode->GetWidgetAcc()->GetChoiceListItems(false))
56     pComboBox->AddString(label.AsStringView());
57 
58   std::vector<int32_t> iSelArray = m_pNode->GetWidgetAcc()->GetSelectedItems();
59   if (iSelArray.empty()) {
60     pComboBox->SetEditText(
61         m_pNode->GetWidgetAcc()->GetValue(XFA_VALUEPICTURE_Raw));
62   } else {
63     pComboBox->SetCurSel(iSelArray.front());
64   }
65 
66   UpdateWidgetProperty();
67   m_pNormalWidget->UnlockUpdate();
68   return CXFA_FFField::LoadWidget();
69 }
70 
UpdateWidgetProperty()71 void CXFA_FFComboBox::UpdateWidgetProperty() {
72   auto* pComboBox = ToComboBox(m_pNormalWidget.get());
73   if (!pComboBox)
74     return;
75 
76   uint32_t dwExtendedStyle = 0;
77   uint32_t dwEditStyles = FWL_STYLEEXT_EDT_ReadOnly;
78   dwExtendedStyle |= UpdateUIProperty();
79   if (m_pNode->GetWidgetAcc()->IsChoiceListAllowTextEntry()) {
80     dwEditStyles &= ~FWL_STYLEEXT_EDT_ReadOnly;
81     dwExtendedStyle |= FWL_STYLEEXT_CMB_DropDown;
82   }
83   if (!m_pNode->IsOpenAccess() || !GetDoc()->GetXFADoc()->IsInteractive()) {
84     dwEditStyles |= FWL_STYLEEXT_EDT_ReadOnly;
85     dwExtendedStyle |= FWL_STYLEEXT_CMB_ReadOnly;
86   }
87   dwExtendedStyle |= GetAlignment();
88   m_pNormalWidget->ModifyStylesEx(dwExtendedStyle, 0xFFFFFFFF);
89 
90   if (!m_pNode->GetWidgetAcc()->IsHorizontalScrollPolicyOff())
91     dwEditStyles |= FWL_STYLEEXT_EDT_AutoHScroll;
92 
93   pComboBox->EditModifyStylesEx(dwEditStyles, 0xFFFFFFFF);
94 }
95 
OnRButtonUp(uint32_t dwFlags,const CFX_PointF & point)96 bool CXFA_FFComboBox::OnRButtonUp(uint32_t dwFlags, const CFX_PointF& point) {
97   if (!CXFA_FFField::OnRButtonUp(dwFlags, point))
98     return false;
99 
100   GetDoc()->GetDocEnvironment()->PopupMenu(this, point);
101   return true;
102 }
103 
OnKillFocus(CXFA_FFWidget * pNewWidget)104 bool CXFA_FFComboBox::OnKillFocus(CXFA_FFWidget* pNewWidget) {
105   if (!ProcessCommittedData())
106     UpdateFWLData();
107 
108   CXFA_FFField::OnKillFocus(pNewWidget);
109   return true;
110 }
111 
OpenDropDownList()112 void CXFA_FFComboBox::OpenDropDownList() {
113   ToComboBox(m_pNormalWidget.get())->OpenDropDownList(true);
114 }
115 
CommitData()116 bool CXFA_FFComboBox::CommitData() {
117   return m_pNode->GetWidgetAcc()->SetValue(XFA_VALUEPICTURE_Raw, m_wsNewValue);
118 }
119 
IsDataChanged()120 bool CXFA_FFComboBox::IsDataChanged() {
121   auto* pFWLcombobox = ToComboBox(m_pNormalWidget.get());
122   WideString wsText = pFWLcombobox->GetEditText();
123   int32_t iCursel = pFWLcombobox->GetCurSel();
124   if (iCursel >= 0) {
125     WideString wsSel = pFWLcombobox->GetTextByIndex(iCursel);
126     if (wsSel == wsText)
127       wsText = m_pNode->GetWidgetAcc()
128                    ->GetChoiceListItem(iCursel, true)
129                    .value_or(L"");
130   }
131   if (m_pNode->GetWidgetAcc()->GetValue(XFA_VALUEPICTURE_Raw) == wsText)
132     return false;
133 
134   m_wsNewValue = wsText;
135   return true;
136 }
137 
FWLEventSelChange(CXFA_EventParam * pParam)138 void CXFA_FFComboBox::FWLEventSelChange(CXFA_EventParam* pParam) {
139   pParam->m_eType = XFA_EVENT_Change;
140   pParam->m_pTarget = m_pNode->GetWidgetAcc();
141   pParam->m_wsNewText = ToComboBox(m_pNormalWidget.get())->GetEditText();
142   m_pNode->ProcessEvent(GetDocView(), XFA_AttributeEnum::Change, pParam);
143 }
144 
GetAlignment()145 uint32_t CXFA_FFComboBox::GetAlignment() {
146   CXFA_Para* para = m_pNode->GetParaIfExists();
147   if (!para)
148     return 0;
149 
150   uint32_t dwExtendedStyle = 0;
151   switch (para->GetHorizontalAlign()) {
152     case XFA_AttributeEnum::Center:
153       dwExtendedStyle |=
154           FWL_STYLEEXT_CMB_EditHCenter | FWL_STYLEEXT_CMB_ListItemCenterAlign;
155       break;
156     case XFA_AttributeEnum::Justify:
157       dwExtendedStyle |= FWL_STYLEEXT_CMB_EditJustified;
158       break;
159     case XFA_AttributeEnum::JustifyAll:
160       break;
161     case XFA_AttributeEnum::Radix:
162       break;
163     case XFA_AttributeEnum::Right:
164       break;
165     default:
166       dwExtendedStyle |=
167           FWL_STYLEEXT_CMB_EditHNear | FWL_STYLEEXT_CMB_ListItemLeftAlign;
168       break;
169   }
170 
171   switch (para->GetVerticalAlign()) {
172     case XFA_AttributeEnum::Middle:
173       dwExtendedStyle |= FWL_STYLEEXT_CMB_EditVCenter;
174       break;
175     case XFA_AttributeEnum::Bottom:
176       dwExtendedStyle |= FWL_STYLEEXT_CMB_EditVFar;
177       break;
178     default:
179       dwExtendedStyle |= FWL_STYLEEXT_CMB_EditVNear;
180       break;
181   }
182   return dwExtendedStyle;
183 }
184 
UpdateFWLData()185 bool CXFA_FFComboBox::UpdateFWLData() {
186   auto* pComboBox = ToComboBox(m_pNormalWidget.get());
187   if (!pComboBox)
188     return false;
189 
190   std::vector<int32_t> iSelArray = m_pNode->GetWidgetAcc()->GetSelectedItems();
191   if (!iSelArray.empty()) {
192     pComboBox->SetCurSel(iSelArray.front());
193   } else {
194     pComboBox->SetCurSel(-1);
195     pComboBox->SetEditText(
196         m_pNode->GetWidgetAcc()->GetValue(XFA_VALUEPICTURE_Raw));
197   }
198   pComboBox->Update();
199   return true;
200 }
201 
CanUndo()202 bool CXFA_FFComboBox::CanUndo() {
203   return m_pNode->GetWidgetAcc()->IsChoiceListAllowTextEntry() &&
204          ToComboBox(m_pNormalWidget.get())->EditCanUndo();
205 }
206 
CanRedo()207 bool CXFA_FFComboBox::CanRedo() {
208   return m_pNode->GetWidgetAcc()->IsChoiceListAllowTextEntry() &&
209          ToComboBox(m_pNormalWidget.get())->EditCanRedo();
210 }
211 
Undo()212 bool CXFA_FFComboBox::Undo() {
213   return m_pNode->GetWidgetAcc()->IsChoiceListAllowTextEntry() &&
214          ToComboBox(m_pNormalWidget.get())->EditUndo();
215 }
216 
Redo()217 bool CXFA_FFComboBox::Redo() {
218   return m_pNode->GetWidgetAcc()->IsChoiceListAllowTextEntry() &&
219          ToComboBox(m_pNormalWidget.get())->EditRedo();
220 }
221 
CanCopy()222 bool CXFA_FFComboBox::CanCopy() {
223   return ToComboBox(m_pNormalWidget.get())->EditCanCopy();
224 }
225 
CanCut()226 bool CXFA_FFComboBox::CanCut() {
227   return m_pNode->IsOpenAccess() &&
228          m_pNode->GetWidgetAcc()->IsChoiceListAllowTextEntry() &&
229          ToComboBox(m_pNormalWidget.get())->EditCanCut();
230 }
231 
CanPaste()232 bool CXFA_FFComboBox::CanPaste() {
233   return m_pNode->GetWidgetAcc()->IsChoiceListAllowTextEntry() &&
234          m_pNode->IsOpenAccess();
235 }
236 
CanSelectAll()237 bool CXFA_FFComboBox::CanSelectAll() {
238   return ToComboBox(m_pNormalWidget.get())->EditCanSelectAll();
239 }
240 
Copy()241 Optional<WideString> CXFA_FFComboBox::Copy() {
242   return ToComboBox(m_pNormalWidget.get())->EditCopy();
243 }
244 
Cut()245 Optional<WideString> CXFA_FFComboBox::Cut() {
246   if (!m_pNode->GetWidgetAcc()->IsChoiceListAllowTextEntry())
247     return {};
248 
249   return ToComboBox(m_pNormalWidget.get())->EditCut();
250 }
251 
Paste(const WideString & wsPaste)252 bool CXFA_FFComboBox::Paste(const WideString& wsPaste) {
253   return m_pNode->GetWidgetAcc()->IsChoiceListAllowTextEntry() &&
254          ToComboBox(m_pNormalWidget.get())->EditPaste(wsPaste);
255 }
256 
SelectAll()257 void CXFA_FFComboBox::SelectAll() {
258   ToComboBox(m_pNormalWidget.get())->EditSelectAll();
259 }
260 
Delete()261 void CXFA_FFComboBox::Delete() {
262   ToComboBox(m_pNormalWidget.get())->EditDelete();
263 }
264 
DeSelect()265 void CXFA_FFComboBox::DeSelect() {
266   ToComboBox(m_pNormalWidget.get())->EditDeSelect();
267 }
268 
GetFormFieldType()269 FormFieldType CXFA_FFComboBox::GetFormFieldType() {
270   return FormFieldType::kXFA_ComboBox;
271 }
272 
SetItemState(int32_t nIndex,bool bSelected)273 void CXFA_FFComboBox::SetItemState(int32_t nIndex, bool bSelected) {
274   ToComboBox(m_pNormalWidget.get())->SetCurSel(bSelected ? nIndex : -1);
275   m_pNormalWidget->Update();
276   AddInvalidateRect();
277 }
278 
InsertItem(const WideStringView & wsLabel,int32_t nIndex)279 void CXFA_FFComboBox::InsertItem(const WideStringView& wsLabel,
280                                  int32_t nIndex) {
281   ToComboBox(m_pNormalWidget.get())->AddString(wsLabel);
282   m_pNormalWidget->Update();
283   AddInvalidateRect();
284 }
285 
DeleteItem(int32_t nIndex)286 void CXFA_FFComboBox::DeleteItem(int32_t nIndex) {
287   if (nIndex < 0)
288     ToComboBox(m_pNormalWidget.get())->RemoveAll();
289   else
290     ToComboBox(m_pNormalWidget.get())->RemoveAt(nIndex);
291 
292   m_pNormalWidget->Update();
293   AddInvalidateRect();
294 }
295 
OnTextChanged(CFWL_Widget * pWidget,const WideString & wsChanged)296 void CXFA_FFComboBox::OnTextChanged(CFWL_Widget* pWidget,
297                                     const WideString& wsChanged) {
298   CXFA_EventParam eParam;
299   eParam.m_wsPrevText = m_pNode->GetWidgetAcc()->GetValue(XFA_VALUEPICTURE_Raw);
300   eParam.m_wsChange = wsChanged;
301   FWLEventSelChange(&eParam);
302 }
303 
OnSelectChanged(CFWL_Widget * pWidget,bool bLButtonUp)304 void CXFA_FFComboBox::OnSelectChanged(CFWL_Widget* pWidget, bool bLButtonUp) {
305   CXFA_EventParam eParam;
306   eParam.m_wsPrevText = m_pNode->GetWidgetAcc()->GetValue(XFA_VALUEPICTURE_Raw);
307   FWLEventSelChange(&eParam);
308   if (m_pNode->GetWidgetAcc()->IsChoiceListCommitOnSelect() && bLButtonUp)
309     m_pDocView->SetFocusWidgetAcc(nullptr);
310 }
311 
OnPreOpen(CFWL_Widget * pWidget)312 void CXFA_FFComboBox::OnPreOpen(CFWL_Widget* pWidget) {
313   CXFA_EventParam eParam;
314   eParam.m_eType = XFA_EVENT_PreOpen;
315   eParam.m_pTarget = m_pNode->GetWidgetAcc();
316   m_pNode->ProcessEvent(GetDocView(), XFA_AttributeEnum::PreOpen, &eParam);
317 }
318 
OnPostOpen(CFWL_Widget * pWidget)319 void CXFA_FFComboBox::OnPostOpen(CFWL_Widget* pWidget) {
320   CXFA_EventParam eParam;
321   eParam.m_eType = XFA_EVENT_PostOpen;
322   eParam.m_pTarget = m_pNode->GetWidgetAcc();
323   m_pNode->ProcessEvent(GetDocView(), XFA_AttributeEnum::PostOpen, &eParam);
324 }
325 
OnProcessMessage(CFWL_Message * pMessage)326 void CXFA_FFComboBox::OnProcessMessage(CFWL_Message* pMessage) {
327   m_pOldDelegate->OnProcessMessage(pMessage);
328 }
329 
OnProcessEvent(CFWL_Event * pEvent)330 void CXFA_FFComboBox::OnProcessEvent(CFWL_Event* pEvent) {
331   CXFA_FFField::OnProcessEvent(pEvent);
332   switch (pEvent->GetType()) {
333     case CFWL_Event::Type::SelectChanged: {
334       auto* postEvent = static_cast<CFWL_EventSelectChanged*>(pEvent);
335       OnSelectChanged(m_pNormalWidget.get(), postEvent->bLButtonUp);
336       break;
337     }
338     case CFWL_Event::Type::EditChanged: {
339       WideString wsChanged;
340       OnTextChanged(m_pNormalWidget.get(), wsChanged);
341       break;
342     }
343     case CFWL_Event::Type::PreDropDown: {
344       OnPreOpen(m_pNormalWidget.get());
345       break;
346     }
347     case CFWL_Event::Type::PostDropDown: {
348       OnPostOpen(m_pNormalWidget.get());
349       break;
350     }
351     default:
352       break;
353   }
354   m_pOldDelegate->OnProcessEvent(pEvent);
355 }
356 
OnDrawWidget(CXFA_Graphics * pGraphics,const CFX_Matrix & matrix)357 void CXFA_FFComboBox::OnDrawWidget(CXFA_Graphics* pGraphics,
358                                    const CFX_Matrix& matrix) {
359   m_pOldDelegate->OnDrawWidget(pGraphics, matrix);
360 }
361