xfa_ffnotify.cpp revision 4d3acf4ec42bf6e838f9060103aff98fbf170794
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 34static void XFA_FFDeleteWidgetAcc(void* pData) { 35 delete static_cast<CXFA_WidgetAcc*>(pData); 36} 37 38static XFA_MAPDATABLOCKCALLBACKINFO gs_XFADeleteWidgetAcc = { 39 XFA_FFDeleteWidgetAcc, nullptr}; 40 41CXFA_FFNotify::CXFA_FFNotify(CXFA_FFDoc* pDoc) : m_pDoc(pDoc) {} 42CXFA_FFNotify::~CXFA_FFNotify() {} 43 44void 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 51void 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 71void 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 89CXFA_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 173void 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 183bool 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 190bool 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} 212int32_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} 225void 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} 238CXFA_FFDoc* CXFA_FFNotify::GetHDOC() { 239 return m_pDoc; 240} 241IXFA_DocEnvironment* CXFA_FFNotify::GetDocEnvironment() const { 242 return m_pDoc->GetDocEnvironment(); 243} 244IXFA_AppProvider* CXFA_FFNotify::GetAppProvider() { 245 return m_pDoc->GetApp()->GetAppProvider(); 246} 247CXFA_FFWidgetHandler* CXFA_FFNotify::GetWidgetHandler() { 248 CXFA_FFDocView* pDocView = m_pDoc->GetDocView(); 249 return pDocView ? pDocView->GetWidgetHandler() : nullptr; 250} 251CXFA_FFWidget* CXFA_FFNotify::GetHWidget(CXFA_LayoutItem* pLayoutItem) { 252 return XFA_GetWidgetFromLayoutItem(pLayoutItem); 253} 254void 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} 264CFX_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} 273void 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} 280int32_t CXFA_FFNotify::GetLayoutStatus() { 281 CXFA_FFDocView* pDocView = m_pDoc->GetDocView(); 282 return pDocView ? pDocView->GetLayoutStatus() : 0; 283} 284void CXFA_FFNotify::RunNodeInitialize(CXFA_Node* pNode) { 285 CXFA_FFDocView* pDocView = m_pDoc->GetDocView(); 286 if (!pDocView) { 287 return; 288 } 289 pDocView->AddNewFormNode(pNode); 290} 291void CXFA_FFNotify::RunSubformIndexChange(CXFA_Node* pSubformNode) { 292 CXFA_FFDocView* pDocView = m_pDoc->GetDocView(); 293 if (!pDocView) { 294 return; 295 } 296 pDocView->AddIndexChangedSubform(pSubformNode); 297} 298CXFA_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} 306void 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 316void 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 339void 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 368void 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 435void 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 450void 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 462void 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 CFX_RectF rtOld; 491 pWidget->GetWidgetRect(rtOld); 492 if (rtOld != pWidget->ReCacheWidgetRect()) 493 pWidget->PerformLayout(); 494 } else { 495 pWidget->LoadWidget(); 496 } 497 pWidget->AddInvalidateRect(nullptr); 498} 499 500void CXFA_FFNotify::OnLayoutItemRemoving(CXFA_LayoutProcessor* pLayout, 501 CXFA_LayoutItem* pSender) { 502 CXFA_FFDocView* pDocView = m_pDoc->GetDocView(pLayout); 503 if (!pDocView) 504 return; 505 506 CXFA_FFWidget* pWidget = XFA_GetWidgetFromLayoutItem(pSender); 507 if (!pWidget) 508 return; 509 510 pDocView->DeleteLayoutItem(pWidget); 511 m_pDoc->GetDocEnvironment()->WidgetPreRemove(pWidget, pWidget->GetDataAcc()); 512 pWidget->AddInvalidateRect(nullptr); 513} 514