• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2014 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_ffnotify.h"
8 
9 #include <utility>
10 
11 #include "third_party/base/check.h"
12 #include "xfa/fxfa/cxfa_ffapp.h"
13 #include "xfa/fxfa/cxfa_ffarc.h"
14 #include "xfa/fxfa/cxfa_ffbarcode.h"
15 #include "xfa/fxfa/cxfa_ffcheckbutton.h"
16 #include "xfa/fxfa/cxfa_ffcombobox.h"
17 #include "xfa/fxfa/cxfa_ffdatetimeedit.h"
18 #include "xfa/fxfa/cxfa_ffdoc.h"
19 #include "xfa/fxfa/cxfa_ffdocview.h"
20 #include "xfa/fxfa/cxfa_ffexclgroup.h"
21 #include "xfa/fxfa/cxfa_fffield.h"
22 #include "xfa/fxfa/cxfa_ffimage.h"
23 #include "xfa/fxfa/cxfa_ffimageedit.h"
24 #include "xfa/fxfa/cxfa_ffline.h"
25 #include "xfa/fxfa/cxfa_fflistbox.h"
26 #include "xfa/fxfa/cxfa_ffnumericedit.h"
27 #include "xfa/fxfa/cxfa_ffpageview.h"
28 #include "xfa/fxfa/cxfa_ffpasswordedit.h"
29 #include "xfa/fxfa/cxfa_ffpushbutton.h"
30 #include "xfa/fxfa/cxfa_ffrectangle.h"
31 #include "xfa/fxfa/cxfa_ffsignature.h"
32 #include "xfa/fxfa/cxfa_fftext.h"
33 #include "xfa/fxfa/cxfa_ffwidget.h"
34 #include "xfa/fxfa/cxfa_ffwidgethandler.h"
35 #include "xfa/fxfa/cxfa_fwladapterwidgetmgr.h"
36 #include "xfa/fxfa/cxfa_textlayout.h"
37 #include "xfa/fxfa/cxfa_textprovider.h"
38 #include "xfa/fxfa/layout/cxfa_layoutprocessor.h"
39 #include "xfa/fxfa/parser/cxfa_barcode.h"
40 #include "xfa/fxfa/parser/cxfa_binditems.h"
41 #include "xfa/fxfa/parser/cxfa_button.h"
42 #include "xfa/fxfa/parser/cxfa_checkbutton.h"
43 #include "xfa/fxfa/parser/cxfa_node.h"
44 #include "xfa/fxfa/parser/cxfa_passwordedit.h"
45 
CXFA_FFNotify(CXFA_FFDoc * pDoc)46 CXFA_FFNotify::CXFA_FFNotify(CXFA_FFDoc* pDoc) : m_pDoc(pDoc) {}
47 
48 CXFA_FFNotify::~CXFA_FFNotify() = default;
49 
Trace(cppgc::Visitor * visitor) const50 void CXFA_FFNotify::Trace(cppgc::Visitor* visitor) const {
51   visitor->Trace(m_pDoc);
52 }
53 
OnPageViewEvent(CXFA_ViewLayoutItem * pSender,CXFA_FFDoc::PageViewEvent eEvent)54 void CXFA_FFNotify::OnPageViewEvent(CXFA_ViewLayoutItem* pSender,
55                                     CXFA_FFDoc::PageViewEvent eEvent) {
56   CXFA_FFDocView* pDocView = m_pDoc->GetDocView(pSender->GetLayout());
57   if (pDocView)
58     pDocView->OnPageViewEvent(pSender, eEvent);
59 }
60 
OnWidgetListItemAdded(CXFA_Node * pSender,const WideString & wsLabel,int32_t iIndex)61 void CXFA_FFNotify::OnWidgetListItemAdded(CXFA_Node* pSender,
62                                           const WideString& wsLabel,
63                                           int32_t iIndex) {
64   if (pSender->GetFFWidgetType() != XFA_FFWidgetType::kChoiceList)
65     return;
66 
67   CXFA_FFWidget* pWidget = m_pDoc->GetDocView()->GetWidgetForNode(pSender);
68   for (; pWidget; pWidget = pWidget->GetNextFFWidget()) {
69     if (pWidget->IsLoaded())
70       ToDropDown(ToField(pWidget))->InsertItem(wsLabel, iIndex);
71   }
72 }
73 
OnWidgetListItemRemoved(CXFA_Node * pSender,int32_t iIndex)74 void CXFA_FFNotify::OnWidgetListItemRemoved(CXFA_Node* pSender,
75                                             int32_t iIndex) {
76   if (pSender->GetFFWidgetType() != XFA_FFWidgetType::kChoiceList)
77     return;
78 
79   CXFA_FFWidget* pWidget = m_pDoc->GetDocView()->GetWidgetForNode(pSender);
80   for (; pWidget; pWidget = pWidget->GetNextFFWidget()) {
81     if (pWidget->IsLoaded())
82       ToDropDown(ToField(pWidget))->DeleteItem(iIndex);
83   }
84 }
85 
OnCreateViewLayoutItem(CXFA_Node * pNode)86 CXFA_FFPageView* CXFA_FFNotify::OnCreateViewLayoutItem(CXFA_Node* pNode) {
87   if (pNode->GetElementType() != XFA_Element::PageArea)
88     return nullptr;
89 
90   auto* pLayout = CXFA_LayoutProcessor::FromDocument(m_pDoc->GetXFADoc());
91   return cppgc::MakeGarbageCollected<CXFA_FFPageView>(
92       m_pDoc->GetHeap()->GetAllocationHandle(), m_pDoc->GetDocView(pLayout),
93       pNode);
94 }
95 
OnCreateContentLayoutItem(CXFA_Node * pNode)96 CXFA_FFWidget* CXFA_FFNotify::OnCreateContentLayoutItem(CXFA_Node* pNode) {
97   DCHECK(pNode->GetElementType() != XFA_Element::ContentArea);
98   DCHECK(pNode->GetElementType() != XFA_Element::PageArea);
99 
100   // We only need to create the widget for certain types of objects.
101   if (!pNode->HasCreatedUIWidget())
102     return nullptr;
103 
104   CXFA_FFWidget* pWidget = nullptr;
105   switch (pNode->GetFFWidgetType()) {
106     case XFA_FFWidgetType::kBarcode: {
107       auto* child = CXFA_Barcode::FromNode(pNode->GetUIChildNode());
108       if (!child)
109         return nullptr;
110 
111       pWidget = cppgc::MakeGarbageCollected<CXFA_FFBarcode>(
112           m_pDoc->GetHeap()->GetAllocationHandle(), pNode, child);
113       break;
114     }
115     case XFA_FFWidgetType::kButton: {
116       auto* child = CXFA_Button::FromNode(pNode->GetUIChildNode());
117       if (!child)
118         return nullptr;
119 
120       pWidget = cppgc::MakeGarbageCollected<CXFA_FFPushButton>(
121           m_pDoc->GetHeap()->GetAllocationHandle(), pNode, child);
122       break;
123     }
124     case XFA_FFWidgetType::kCheckButton: {
125       auto* child = CXFA_CheckButton::FromNode(pNode->GetUIChildNode());
126       if (!child)
127         return nullptr;
128 
129       pWidget = cppgc::MakeGarbageCollected<CXFA_FFCheckButton>(
130           m_pDoc->GetHeap()->GetAllocationHandle(), pNode, child);
131       break;
132     }
133     case XFA_FFWidgetType::kChoiceList: {
134       if (pNode->IsListBox()) {
135         pWidget = cppgc::MakeGarbageCollected<CXFA_FFListBox>(
136             m_pDoc->GetHeap()->GetAllocationHandle(), pNode);
137       } else {
138         pWidget = cppgc::MakeGarbageCollected<CXFA_FFComboBox>(
139             m_pDoc->GetHeap()->GetAllocationHandle(), pNode);
140       }
141       break;
142     }
143     case XFA_FFWidgetType::kDateTimeEdit:
144       pWidget = cppgc::MakeGarbageCollected<CXFA_FFDateTimeEdit>(
145           m_pDoc->GetHeap()->GetAllocationHandle(), pNode);
146       break;
147     case XFA_FFWidgetType::kImageEdit:
148       pWidget = cppgc::MakeGarbageCollected<CXFA_FFImageEdit>(
149           m_pDoc->GetHeap()->GetAllocationHandle(), pNode);
150       break;
151     case XFA_FFWidgetType::kNumericEdit:
152       pWidget = cppgc::MakeGarbageCollected<CXFA_FFNumericEdit>(
153           m_pDoc->GetHeap()->GetAllocationHandle(), pNode);
154       break;
155     case XFA_FFWidgetType::kPasswordEdit: {
156       auto* child = CXFA_PasswordEdit::FromNode(pNode->GetUIChildNode());
157       if (!child)
158         return nullptr;
159 
160       pWidget = cppgc::MakeGarbageCollected<CXFA_FFPasswordEdit>(
161           m_pDoc->GetHeap()->GetAllocationHandle(), pNode, child);
162       break;
163     }
164     case XFA_FFWidgetType::kSignature:
165       pWidget = cppgc::MakeGarbageCollected<CXFA_FFSignature>(
166           m_pDoc->GetHeap()->GetAllocationHandle(), pNode);
167       break;
168     case XFA_FFWidgetType::kTextEdit:
169       pWidget = cppgc::MakeGarbageCollected<CXFA_FFTextEdit>(
170           m_pDoc->GetHeap()->GetAllocationHandle(), pNode);
171       break;
172     case XFA_FFWidgetType::kArc:
173       pWidget = cppgc::MakeGarbageCollected<CXFA_FFArc>(
174           m_pDoc->GetHeap()->GetAllocationHandle(), pNode);
175       break;
176     case XFA_FFWidgetType::kLine:
177       pWidget = cppgc::MakeGarbageCollected<CXFA_FFLine>(
178           m_pDoc->GetHeap()->GetAllocationHandle(), pNode);
179       break;
180     case XFA_FFWidgetType::kRectangle:
181       pWidget = cppgc::MakeGarbageCollected<CXFA_FFRectangle>(
182           m_pDoc->GetHeap()->GetAllocationHandle(), pNode);
183       break;
184     case XFA_FFWidgetType::kText:
185       pWidget = cppgc::MakeGarbageCollected<CXFA_FFText>(
186           m_pDoc->GetHeap()->GetAllocationHandle(), pNode);
187       break;
188     case XFA_FFWidgetType::kImage:
189       pWidget = cppgc::MakeGarbageCollected<CXFA_FFImage>(
190           m_pDoc->GetHeap()->GetAllocationHandle(), pNode);
191       break;
192     case XFA_FFWidgetType::kSubform:
193       pWidget = cppgc::MakeGarbageCollected<CXFA_FFWidget>(
194           m_pDoc->GetHeap()->GetAllocationHandle(), pNode);
195       break;
196     case XFA_FFWidgetType::kExclGroup:
197       pWidget = cppgc::MakeGarbageCollected<CXFA_FFExclGroup>(
198           m_pDoc->GetHeap()->GetAllocationHandle(), pNode);
199       break;
200     case XFA_FFWidgetType::kNone:
201       return nullptr;
202   }
203   auto* pLayout = CXFA_LayoutProcessor::FromDocument(m_pDoc->GetXFADoc());
204   pWidget->SetDocView(m_pDoc->GetDocView(pLayout));
205   return pWidget;
206 }
207 
StartFieldDrawLayout(CXFA_Node * pItem,float * pCalcWidth,float * pCalcHeight)208 void CXFA_FFNotify::StartFieldDrawLayout(CXFA_Node* pItem,
209                                          float* pCalcWidth,
210                                          float* pCalcHeight) {
211   pItem->StartWidgetLayout(m_pDoc.Get(), pCalcWidth, pCalcHeight);
212 }
213 
RunScript(CXFA_Script * script,CXFA_Node * item)214 bool CXFA_FFNotify::RunScript(CXFA_Script* script, CXFA_Node* item) {
215   CXFA_FFDocView* pDocView = m_pDoc->GetDocView();
216   if (!pDocView)
217     return false;
218 
219   CXFA_EventParam EventParam;
220   EventParam.m_eType = XFA_EVENT_Unknown;
221   EventParam.m_bTargeted = false;
222 
223   XFA_EventError iRet;
224   bool bRet;
225   std::tie(iRet, bRet) = item->ExecuteBoolScript(pDocView, script, &EventParam);
226   return iRet == XFA_EventError::kSuccess && bRet;
227 }
228 
ExecEventByDeepFirst(CXFA_Node * pFormNode,XFA_EVENTTYPE eEventType,bool bIsFormReady,bool bRecursive)229 XFA_EventError CXFA_FFNotify::ExecEventByDeepFirst(CXFA_Node* pFormNode,
230                                                    XFA_EVENTTYPE eEventType,
231                                                    bool bIsFormReady,
232                                                    bool bRecursive) {
233   CXFA_FFDocView* pDocView = m_pDoc->GetDocView();
234   if (!pDocView)
235     return XFA_EventError::kNotExist;
236   return pDocView->ExecEventActivityByDeepFirst(pFormNode, eEventType,
237                                                 bIsFormReady, bRecursive);
238 }
239 
AddCalcValidate(CXFA_Node * pNode)240 void CXFA_FFNotify::AddCalcValidate(CXFA_Node* pNode) {
241   CXFA_FFDocView* pDocView = m_pDoc->GetDocView();
242   if (!pDocView)
243     return;
244 
245   pDocView->AddCalculateNode(pNode);
246   pDocView->AddValidateNode(pNode);
247 }
248 
GetAppProvider()249 CXFA_FFApp::CallbackIface* CXFA_FFNotify::GetAppProvider() {
250   return m_pDoc->GetApp()->GetAppProvider();
251 }
252 
HandleWidgetEvent(CXFA_Node * pNode,CXFA_EventParam * pParam)253 void CXFA_FFNotify::HandleWidgetEvent(CXFA_Node* pNode,
254                                       CXFA_EventParam* pParam) {
255   CXFA_FFDocView* pDocView = m_pDoc->GetDocView();
256   if (!pDocView)
257     return;
258 
259   CXFA_FFWidgetHandler* pHandler = pDocView->GetWidgetHandler();
260   if (!pHandler)
261     return;
262 
263   pHandler->ProcessEvent(pNode, pParam);
264 }
265 
OpenDropDownList(CXFA_Node * pNode)266 void CXFA_FFNotify::OpenDropDownList(CXFA_Node* pNode) {
267   auto* pDocLayout = CXFA_LayoutProcessor::FromDocument(m_pDoc->GetXFADoc());
268   CXFA_LayoutItem* pLayoutItem = pDocLayout->GetLayoutItem(pNode);
269   if (!pLayoutItem)
270     return;
271 
272   CXFA_FFWidget* hWidget = CXFA_FFWidget::FromLayoutItem(pLayoutItem);
273   if (!hWidget)
274     return;
275 
276   CXFA_FFDoc* hDoc = GetFFDoc();
277   hDoc->SetFocusWidget(hWidget);
278   if (hWidget->GetNode()->GetFFWidgetType() != XFA_FFWidgetType::kChoiceList)
279     return;
280 
281   if (!hWidget->IsLoaded())
282     return;
283 
284   CXFA_FFDropDown* pDropDown = ToDropDown(ToField(hWidget));
285   CXFA_FFComboBox* pComboBox = ToComboBox(pDropDown);
286   if (!pComboBox)
287     return;
288 
289   CXFA_FFDocView::UpdateScope scope(m_pDoc->GetDocView());
290   pComboBox->OpenDropDownList();
291 }
292 
ResetData(CXFA_Node * pNode)293 void CXFA_FFNotify::ResetData(CXFA_Node* pNode) {
294   CXFA_FFDocView* pDocView = m_pDoc->GetDocView();
295   if (!pDocView)
296     return;
297 
298   pDocView->ResetNode(pNode);
299 }
300 
GetLayoutStatus()301 CXFA_FFDocView::LayoutStatus CXFA_FFNotify::GetLayoutStatus() {
302   CXFA_FFDocView* pDocView = m_pDoc->GetDocView();
303   return pDocView ? pDocView->GetLayoutStatus()
304                   : CXFA_FFDocView::LayoutStatus::kNone;
305 }
306 
RunNodeInitialize(CXFA_Node * pNode)307 void CXFA_FFNotify::RunNodeInitialize(CXFA_Node* pNode) {
308   CXFA_FFDocView* pDocView = m_pDoc->GetDocView();
309   if (!pDocView)
310     return;
311 
312   pDocView->AddNewFormNode(pNode);
313 }
314 
RunSubformIndexChange(CXFA_Subform * pSubformNode)315 void CXFA_FFNotify::RunSubformIndexChange(CXFA_Subform* pSubformNode) {
316   CXFA_FFDocView* pDocView = m_pDoc->GetDocView();
317   if (!pDocView)
318     return;
319 
320   pDocView->AddIndexChangedSubform(pSubformNode);
321 }
322 
GetFocusWidgetNode()323 CXFA_Node* CXFA_FFNotify::GetFocusWidgetNode() {
324   CXFA_FFDocView* pDocView = m_pDoc->GetDocView();
325   return pDocView ? pDocView->GetFocusNode() : nullptr;
326 }
327 
SetFocusWidgetNode(CXFA_Node * pNode)328 void CXFA_FFNotify::SetFocusWidgetNode(CXFA_Node* pNode) {
329   CXFA_FFDocView* pDocView = m_pDoc->GetDocView();
330   if (!pDocView)
331     return;
332   pDocView->SetFocusNode(pNode);
333 }
334 
OnNodeReady(CXFA_Node * pNode)335 void CXFA_FFNotify::OnNodeReady(CXFA_Node* pNode) {
336   CXFA_FFDocView* pDocView = m_pDoc->GetDocView();
337   if (!pDocView)
338     return;
339 
340   if (pNode->HasCreatedUIWidget()) {
341     pNode->SetWidgetReady();
342     return;
343   }
344 
345   switch (pNode->GetElementType()) {
346     case XFA_Element::BindItems:
347       pDocView->AddBindItem(static_cast<CXFA_BindItems*>(pNode));
348       break;
349     case XFA_Element::Validate:
350       pNode->SetFlag(XFA_NodeFlag::kNeedsInitApp);
351       break;
352     default:
353       break;
354   }
355 }
356 
OnValueChanging(CXFA_Node * pSender,XFA_Attribute eAttr)357 void CXFA_FFNotify::OnValueChanging(CXFA_Node* pSender, XFA_Attribute eAttr) {
358   if (eAttr != XFA_Attribute::Presence)
359     return;
360   if (pSender->GetPacketType() == XFA_PacketType::Datasets)
361     return;
362   if (!pSender->IsFormContainer())
363     return;
364 
365   CXFA_FFDocView* pDocView = m_pDoc->GetDocView();
366   if (!pDocView)
367     return;
368   if (pDocView->GetLayoutStatus() != CXFA_FFDocView::LayoutStatus::kEnd)
369     return;
370 
371   CXFA_FFWidget* pWidget = m_pDoc->GetDocView()->GetWidgetForNode(pSender);
372   for (; pWidget; pWidget = pWidget->GetNextFFWidget()) {
373     if (pWidget->IsLoaded())
374       pWidget->InvalidateRect();
375   }
376 }
377 
OnValueChanged(CXFA_Node * pSender,XFA_Attribute eAttr,CXFA_Node * pParentNode,CXFA_Node * pWidgetNode)378 void CXFA_FFNotify::OnValueChanged(CXFA_Node* pSender,
379                                    XFA_Attribute eAttr,
380                                    CXFA_Node* pParentNode,
381                                    CXFA_Node* pWidgetNode) {
382   CXFA_FFDocView* pDocView = m_pDoc->GetDocView();
383   if (!pDocView)
384     return;
385 
386   if (pSender->GetPacketType() != XFA_PacketType::Form) {
387     if (eAttr == XFA_Attribute::Value)
388       pDocView->AddCalculateNodeNotify(pSender);
389     return;
390   }
391 
392   XFA_Element eType = pParentNode->GetElementType();
393   bool bIsContainerNode = pParentNode->IsContainerNode();
394   bool bUpdateProperty = false;
395   pDocView->SetChangeMark();
396   switch (eType) {
397     case XFA_Element::Caption: {
398       CXFA_TextLayout* pCapOut = pWidgetNode->GetCaptionTextLayout();
399       if (!pCapOut)
400         return;
401 
402       pCapOut->Unload();
403       break;
404     }
405     case XFA_Element::Ui:
406     case XFA_Element::Para:
407       bUpdateProperty = true;
408       break;
409     default:
410       break;
411   }
412   if (bIsContainerNode && eAttr == XFA_Attribute::Access)
413     bUpdateProperty = true;
414 
415   if (eAttr == XFA_Attribute::Value) {
416     pDocView->AddCalculateNodeNotify(pSender);
417     if (eType == XFA_Element::Value || bIsContainerNode) {
418       if (bIsContainerNode) {
419         m_pDoc->GetDocView()->UpdateUIDisplay(pWidgetNode, nullptr);
420         pDocView->AddCalculateNode(pWidgetNode);
421         pDocView->AddValidateNode(pWidgetNode);
422       } else if (pWidgetNode->GetParent()->GetElementType() ==
423                  XFA_Element::ExclGroup) {
424         m_pDoc->GetDocView()->UpdateUIDisplay(pWidgetNode, nullptr);
425       }
426       return;
427     }
428   }
429 
430   CXFA_FFWidget* pWidget = m_pDoc->GetDocView()->GetWidgetForNode(pWidgetNode);
431   for (; pWidget; pWidget = pWidget->GetNextFFWidget()) {
432     if (!pWidget->IsLoaded())
433       continue;
434 
435     if (bUpdateProperty)
436       pWidget->UpdateWidgetProperty();
437     pWidget->PerformLayout();
438     pWidget->InvalidateRect();
439   }
440 }
441 
OnContainerChanged()442 void CXFA_FFNotify::OnContainerChanged() {
443   m_pDoc->GetXFADoc()->GetLayoutProcessor()->SetHasChangedContainer();
444 }
445 
OnChildAdded(CXFA_Node * pSender)446 void CXFA_FFNotify::OnChildAdded(CXFA_Node* pSender) {
447   if (!pSender->IsFormContainer())
448     return;
449 
450   CXFA_FFDocView* pDocView = m_pDoc->GetDocView();
451   if (!pDocView)
452     return;
453 
454   const bool bLayoutReady =
455       !pDocView->InLayoutStatus() &&
456       pDocView->GetLayoutStatus() == CXFA_FFDocView::LayoutStatus::kEnd;
457   if (bLayoutReady)
458     m_pDoc->SetChangeMark();
459 }
460 
OnChildRemoved()461 void CXFA_FFNotify::OnChildRemoved() {
462   CXFA_FFDocView* pDocView = m_pDoc->GetDocView();
463   if (!pDocView)
464     return;
465 
466   const bool bLayoutReady =
467       !pDocView->InLayoutStatus() &&
468       pDocView->GetLayoutStatus() == CXFA_FFDocView::LayoutStatus::kEnd;
469   if (bLayoutReady)
470     m_pDoc->SetChangeMark();
471 }
472 
OnLayoutItemAdded(CXFA_LayoutProcessor * pLayout,CXFA_LayoutItem * pSender,int32_t iPageIdx,Mask<XFA_WidgetStatus> dwStatus)473 void CXFA_FFNotify::OnLayoutItemAdded(CXFA_LayoutProcessor* pLayout,
474                                       CXFA_LayoutItem* pSender,
475                                       int32_t iPageIdx,
476                                       Mask<XFA_WidgetStatus> dwStatus) {
477   CXFA_FFDocView* pDocView = m_pDoc->GetDocView(pLayout);
478   if (!pDocView)
479     return;
480 
481   CXFA_FFWidget* pWidget = CXFA_FFWidget::FromLayoutItem(pSender);
482   if (!pWidget)
483     return;
484 
485   CXFA_FFPageView* pNewPageView = pDocView->GetPageView(iPageIdx);
486   constexpr Mask<XFA_WidgetStatus> kRemove{XFA_WidgetStatus::kVisible,
487                                            XFA_WidgetStatus::kViewable,
488                                            XFA_WidgetStatus::kPrintable};
489   pWidget->ModifyStatus(dwStatus, kRemove);
490   CXFA_FFPageView* pPrePageView = pWidget->GetPageView();
491   if (pPrePageView != pNewPageView ||
492       dwStatus.TestAll(
493           {XFA_WidgetStatus::kVisible, XFA_WidgetStatus::kViewable})) {
494     pWidget->SetPageView(pNewPageView);
495     m_pDoc->WidgetPostAdd(pWidget);
496   }
497   if (pDocView->GetLayoutStatus() != CXFA_FFDocView::LayoutStatus::kEnd ||
498       !(dwStatus & XFA_WidgetStatus::kVisible)) {
499     return;
500   }
501   if (pWidget->IsLoaded()) {
502     if (pWidget->GetWidgetRect() != pWidget->RecacheWidgetRect())
503       pWidget->PerformLayout();
504   } else {
505     pWidget->LoadWidget();
506   }
507   pWidget->InvalidateRect();
508 }
509 
OnLayoutItemRemoving(CXFA_LayoutProcessor * pLayout,CXFA_LayoutItem * pSender)510 void CXFA_FFNotify::OnLayoutItemRemoving(CXFA_LayoutProcessor* pLayout,
511                                          CXFA_LayoutItem* pSender) {
512   CXFA_FFDocView* pDocView = m_pDoc->GetDocView(pLayout);
513   if (!pDocView)
514     return;
515 
516   CXFA_FFWidget* pWidget = CXFA_FFWidget::FromLayoutItem(pSender);
517   if (!pWidget)
518     return;
519 
520   pDocView->DeleteLayoutItem(pWidget);
521   m_pDoc->WidgetPreRemove(pWidget);
522   pWidget->InvalidateRect();
523 }
524