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