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/app/xfa_ffnotify.h"
8 
9 #include "fxjs/include/cfxjse_value.h"
10 #include "xfa/fxfa/app/xfa_ffbarcode.h"
11 #include "xfa/fxfa/app/xfa_ffcheckbutton.h"
12 #include "xfa/fxfa/app/xfa_ffchoicelist.h"
13 #include "xfa/fxfa/app/xfa_ffdraw.h"
14 #include "xfa/fxfa/app/xfa_ffexclgroup.h"
15 #include "xfa/fxfa/app/xfa_fffield.h"
16 #include "xfa/fxfa/app/xfa_ffimage.h"
17 #include "xfa/fxfa/app/xfa_ffimageedit.h"
18 #include "xfa/fxfa/app/xfa_ffpath.h"
19 #include "xfa/fxfa/app/xfa_ffpushbutton.h"
20 #include "xfa/fxfa/app/xfa_ffsignature.h"
21 #include "xfa/fxfa/app/xfa_ffsubform.h"
22 #include "xfa/fxfa/app/xfa_fftext.h"
23 #include "xfa/fxfa/app/xfa_fftextedit.h"
24 #include "xfa/fxfa/app/xfa_ffwidgetacc.h"
25 #include "xfa/fxfa/app/xfa_fwladapter.h"
26 #include "xfa/fxfa/app/xfa_textlayout.h"
27 #include "xfa/fxfa/include/xfa_ffapp.h"
28 #include "xfa/fxfa/include/xfa_ffdoc.h"
29 #include "xfa/fxfa/include/xfa_ffdocview.h"
30 #include "xfa/fxfa/include/xfa_ffpageview.h"
31 #include "xfa/fxfa/include/xfa_ffwidget.h"
32 #include "xfa/fxfa/include/xfa_ffwidgethandler.h"
33 
XFA_FFDeleteWidgetAcc(void * pData)34 static void XFA_FFDeleteWidgetAcc(void* pData) {
35   delete static_cast<CXFA_WidgetAcc*>(pData);
36 }
37 
38 static XFA_MAPDATABLOCKCALLBACKINFO gs_XFADeleteWidgetAcc = {
39     XFA_FFDeleteWidgetAcc, nullptr};
40 
CXFA_FFNotify(CXFA_FFDoc * pDoc)41 CXFA_FFNotify::CXFA_FFNotify(CXFA_FFDoc* pDoc) : m_pDoc(pDoc) {}
~CXFA_FFNotify()42 CXFA_FFNotify::~CXFA_FFNotify() {}
43 
OnPageEvent(CXFA_ContainerLayoutItem * pSender,uint32_t dwEvent)44 void CXFA_FFNotify::OnPageEvent(CXFA_ContainerLayoutItem* pSender,
45                                 uint32_t dwEvent) {
46   CXFA_FFDocView* pDocView = m_pDoc->GetDocView(pSender->GetLayout());
47   if (pDocView)
48     pDocView->OnPageEvent(pSender, dwEvent);
49 }
50 
OnWidgetListItemAdded(CXFA_WidgetData * pSender,const FX_WCHAR * pLabel,const FX_WCHAR * pValue,int32_t iIndex)51 void CXFA_FFNotify::OnWidgetListItemAdded(CXFA_WidgetData* pSender,
52                                           const FX_WCHAR* pLabel,
53                                           const FX_WCHAR* pValue,
54                                           int32_t iIndex) {
55   CXFA_WidgetAcc* pWidgetAcc = static_cast<CXFA_WidgetAcc*>(pSender);
56   if (pWidgetAcc->GetUIType() != XFA_Element::ChoiceList)
57     return;
58 
59   CXFA_FFWidget* pWidget = nullptr;
60   while ((pWidget = pWidgetAcc->GetNextWidget(pWidget)) != nullptr) {
61     if (pWidget->IsLoaded()) {
62       if (pWidgetAcc->IsListBox()) {
63         static_cast<CXFA_FFListBox*>(pWidget)->InsertItem(pLabel, iIndex);
64       } else {
65         static_cast<CXFA_FFComboBox*>(pWidget)->InsertItem(pLabel, iIndex);
66       }
67     }
68   }
69 }
70 
OnWidgetListItemRemoved(CXFA_WidgetData * pSender,int32_t iIndex)71 void CXFA_FFNotify::OnWidgetListItemRemoved(CXFA_WidgetData* pSender,
72                                             int32_t iIndex) {
73   CXFA_WidgetAcc* pWidgetAcc = static_cast<CXFA_WidgetAcc*>(pSender);
74   if (pWidgetAcc->GetUIType() != XFA_Element::ChoiceList)
75     return;
76 
77   CXFA_FFWidget* pWidget = nullptr;
78   while ((pWidget = pWidgetAcc->GetNextWidget(pWidget)) != nullptr) {
79     if (pWidget->IsLoaded()) {
80       if (pWidgetAcc->IsListBox()) {
81         static_cast<CXFA_FFListBox*>(pWidget)->DeleteItem(iIndex);
82       } else {
83         static_cast<CXFA_FFComboBox*>(pWidget)->DeleteItem(iIndex);
84       }
85     }
86   }
87 }
88 
OnCreateLayoutItem(CXFA_Node * pNode)89 CXFA_LayoutItem* CXFA_FFNotify::OnCreateLayoutItem(CXFA_Node* pNode) {
90   CXFA_LayoutProcessor* pLayout = m_pDoc->GetXFADoc()->GetDocLayout();
91   CXFA_FFDocView* pDocView = m_pDoc->GetDocView(pLayout);
92   XFA_Element eType = pNode->GetElementType();
93   if (eType == XFA_Element::PageArea)
94     return new CXFA_FFPageView(pDocView, pNode);
95   if (eType == XFA_Element::ContentArea)
96     return new CXFA_ContainerLayoutItem(pNode);
97 
98   CXFA_WidgetAcc* pAcc = static_cast<CXFA_WidgetAcc*>(pNode->GetWidgetData());
99   if (!pAcc)
100     return new CXFA_ContentLayoutItem(pNode);
101 
102   CXFA_FFWidget* pWidget;
103   switch (pAcc->GetUIType()) {
104     case XFA_Element::Barcode:
105       pWidget = new CXFA_FFBarcode(nullptr, pAcc);
106       break;
107     case XFA_Element::Button:
108       pWidget = new CXFA_FFPushButton(nullptr, pAcc);
109       break;
110     case XFA_Element::CheckButton:
111       pWidget = new CXFA_FFCheckButton(nullptr, pAcc);
112       break;
113     case XFA_Element::ChoiceList: {
114       if (pAcc->IsListBox()) {
115         pWidget = new CXFA_FFListBox(nullptr, pAcc);
116       } else {
117         pWidget = new CXFA_FFComboBox(nullptr, pAcc);
118       }
119     } break;
120     case XFA_Element::DateTimeEdit:
121       pWidget = new CXFA_FFDateTimeEdit(nullptr, pAcc);
122       break;
123     case XFA_Element::ImageEdit:
124       pWidget = new CXFA_FFImageEdit(nullptr, pAcc);
125       break;
126     case XFA_Element::NumericEdit:
127       pWidget = new CXFA_FFNumericEdit(nullptr, pAcc);
128       break;
129     case XFA_Element::PasswordEdit:
130       pWidget = new CXFA_FFPasswordEdit(nullptr, pAcc);
131       break;
132     case XFA_Element::Signature:
133       pWidget = new CXFA_FFSignature(nullptr, pAcc);
134       break;
135     case XFA_Element::TextEdit:
136       pWidget = new CXFA_FFTextEdit(nullptr, pAcc);
137       break;
138     case XFA_Element::Arc:
139       pWidget = new CXFA_FFArc(nullptr, pAcc);
140       break;
141     case XFA_Element::Line:
142       pWidget = new CXFA_FFLine(nullptr, pAcc);
143       break;
144     case XFA_Element::Rectangle:
145       pWidget = new CXFA_FFRectangle(nullptr, pAcc);
146       break;
147     case XFA_Element::Text:
148       pWidget = new CXFA_FFText(nullptr, pAcc);
149       break;
150     case XFA_Element::Image:
151       pWidget = new CXFA_FFImage(nullptr, pAcc);
152       break;
153     case XFA_Element::Draw:
154       pWidget = new CXFA_FFDraw(nullptr, pAcc);
155       break;
156     case XFA_Element::Subform:
157       pWidget = new CXFA_FFSubForm(nullptr, pAcc);
158       break;
159     case XFA_Element::ExclGroup:
160       pWidget = new CXFA_FFExclGroup(nullptr, pAcc);
161       break;
162     case XFA_Element::DefaultUi:
163     default:
164       pWidget = nullptr;
165       break;
166   }
167 
168   if (pWidget)
169     pWidget->SetDocView(pDocView);
170   return pWidget;
171 }
172 
StartFieldDrawLayout(CXFA_Node * pItem,FX_FLOAT & fCalcWidth,FX_FLOAT & fCalcHeight)173 void CXFA_FFNotify::StartFieldDrawLayout(CXFA_Node* pItem,
174                                          FX_FLOAT& fCalcWidth,
175                                          FX_FLOAT& fCalcHeight) {
176   CXFA_WidgetAcc* pAcc = static_cast<CXFA_WidgetAcc*>(pItem->GetWidgetData());
177   if (!pAcc) {
178     return;
179   }
180   pAcc->StartWidgetLayout(fCalcWidth, fCalcHeight);
181 }
FindSplitPos(CXFA_Node * pItem,int32_t iBlockIndex,FX_FLOAT & fCalcHeightPos)182 FX_BOOL CXFA_FFNotify::FindSplitPos(CXFA_Node* pItem,
183                                     int32_t iBlockIndex,
184                                     FX_FLOAT& fCalcHeightPos) {
185   CXFA_WidgetAcc* pAcc = static_cast<CXFA_WidgetAcc*>(pItem->GetWidgetData());
186   if (!pAcc) {
187     return FALSE;
188   }
189   return (XFA_LAYOUTRESULT)pAcc->FindSplitPos(iBlockIndex, fCalcHeightPos);
190 }
RunScript(CXFA_Node * pScript,CXFA_Node * pFormItem)191 FX_BOOL CXFA_FFNotify::RunScript(CXFA_Node* pScript, CXFA_Node* pFormItem) {
192   FX_BOOL bRet = FALSE;
193   CXFA_FFDocView* pDocView = m_pDoc->GetDocView();
194   if (!pDocView) {
195     return bRet;
196   }
197   CXFA_WidgetAcc* pWidgetAcc =
198       static_cast<CXFA_WidgetAcc*>(pFormItem->GetWidgetData());
199   if (!pWidgetAcc) {
200     return bRet;
201   }
202   CXFA_EventParam EventParam;
203   EventParam.m_eType = XFA_EVENT_Unknown;
204   CFXJSE_Value* pRetValue = nullptr;
205   int32_t iRet =
206       pWidgetAcc->ExecuteScript(CXFA_Script(pScript), &EventParam, &pRetValue);
207   if (iRet == XFA_EVENTERROR_Success && pRetValue) {
208     bRet = pRetValue->ToBoolean();
209     delete pRetValue;
210   }
211   return bRet;
212 }
ExecEventByDeepFirst(CXFA_Node * pFormNode,XFA_EVENTTYPE eEventType,FX_BOOL bIsFormReady,FX_BOOL bRecursive,CXFA_WidgetAcc * pExclude)213 int32_t CXFA_FFNotify::ExecEventByDeepFirst(CXFA_Node* pFormNode,
214                                             XFA_EVENTTYPE eEventType,
215                                             FX_BOOL bIsFormReady,
216                                             FX_BOOL bRecursive,
217                                             CXFA_WidgetAcc* pExclude) {
218   CXFA_FFDocView* pDocView = m_pDoc->GetDocView();
219   if (!pDocView) {
220     return XFA_EVENTERROR_NotExist;
221   }
222   return pDocView->ExecEventActivityByDeepFirst(
223       pFormNode, eEventType, bIsFormReady, bRecursive,
224       pExclude ? pExclude->GetNode() : nullptr);
225 }
AddCalcValidate(CXFA_Node * pNode)226 void CXFA_FFNotify::AddCalcValidate(CXFA_Node* pNode) {
227   CXFA_FFDocView* pDocView = m_pDoc->GetDocView();
228   if (!pDocView) {
229     return;
230   }
231   CXFA_WidgetAcc* pWidgetAcc =
232       static_cast<CXFA_WidgetAcc*>(pNode->GetWidgetData());
233   if (!pWidgetAcc) {
234     return;
235   }
236   pDocView->AddCalculateWidgetAcc(pWidgetAcc);
237   pDocView->AddValidateWidget(pWidgetAcc);
238 }
GetHDOC()239 CXFA_FFDoc* CXFA_FFNotify::GetHDOC() {
240   return m_pDoc;
241 }
GetDocProvider()242 IXFA_DocProvider* CXFA_FFNotify::GetDocProvider() {
243   return m_pDoc->GetDocProvider();
244 }
GetAppProvider()245 IXFA_AppProvider* CXFA_FFNotify::GetAppProvider() {
246   return m_pDoc->GetApp()->GetAppProvider();
247 }
GetWidgetHandler()248 CXFA_FFWidgetHandler* CXFA_FFNotify::GetWidgetHandler() {
249   CXFA_FFDocView* pDocView = m_pDoc->GetDocView();
250   return pDocView ? pDocView->GetWidgetHandler() : nullptr;
251 }
GetHWidget(CXFA_LayoutItem * pLayoutItem)252 CXFA_FFWidget* CXFA_FFNotify::GetHWidget(CXFA_LayoutItem* pLayoutItem) {
253   return XFA_GetWidgetFromLayoutItem(pLayoutItem);
254 }
OpenDropDownList(CXFA_FFWidget * hWidget)255 void CXFA_FFNotify::OpenDropDownList(CXFA_FFWidget* hWidget) {
256   if (hWidget->GetDataAcc()->GetUIType() != XFA_Element::ChoiceList) {
257     return;
258   }
259   CXFA_FFDocView* pDocView = m_pDoc->GetDocView();
260   pDocView->LockUpdate();
261   static_cast<CXFA_FFComboBox*>(hWidget)->OpenDropDownList();
262   pDocView->UnlockUpdate();
263   pDocView->UpdateDocView();
264 }
GetCurrentDateTime()265 CFX_WideString CXFA_FFNotify::GetCurrentDateTime() {
266   CFX_Unitime dataTime;
267   dataTime.Now();
268   CFX_WideString wsDateTime;
269   wsDateTime.Format(L"%d%02d%02dT%02d%02d%02d", dataTime.GetYear(),
270                     dataTime.GetMonth(), dataTime.GetDay(), dataTime.GetHour(),
271                     dataTime.GetMinute(), dataTime.GetSecond());
272   return wsDateTime;
273 }
ResetData(CXFA_WidgetData * pWidgetData)274 void CXFA_FFNotify::ResetData(CXFA_WidgetData* pWidgetData) {
275   CXFA_FFDocView* pDocView = m_pDoc->GetDocView();
276   if (!pDocView) {
277     return;
278   }
279   pDocView->ResetWidgetData(static_cast<CXFA_WidgetAcc*>(pWidgetData));
280 }
GetLayoutStatus()281 int32_t CXFA_FFNotify::GetLayoutStatus() {
282   CXFA_FFDocView* pDocView = m_pDoc->GetDocView();
283   return pDocView ? pDocView->GetLayoutStatus() : 0;
284 }
RunNodeInitialize(CXFA_Node * pNode)285 void CXFA_FFNotify::RunNodeInitialize(CXFA_Node* pNode) {
286   CXFA_FFDocView* pDocView = m_pDoc->GetDocView();
287   if (!pDocView) {
288     return;
289   }
290   pDocView->AddNewFormNode(pNode);
291 }
RunSubformIndexChange(CXFA_Node * pSubformNode)292 void CXFA_FFNotify::RunSubformIndexChange(CXFA_Node* pSubformNode) {
293   CXFA_FFDocView* pDocView = m_pDoc->GetDocView();
294   if (!pDocView) {
295     return;
296   }
297   pDocView->AddIndexChangedSubform(pSubformNode);
298 }
GetFocusWidgetNode()299 CXFA_Node* CXFA_FFNotify::GetFocusWidgetNode() {
300   CXFA_FFDocView* pDocView = m_pDoc->GetDocView();
301   if (!pDocView) {
302     return nullptr;
303   }
304   CXFA_WidgetAcc* pAcc = pDocView->GetFocusWidgetAcc();
305   return pAcc ? pAcc->GetNode() : nullptr;
306 }
SetFocusWidgetNode(CXFA_Node * pNode)307 void CXFA_FFNotify::SetFocusWidgetNode(CXFA_Node* pNode) {
308   CXFA_FFDocView* pDocView = m_pDoc->GetDocView();
309   if (!pDocView) {
310     return;
311   }
312   CXFA_WidgetAcc* pAcc =
313       pNode ? static_cast<CXFA_WidgetAcc*>(pNode->GetWidgetData()) : nullptr;
314   pDocView->SetFocusWidgetAcc(pAcc);
315 }
316 
OnNodeReady(CXFA_Node * pNode)317 void CXFA_FFNotify::OnNodeReady(CXFA_Node* pNode) {
318   CXFA_FFDocView* pDocView = m_pDoc->GetDocView();
319   if (!pDocView)
320     return;
321 
322   XFA_Element eType = pNode->GetElementType();
323   if (XFA_IsCreateWidget(eType)) {
324     CXFA_WidgetAcc* pAcc = new CXFA_WidgetAcc(pDocView, pNode);
325     pNode->SetObject(XFA_ATTRIBUTE_WidgetData, pAcc, &gs_XFADeleteWidgetAcc);
326     return;
327   }
328   switch (eType) {
329     case XFA_Element::BindItems:
330       pDocView->m_BindItems.Add(pNode);
331       break;
332     case XFA_Element::Validate: {
333       pNode->SetFlag(XFA_NodeFlag_NeedsInitApp, false);
334     } break;
335     default:
336       break;
337   }
338 }
339 
OnValueChanging(CXFA_Node * pSender,XFA_ATTRIBUTE eAttr)340 void CXFA_FFNotify::OnValueChanging(CXFA_Node* pSender, XFA_ATTRIBUTE eAttr) {
341   if (eAttr != XFA_ATTRIBUTE_Presence)
342     return;
343 
344   if (pSender->GetPacketID() & XFA_XDPPACKET_Datasets)
345     return;
346 
347   if (!pSender->IsFormContainer())
348     return;
349 
350   CXFA_FFDocView* pDocView = m_pDoc->GetDocView();
351   if (!pDocView)
352     return;
353 
354   if (pDocView->GetLayoutStatus() < XFA_DOCVIEW_LAYOUTSTATUS_End)
355     return;
356 
357   CXFA_WidgetAcc* pWidgetAcc =
358       static_cast<CXFA_WidgetAcc*>(pSender->GetWidgetData());
359   if (!pWidgetAcc)
360     return;
361 
362   CXFA_FFWidget* pWidget = nullptr;
363   while ((pWidget = pWidgetAcc->GetNextWidget(pWidget)) != nullptr) {
364     if (pWidget->IsLoaded())
365       pWidget->AddInvalidateRect();
366   }
367 }
368 
OnValueChanged(CXFA_Node * pSender,XFA_ATTRIBUTE eAttr,CXFA_Node * pParentNode,CXFA_Node * pWidgetNode)369 void CXFA_FFNotify::OnValueChanged(CXFA_Node* pSender,
370                                    XFA_ATTRIBUTE eAttr,
371                                    CXFA_Node* pParentNode,
372                                    CXFA_Node* pWidgetNode) {
373   CXFA_FFDocView* pDocView = m_pDoc->GetDocView();
374   if (!pDocView)
375     return;
376 
377   if (!(pSender->GetPacketID() & XFA_XDPPACKET_Form)) {
378     if (eAttr == XFA_ATTRIBUTE_Value)
379       pDocView->AddCalculateNodeNotify(pSender);
380     return;
381   }
382 
383   XFA_Element eType = pParentNode->GetElementType();
384   FX_BOOL bIsContainerNode = pParentNode->IsContainerNode();
385   CXFA_WidgetAcc* pWidgetAcc =
386       static_cast<CXFA_WidgetAcc*>(pWidgetNode->GetWidgetData());
387   if (!pWidgetAcc)
388     return;
389 
390   bool bUpdateProperty = false;
391   pDocView->SetChangeMark();
392   switch (eType) {
393     case XFA_Element::Caption: {
394       CXFA_TextLayout* pCapOut = pWidgetAcc->GetCaptionTextLayout();
395       if (!pCapOut)
396         return;
397 
398       pCapOut->Unload();
399     } break;
400     case XFA_Element::Ui:
401     case XFA_Element::Para:
402       bUpdateProperty = true;
403       break;
404     default:
405       break;
406   }
407   if (bIsContainerNode && eAttr == XFA_ATTRIBUTE_Access)
408     bUpdateProperty = true;
409 
410   if (eAttr == XFA_ATTRIBUTE_Value) {
411     pDocView->AddCalculateNodeNotify(pSender);
412     if (eType == XFA_Element::Value || bIsContainerNode) {
413       if (bIsContainerNode) {
414         pWidgetAcc->UpdateUIDisplay();
415         pDocView->AddCalculateWidgetAcc(pWidgetAcc);
416         pDocView->AddValidateWidget(pWidgetAcc);
417       } else if (pWidgetNode->GetNodeItem(XFA_NODEITEM_Parent)
418                      ->GetElementType() == XFA_Element::ExclGroup) {
419         pWidgetAcc->UpdateUIDisplay();
420       }
421       return;
422     }
423   }
424   CXFA_FFWidget* pWidget = nullptr;
425   while ((pWidget = pWidgetAcc->GetNextWidget(pWidget)) != nullptr) {
426     if (!pWidget->IsLoaded())
427       continue;
428 
429     if (bUpdateProperty)
430       pWidget->UpdateWidgetProperty();
431     pWidget->PerformLayout();
432     pWidget->AddInvalidateRect();
433   }
434 }
435 
OnChildAdded(CXFA_Node * pSender)436 void CXFA_FFNotify::OnChildAdded(CXFA_Node* pSender) {
437   if (!pSender->IsFormContainer()) {
438     return;
439   }
440   CXFA_FFDocView* pDocView = m_pDoc->GetDocView();
441   if (!pDocView) {
442     return;
443   }
444   FX_BOOL bLayoutReady =
445       !(pDocView->m_bInLayoutStatus) &&
446       (pDocView->GetLayoutStatus() == XFA_DOCVIEW_LAYOUTSTATUS_End);
447   if (bLayoutReady)
448     m_pDoc->GetDocProvider()->SetChangeMark(m_pDoc);
449 }
450 
OnChildRemoved()451 void CXFA_FFNotify::OnChildRemoved() {
452   CXFA_FFDocView* pDocView = m_pDoc->GetDocView();
453   if (!pDocView)
454     return;
455 
456   bool bLayoutReady =
457       !(pDocView->m_bInLayoutStatus) &&
458       (pDocView->GetLayoutStatus() == XFA_DOCVIEW_LAYOUTSTATUS_End);
459   if (bLayoutReady)
460     m_pDoc->GetDocProvider()->SetChangeMark(m_pDoc);
461 }
462 
OnLayoutItemAdded(CXFA_LayoutProcessor * pLayout,CXFA_LayoutItem * pSender,int32_t iPageIdx,uint32_t dwStatus)463 void CXFA_FFNotify::OnLayoutItemAdded(CXFA_LayoutProcessor* pLayout,
464                                       CXFA_LayoutItem* pSender,
465                                       int32_t iPageIdx,
466                                       uint32_t dwStatus) {
467   CXFA_FFDocView* pDocView = m_pDoc->GetDocView(pLayout);
468   if (!pDocView)
469     return;
470 
471   CXFA_FFWidget* pWidget = XFA_GetWidgetFromLayoutItem(pSender);
472   if (!pWidget)
473     return;
474 
475   CXFA_FFPageView* pNewPageView = pDocView->GetPageView(iPageIdx);
476   uint32_t dwFilter = XFA_WidgetStatus_Visible | XFA_WidgetStatus_Viewable |
477                       XFA_WidgetStatus_Printable;
478   pWidget->ModifyStatus(dwStatus, dwFilter);
479   CXFA_FFPageView* pPrePageView = pWidget->GetPageView();
480   if (pPrePageView != pNewPageView ||
481       (dwStatus & (XFA_WidgetStatus_Visible | XFA_WidgetStatus_Viewable)) ==
482           (XFA_WidgetStatus_Visible | XFA_WidgetStatus_Viewable)) {
483     pWidget->SetPageView(pNewPageView);
484     m_pDoc->GetDocProvider()->WidgetPostAdd(pWidget, pWidget->GetDataAcc());
485   }
486   if (pDocView->GetLayoutStatus() != XFA_DOCVIEW_LAYOUTSTATUS_End ||
487       !(dwStatus & XFA_WidgetStatus_Visible)) {
488     return;
489   }
490   if (pWidget->IsLoaded()) {
491     CFX_RectF rtOld;
492     pWidget->GetWidgetRect(rtOld);
493     if (rtOld != pWidget->ReCacheWidgetRect())
494       pWidget->PerformLayout();
495   } else {
496     pWidget->LoadWidget();
497   }
498   pWidget->AddInvalidateRect(nullptr);
499 }
500 
OnLayoutItemRemoving(CXFA_LayoutProcessor * pLayout,CXFA_LayoutItem * pSender)501 void CXFA_FFNotify::OnLayoutItemRemoving(CXFA_LayoutProcessor* pLayout,
502                                          CXFA_LayoutItem* pSender) {
503   CXFA_FFDocView* pDocView = m_pDoc->GetDocView(pLayout);
504   if (!pDocView)
505     return;
506 
507   CXFA_FFWidget* pWidget = XFA_GetWidgetFromLayoutItem(pSender);
508   if (!pWidget)
509     return;
510 
511   pDocView->DeleteLayoutItem(pWidget);
512   m_pDoc->GetDocProvider()->WidgetPreRemove(pWidget, pWidget->GetDataAcc());
513   pWidget->AddInvalidateRect(nullptr);
514 }
515