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_fffield.h" 8 9 #include "xfa/fwl/cfwl_edit.h" 10 #include "xfa/fwl/cfwl_eventmouse.h" 11 #include "xfa/fwl/cfwl_messagekey.h" 12 #include "xfa/fwl/cfwl_messagekillfocus.h" 13 #include "xfa/fwl/cfwl_messagemouse.h" 14 #include "xfa/fwl/cfwl_messagemousewheel.h" 15 #include "xfa/fwl/cfwl_messagesetfocus.h" 16 #include "xfa/fwl/cfwl_picturebox.h" 17 #include "xfa/fwl/cfwl_widgetmgr.h" 18 #include "xfa/fxfa/cxfa_ffapp.h" 19 #include "xfa/fxfa/cxfa_ffdoc.h" 20 #include "xfa/fxfa/cxfa_ffdocview.h" 21 #include "xfa/fxfa/cxfa_ffpageview.h" 22 #include "xfa/fxfa/cxfa_ffwidget.h" 23 #include "xfa/fxfa/cxfa_fwltheme.h" 24 #include "xfa/fxfa/cxfa_textlayout.h" 25 #include "xfa/fxfa/parser/cxfa_border.h" 26 #include "xfa/fxfa/parser/cxfa_calculate.h" 27 #include "xfa/fxfa/parser/cxfa_caption.h" 28 #include "xfa/fxfa/parser/cxfa_margin.h" 29 #include "xfa/fxfa/parser/cxfa_node.h" 30 #include "xfa/fxfa/parser/cxfa_script.h" 31 #include "xfa/fxgraphics/cxfa_gecolor.h" 32 #include "xfa/fxgraphics/cxfa_gepath.h" 33 34 namespace { 35 36 CXFA_FFField* ToField(CXFA_LayoutItem* widget) { 37 return static_cast<CXFA_FFField*>(widget); 38 } 39 40 } // namespace 41 42 CXFA_FFField::CXFA_FFField(CXFA_Node* pNode) : CXFA_FFWidget(pNode) {} 43 44 CXFA_FFField::~CXFA_FFField() { 45 CXFA_FFField::UnloadWidget(); 46 } 47 48 CFX_RectF CXFA_FFField::GetBBox(uint32_t dwStatus, bool bDrawFocus) { 49 if (!bDrawFocus) 50 return CXFA_FFWidget::GetBBox(dwStatus); 51 52 XFA_Element type = m_pNode->GetWidgetAcc()->GetUIType(); 53 if (type != XFA_Element::Button && type != XFA_Element::CheckButton && 54 type != XFA_Element::ImageEdit && type != XFA_Element::Signature && 55 type != XFA_Element::ChoiceList) { 56 return CFX_RectF(); 57 } 58 59 return GetRotateMatrix().TransformRect(m_rtUI); 60 } 61 62 void CXFA_FFField::RenderWidget(CXFA_Graphics* pGS, 63 const CFX_Matrix& matrix, 64 uint32_t dwStatus) { 65 if (!IsMatchVisibleStatus(dwStatus)) 66 return; 67 68 CFX_Matrix mtRotate = GetRotateMatrix(); 69 mtRotate.Concat(matrix); 70 71 CXFA_FFWidget::RenderWidget(pGS, mtRotate, dwStatus); 72 DrawBorder(pGS, m_pNode->GetWidgetAcc()->GetUIBorder(), m_rtUI, mtRotate); 73 RenderCaption(pGS, &mtRotate); 74 DrawHighlight(pGS, &mtRotate, dwStatus, false); 75 76 CFX_RectF rtWidget = m_pNormalWidget->GetWidgetRect(); 77 CFX_Matrix mt(1, 0, 0, 1, rtWidget.left, rtWidget.top); 78 mt.Concat(mtRotate); 79 GetApp()->GetFWLWidgetMgr()->OnDrawWidget(m_pNormalWidget.get(), pGS, mt); 80 } 81 82 void CXFA_FFField::DrawHighlight(CXFA_Graphics* pGS, 83 CFX_Matrix* pMatrix, 84 uint32_t dwStatus, 85 bool bEllipse) { 86 if (m_rtUI.IsEmpty() || !GetDoc()->GetXFADoc()->IsInteractive()) 87 return; 88 if (!(dwStatus & XFA_WidgetStatus_Highlight) || !m_pNode->IsOpenAccess()) 89 return; 90 91 CXFA_FFDoc* pDoc = GetDoc(); 92 pGS->SetFillColor( 93 CXFA_GEColor(pDoc->GetDocEnvironment()->GetHighlightColor(pDoc))); 94 CXFA_GEPath path; 95 if (bEllipse) 96 path.AddEllipse(m_rtUI); 97 else 98 path.AddRectangle(m_rtUI.left, m_rtUI.top, m_rtUI.width, m_rtUI.height); 99 100 pGS->FillPath(&path, FXFILL_WINDING, pMatrix); 101 } 102 103 void CXFA_FFField::DrawFocus(CXFA_Graphics* pGS, CFX_Matrix* pMatrix) { 104 if (!(m_dwStatus & XFA_WidgetStatus_Focused)) 105 return; 106 107 pGS->SetStrokeColor(CXFA_GEColor(0xFF000000)); 108 109 float DashPattern[2] = {1, 1}; 110 pGS->SetLineDash(0.0f, DashPattern, 2); 111 pGS->SetLineWidth(0); 112 113 CXFA_GEPath path; 114 path.AddRectangle(m_rtUI.left, m_rtUI.top, m_rtUI.width, m_rtUI.height); 115 pGS->StrokePath(&path, pMatrix); 116 } 117 118 void CXFA_FFField::SetFWLThemeProvider() { 119 if (m_pNormalWidget) 120 m_pNormalWidget->SetThemeProvider(GetApp()->GetFWLTheme()); 121 } 122 123 bool CXFA_FFField::IsLoaded() { 124 return m_pNormalWidget && CXFA_FFWidget::IsLoaded(); 125 } 126 127 bool CXFA_FFField::LoadWidget() { 128 SetFWLThemeProvider(); 129 m_pNode->GetWidgetAcc()->LoadCaption(GetDoc()); 130 PerformLayout(); 131 return true; 132 } 133 134 void CXFA_FFField::UnloadWidget() { 135 m_pNormalWidget.reset(); 136 } 137 138 void CXFA_FFField::SetEditScrollOffset() { 139 XFA_Element eType = m_pNode->GetWidgetAcc()->GetUIType(); 140 if (eType != XFA_Element::TextEdit && eType != XFA_Element::NumericEdit && 141 eType != XFA_Element::PasswordEdit) { 142 return; 143 } 144 145 float fScrollOffset = 0; 146 CXFA_FFField* pPrev = ToField(GetPrev()); 147 if (pPrev) { 148 CFX_RectF rtMargin = m_pNode->GetWidgetAcc()->GetUIMargin(); 149 fScrollOffset = -rtMargin.top; 150 } 151 152 while (pPrev) { 153 fScrollOffset += pPrev->m_rtUI.height; 154 pPrev = ToField(pPrev->GetPrev()); 155 } 156 static_cast<CFWL_Edit*>(m_pNormalWidget.get()) 157 ->SetScrollOffset(fScrollOffset); 158 } 159 160 bool CXFA_FFField::PerformLayout() { 161 CXFA_FFWidget::PerformLayout(); 162 CapPlacement(); 163 LayoutCaption(); 164 SetFWLRect(); 165 SetEditScrollOffset(); 166 if (m_pNormalWidget) 167 m_pNormalWidget->Update(); 168 return true; 169 } 170 171 void CXFA_FFField::CapPlacement() { 172 CFX_RectF rtWidget = GetRectWithoutRotate(); 173 CXFA_Margin* margin = m_pNode->GetMarginIfExists(); 174 if (margin) { 175 CXFA_LayoutItem* pItem = this; 176 float fLeftInset = margin->GetLeftInset(); 177 float fRightInset = margin->GetRightInset(); 178 float fTopInset = margin->GetTopInset(); 179 float fBottomInset = margin->GetBottomInset(); 180 if (!pItem->GetPrev() && !pItem->GetNext()) { 181 rtWidget.Deflate(fLeftInset, fTopInset, fRightInset, fBottomInset); 182 } else { 183 if (!pItem->GetPrev()) 184 rtWidget.Deflate(fLeftInset, fTopInset, fRightInset, 0); 185 else if (!pItem->GetNext()) 186 rtWidget.Deflate(fLeftInset, 0, fRightInset, fBottomInset); 187 else 188 rtWidget.Deflate(fLeftInset, 0, fRightInset, 0); 189 } 190 } 191 192 XFA_AttributeEnum iCapPlacement = XFA_AttributeEnum::Unknown; 193 float fCapReserve = 0; 194 CXFA_Caption* caption = m_pNode->GetCaptionIfExists(); 195 if (caption && !caption->IsHidden()) { 196 iCapPlacement = caption->GetPlacementType(); 197 if (iCapPlacement == XFA_AttributeEnum::Top && GetPrev()) { 198 m_rtCaption.Reset(); 199 } else if (iCapPlacement == XFA_AttributeEnum::Bottom && GetNext()) { 200 m_rtCaption.Reset(); 201 } else { 202 fCapReserve = caption->GetReserve(); 203 CXFA_LayoutItem* pItem = this; 204 if (!pItem->GetPrev() && !pItem->GetNext()) { 205 m_rtCaption = rtWidget; 206 } else { 207 pItem = pItem->GetFirst(); 208 m_rtCaption = pItem->GetRect(false); 209 pItem = pItem->GetNext(); 210 while (pItem) { 211 m_rtCaption.height += pItem->GetRect(false).Height(); 212 pItem = pItem->GetNext(); 213 } 214 XFA_RectWithoutMargin(m_rtCaption, margin); 215 } 216 217 CXFA_TextLayout* pCapTextLayout = 218 m_pNode->GetWidgetAcc()->GetCaptionTextLayout(); 219 if (fCapReserve <= 0 && pCapTextLayout) { 220 CFX_SizeF minSize; 221 CFX_SizeF maxSize; 222 CFX_SizeF size = pCapTextLayout->CalcSize(minSize, maxSize); 223 if (iCapPlacement == XFA_AttributeEnum::Top || 224 iCapPlacement == XFA_AttributeEnum::Bottom) { 225 fCapReserve = size.height; 226 } else { 227 fCapReserve = size.width; 228 } 229 } 230 } 231 } 232 233 m_rtUI = rtWidget; 234 CXFA_Margin* capMargin = caption ? caption->GetMarginIfExists() : nullptr; 235 switch (iCapPlacement) { 236 case XFA_AttributeEnum::Left: { 237 m_rtCaption.width = fCapReserve; 238 CapLeftRightPlacement(capMargin, rtWidget, iCapPlacement); 239 m_rtUI.width -= fCapReserve; 240 m_rtUI.left += fCapReserve; 241 break; 242 } 243 case XFA_AttributeEnum::Top: { 244 m_rtCaption.height = fCapReserve; 245 CapTopBottomPlacement(capMargin, rtWidget, iCapPlacement); 246 m_rtUI.top += fCapReserve; 247 m_rtUI.height -= fCapReserve; 248 break; 249 } 250 case XFA_AttributeEnum::Right: { 251 m_rtCaption.left = m_rtCaption.right() - fCapReserve; 252 m_rtCaption.width = fCapReserve; 253 CapLeftRightPlacement(capMargin, rtWidget, iCapPlacement); 254 m_rtUI.width -= fCapReserve; 255 break; 256 } 257 case XFA_AttributeEnum::Bottom: { 258 m_rtCaption.top = m_rtCaption.bottom() - fCapReserve; 259 m_rtCaption.height = fCapReserve; 260 CapTopBottomPlacement(capMargin, rtWidget, iCapPlacement); 261 m_rtUI.height -= fCapReserve; 262 break; 263 } 264 case XFA_AttributeEnum::Inline: 265 break; 266 default: 267 break; 268 } 269 270 CXFA_Border* borderUI = m_pNode->GetWidgetAcc()->GetUIBorder(); 271 if (borderUI) { 272 CXFA_Margin* borderMargin = borderUI->GetMarginIfExists(); 273 if (borderMargin) 274 XFA_RectWithoutMargin(m_rtUI, borderMargin); 275 } 276 m_rtUI.Normalize(); 277 } 278 279 void CXFA_FFField::CapTopBottomPlacement(const CXFA_Margin* margin, 280 const CFX_RectF& rtWidget, 281 XFA_AttributeEnum iCapPlacement) { 282 CFX_RectF rtUIMargin = m_pNode->GetWidgetAcc()->GetUIMargin(); 283 m_rtCaption.left += rtUIMargin.left; 284 if (margin) { 285 XFA_RectWithoutMargin(m_rtCaption, margin); 286 if (m_rtCaption.height < 0) 287 m_rtCaption.top += m_rtCaption.height; 288 } 289 290 float fWidth = rtUIMargin.left + rtUIMargin.width; 291 float fHeight = m_rtCaption.height + rtUIMargin.top + rtUIMargin.height; 292 if (fWidth > rtWidget.width) 293 m_rtUI.width += fWidth - rtWidget.width; 294 295 if (fHeight == XFA_DEFAULTUI_HEIGHT && m_rtUI.height < XFA_MINUI_HEIGHT) { 296 m_rtUI.height = XFA_MINUI_HEIGHT; 297 m_rtCaption.top += rtUIMargin.top + rtUIMargin.height; 298 } else if (fHeight > rtWidget.height) { 299 m_rtUI.height += fHeight - rtWidget.height; 300 if (iCapPlacement == XFA_AttributeEnum::Bottom) 301 m_rtCaption.top += fHeight - rtWidget.height; 302 } 303 } 304 305 void CXFA_FFField::CapLeftRightPlacement(const CXFA_Margin* margin, 306 const CFX_RectF& rtWidget, 307 XFA_AttributeEnum iCapPlacement) { 308 CFX_RectF rtUIMargin = m_pNode->GetWidgetAcc()->GetUIMargin(); 309 m_rtCaption.top += rtUIMargin.top; 310 m_rtCaption.height -= rtUIMargin.top; 311 if (margin) { 312 XFA_RectWithoutMargin(m_rtCaption, margin); 313 if (m_rtCaption.height < 0) 314 m_rtCaption.top += m_rtCaption.height; 315 } 316 317 float fWidth = m_rtCaption.width + rtUIMargin.left + rtUIMargin.width; 318 float fHeight = rtUIMargin.top + rtUIMargin.height; 319 if (fWidth > rtWidget.width) { 320 m_rtUI.width += fWidth - rtWidget.width; 321 if (iCapPlacement == XFA_AttributeEnum::Right) 322 m_rtCaption.left += fWidth - rtWidget.width; 323 } 324 325 if (fHeight == XFA_DEFAULTUI_HEIGHT && m_rtUI.height < XFA_MINUI_HEIGHT) { 326 m_rtUI.height = XFA_MINUI_HEIGHT; 327 m_rtCaption.top += rtUIMargin.top + rtUIMargin.height; 328 } else if (fHeight > rtWidget.height) { 329 m_rtUI.height += fHeight - rtWidget.height; 330 } 331 } 332 333 void CXFA_FFField::UpdateFWL() { 334 if (m_pNormalWidget) 335 m_pNormalWidget->Update(); 336 } 337 338 uint32_t CXFA_FFField::UpdateUIProperty() { 339 CXFA_Node* pUiNode = m_pNode->GetWidgetAcc()->GetUIChild(); 340 if (pUiNode && pUiNode->GetElementType() == XFA_Element::DefaultUi) 341 return FWL_STYLEEXT_EDT_ReadOnly; 342 return 0; 343 } 344 345 void CXFA_FFField::SetFWLRect() { 346 if (!m_pNormalWidget) 347 return; 348 349 CFX_RectF rtUi = m_rtUI; 350 if (rtUi.width < 1.0) 351 rtUi.width = 1.0; 352 if (!GetDoc()->GetXFADoc()->IsInteractive()) { 353 float fFontSize = m_pNode->GetFontSize(); 354 if (rtUi.height < fFontSize) 355 rtUi.height = fFontSize; 356 } 357 m_pNormalWidget->SetWidgetRect(rtUi); 358 } 359 360 bool CXFA_FFField::OnMouseEnter() { 361 if (!m_pNormalWidget) 362 return false; 363 364 CFWL_MessageMouse ms(nullptr, m_pNormalWidget.get()); 365 ms.m_dwCmd = FWL_MouseCommand::Enter; 366 TranslateFWLMessage(&ms); 367 return true; 368 } 369 370 bool CXFA_FFField::OnMouseExit() { 371 if (!m_pNormalWidget) 372 return false; 373 374 CFWL_MessageMouse ms(nullptr, m_pNormalWidget.get()); 375 ms.m_dwCmd = FWL_MouseCommand::Leave; 376 TranslateFWLMessage(&ms); 377 return true; 378 } 379 380 CFX_PointF CXFA_FFField::FWLToClient(const CFX_PointF& point) { 381 return m_pNormalWidget ? point - m_pNormalWidget->GetWidgetRect().TopLeft() 382 : point; 383 } 384 385 bool CXFA_FFField::OnLButtonDown(uint32_t dwFlags, const CFX_PointF& point) { 386 if (!m_pNormalWidget) 387 return false; 388 if (!m_pNode->IsOpenAccess() || !GetDoc()->GetXFADoc()->IsInteractive()) 389 return false; 390 if (!PtInActiveRect(point)) 391 return false; 392 393 SetButtonDown(true); 394 CFWL_MessageMouse ms(nullptr, m_pNormalWidget.get()); 395 ms.m_dwCmd = FWL_MouseCommand::LeftButtonDown; 396 ms.m_dwFlags = dwFlags; 397 ms.m_pos = FWLToClient(point); 398 TranslateFWLMessage(&ms); 399 return true; 400 } 401 402 bool CXFA_FFField::OnLButtonUp(uint32_t dwFlags, const CFX_PointF& point) { 403 if (!m_pNormalWidget) 404 return false; 405 if (!IsButtonDown()) 406 return false; 407 408 SetButtonDown(false); 409 CFWL_MessageMouse ms(nullptr, m_pNormalWidget.get()); 410 ms.m_dwCmd = FWL_MouseCommand::LeftButtonUp; 411 ms.m_dwFlags = dwFlags; 412 ms.m_pos = FWLToClient(point); 413 TranslateFWLMessage(&ms); 414 return true; 415 } 416 417 bool CXFA_FFField::OnLButtonDblClk(uint32_t dwFlags, const CFX_PointF& point) { 418 if (!m_pNormalWidget) 419 return false; 420 421 CFWL_MessageMouse ms(nullptr, m_pNormalWidget.get()); 422 ms.m_dwCmd = FWL_MouseCommand::LeftButtonDblClk; 423 ms.m_dwFlags = dwFlags; 424 ms.m_pos = FWLToClient(point); 425 TranslateFWLMessage(&ms); 426 return true; 427 } 428 429 bool CXFA_FFField::OnMouseMove(uint32_t dwFlags, const CFX_PointF& point) { 430 if (!m_pNormalWidget) 431 return false; 432 433 CFWL_MessageMouse ms(nullptr, m_pNormalWidget.get()); 434 ms.m_dwCmd = FWL_MouseCommand::Move; 435 ms.m_dwFlags = dwFlags; 436 ms.m_pos = FWLToClient(point); 437 TranslateFWLMessage(&ms); 438 return true; 439 } 440 441 bool CXFA_FFField::OnMouseWheel(uint32_t dwFlags, 442 int16_t zDelta, 443 const CFX_PointF& point) { 444 if (!m_pNormalWidget) 445 return false; 446 447 CFWL_MessageMouseWheel ms(nullptr, m_pNormalWidget.get()); 448 ms.m_dwFlags = dwFlags; 449 ms.m_pos = FWLToClient(point); 450 ms.m_delta = CFX_PointF(zDelta, 0); 451 TranslateFWLMessage(&ms); 452 return true; 453 } 454 455 bool CXFA_FFField::OnRButtonDown(uint32_t dwFlags, const CFX_PointF& point) { 456 if (!m_pNormalWidget) 457 return false; 458 if (!m_pNode->IsOpenAccess() || !GetDoc()->GetXFADoc()->IsInteractive()) 459 return false; 460 if (!PtInActiveRect(point)) 461 return false; 462 463 SetButtonDown(true); 464 465 CFWL_MessageMouse ms(nullptr, m_pNormalWidget.get()); 466 ms.m_dwCmd = FWL_MouseCommand::RightButtonDown; 467 ms.m_dwFlags = dwFlags; 468 ms.m_pos = FWLToClient(point); 469 TranslateFWLMessage(&ms); 470 return true; 471 } 472 473 bool CXFA_FFField::OnRButtonUp(uint32_t dwFlags, const CFX_PointF& point) { 474 if (!m_pNormalWidget) 475 return false; 476 if (!IsButtonDown()) 477 return false; 478 479 SetButtonDown(false); 480 CFWL_MessageMouse ms(nullptr, m_pNormalWidget.get()); 481 ms.m_dwCmd = FWL_MouseCommand::RightButtonUp; 482 ms.m_dwFlags = dwFlags; 483 ms.m_pos = FWLToClient(point); 484 TranslateFWLMessage(&ms); 485 return true; 486 } 487 488 bool CXFA_FFField::OnRButtonDblClk(uint32_t dwFlags, const CFX_PointF& point) { 489 if (!m_pNormalWidget) 490 return false; 491 492 CFWL_MessageMouse ms(nullptr, m_pNormalWidget.get()); 493 ms.m_dwCmd = FWL_MouseCommand::RightButtonDblClk; 494 ms.m_dwFlags = dwFlags; 495 ms.m_pos = FWLToClient(point); 496 TranslateFWLMessage(&ms); 497 return true; 498 } 499 500 bool CXFA_FFField::OnSetFocus(CXFA_FFWidget* pOldWidget) { 501 CXFA_FFWidget::OnSetFocus(pOldWidget); 502 if (!m_pNormalWidget) 503 return false; 504 505 CFWL_MessageSetFocus ms(nullptr, m_pNormalWidget.get()); 506 TranslateFWLMessage(&ms); 507 m_dwStatus |= XFA_WidgetStatus_Focused; 508 AddInvalidateRect(); 509 return true; 510 } 511 512 bool CXFA_FFField::OnKillFocus(CXFA_FFWidget* pNewWidget) { 513 if (!m_pNormalWidget) 514 return CXFA_FFWidget::OnKillFocus(pNewWidget); 515 516 CFWL_MessageKillFocus ms(nullptr, m_pNormalWidget.get()); 517 TranslateFWLMessage(&ms); 518 m_dwStatus &= ~XFA_WidgetStatus_Focused; 519 AddInvalidateRect(); 520 CXFA_FFWidget::OnKillFocus(pNewWidget); 521 return true; 522 } 523 524 bool CXFA_FFField::OnKeyDown(uint32_t dwKeyCode, uint32_t dwFlags) { 525 if (!m_pNormalWidget || !GetDoc()->GetXFADoc()->IsInteractive()) 526 return false; 527 528 CFWL_MessageKey ms(nullptr, m_pNormalWidget.get()); 529 ms.m_dwCmd = FWL_KeyCommand::KeyDown; 530 ms.m_dwFlags = dwFlags; 531 ms.m_dwKeyCode = dwKeyCode; 532 TranslateFWLMessage(&ms); 533 return true; 534 } 535 536 bool CXFA_FFField::OnKeyUp(uint32_t dwKeyCode, uint32_t dwFlags) { 537 if (!m_pNormalWidget || !GetDoc()->GetXFADoc()->IsInteractive()) 538 return false; 539 540 CFWL_MessageKey ms(nullptr, m_pNormalWidget.get()); 541 ms.m_dwCmd = FWL_KeyCommand::KeyUp; 542 ms.m_dwFlags = dwFlags; 543 ms.m_dwKeyCode = dwKeyCode; 544 TranslateFWLMessage(&ms); 545 return true; 546 } 547 548 bool CXFA_FFField::OnChar(uint32_t dwChar, uint32_t dwFlags) { 549 if (!GetDoc()->GetXFADoc()->IsInteractive()) 550 return false; 551 if (dwChar == FWL_VKEY_Tab) 552 return true; 553 if (!m_pNormalWidget) 554 return false; 555 if (!m_pNode->IsOpenAccess()) 556 return false; 557 558 CFWL_MessageKey ms(nullptr, m_pNormalWidget.get()); 559 ms.m_dwCmd = FWL_KeyCommand::Char; 560 ms.m_dwFlags = dwFlags; 561 ms.m_dwKeyCode = dwChar; 562 TranslateFWLMessage(&ms); 563 return true; 564 } 565 566 FWL_WidgetHit CXFA_FFField::OnHitTest(const CFX_PointF& point) { 567 if (m_pNormalWidget && 568 m_pNormalWidget->HitTest(FWLToClient(point)) != FWL_WidgetHit::Unknown) { 569 return FWL_WidgetHit::Client; 570 } 571 572 if (!GetRectWithoutRotate().Contains(point)) 573 return FWL_WidgetHit::Unknown; 574 if (m_rtCaption.Contains(point)) 575 return FWL_WidgetHit::Titlebar; 576 return FWL_WidgetHit::Border; 577 } 578 579 bool CXFA_FFField::OnSetCursor(const CFX_PointF& point) { 580 return true; 581 } 582 583 bool CXFA_FFField::PtInActiveRect(const CFX_PointF& point) { 584 return m_pNormalWidget && m_pNormalWidget->GetWidgetRect().Contains(point); 585 } 586 587 void CXFA_FFField::LayoutCaption() { 588 CXFA_TextLayout* pCapTextLayout = 589 m_pNode->GetWidgetAcc()->GetCaptionTextLayout(); 590 if (!pCapTextLayout) 591 return; 592 593 float fHeight = 594 pCapTextLayout->Layout(CFX_SizeF(m_rtCaption.width, m_rtCaption.height)); 595 if (m_rtCaption.height < fHeight) 596 m_rtCaption.height = fHeight; 597 } 598 599 void CXFA_FFField::RenderCaption(CXFA_Graphics* pGS, CFX_Matrix* pMatrix) { 600 CXFA_TextLayout* pCapTextLayout = 601 m_pNode->GetWidgetAcc()->GetCaptionTextLayout(); 602 if (!pCapTextLayout) 603 return; 604 605 CXFA_Caption* caption = m_pNode->GetCaptionIfExists(); 606 if (!caption || !caption->IsVisible()) 607 return; 608 609 if (!pCapTextLayout->IsLoaded()) 610 pCapTextLayout->Layout(CFX_SizeF(m_rtCaption.width, m_rtCaption.height)); 611 612 CFX_RectF rtClip = m_rtCaption; 613 rtClip.Intersect(GetRectWithoutRotate()); 614 CFX_RenderDevice* pRenderDevice = pGS->GetRenderDevice(); 615 CFX_Matrix mt(1, 0, 0, 1, m_rtCaption.left, m_rtCaption.top); 616 if (pMatrix) { 617 rtClip = pMatrix->TransformRect(rtClip); 618 mt.Concat(*pMatrix); 619 } 620 pCapTextLayout->DrawString(pRenderDevice, mt, rtClip, 0); 621 } 622 623 bool CXFA_FFField::ProcessCommittedData() { 624 if (!m_pNode->IsOpenAccess()) 625 return false; 626 if (!IsDataChanged()) 627 return false; 628 if (CalculateOverride() != 1) 629 return false; 630 if (!CommitData()) 631 return false; 632 633 m_pDocView->SetChangeMark(); 634 m_pDocView->AddValidateWidget(m_pNode->GetWidgetAcc()); 635 return true; 636 } 637 638 int32_t CXFA_FFField::CalculateOverride() { 639 CXFA_Node* exclNode = m_pNode->GetExclGroupIfExists(); 640 if (!exclNode) 641 return CalculateWidgetAcc(m_pNode->GetWidgetAcc()); 642 643 CXFA_WidgetAcc* pAcc = exclNode->GetWidgetAcc(); 644 if (!pAcc) 645 return CalculateWidgetAcc(m_pNode->GetWidgetAcc()); 646 if (CalculateWidgetAcc(pAcc) == 0) 647 return 0; 648 649 CXFA_Node* pNode = pAcc->GetExclGroupFirstMember(); 650 if (!pNode) 651 return 1; 652 653 CXFA_WidgetAcc* pWidgetAcc = nullptr; 654 while (pNode) { 655 pWidgetAcc = pNode->GetWidgetAcc(); 656 if (!pWidgetAcc) 657 return 1; 658 if (CalculateWidgetAcc(pWidgetAcc) == 0) 659 return 0; 660 661 pNode = pWidgetAcc->GetExclGroupNextMember(pNode); 662 } 663 return 1; 664 } 665 666 int32_t CXFA_FFField::CalculateWidgetAcc(CXFA_WidgetAcc* pAcc) { 667 CXFA_Calculate* calc = pAcc->GetNode()->GetCalculateIfExists(); 668 if (!calc) 669 return 1; 670 671 XFA_VERSION version = GetDoc()->GetXFADoc()->GetCurVersionMode(); 672 switch (calc->GetOverride()) { 673 case XFA_AttributeEnum::Error: { 674 if (version <= XFA_VERSION_204) 675 return 1; 676 677 IXFA_AppProvider* pAppProvider = GetApp()->GetAppProvider(); 678 if (pAppProvider) { 679 pAppProvider->MsgBox(L"You are not allowed to modify this field.", 680 L"Calculate Override", XFA_MBICON_Warning, 681 XFA_MB_OK); 682 } 683 return 0; 684 } 685 case XFA_AttributeEnum::Warning: { 686 if (version <= XFA_VERSION_204) { 687 CXFA_Script* script = calc->GetScriptIfExists(); 688 if (!script) 689 return 1; 690 if (script->GetExpression().IsEmpty()) 691 return 1; 692 } 693 694 if (pAcc->GetNode()->IsUserInteractive()) 695 return 1; 696 697 IXFA_AppProvider* pAppProvider = GetApp()->GetAppProvider(); 698 if (!pAppProvider) 699 return 0; 700 701 WideString wsMessage = calc->GetMessageText(); 702 if (!wsMessage.IsEmpty()) 703 wsMessage += L"\r\n"; 704 705 wsMessage += L"Are you sure you want to modify this field?"; 706 if (pAppProvider->MsgBox(wsMessage, L"Calculate Override", 707 XFA_MBICON_Warning, XFA_MB_YesNo) == XFA_IDYes) { 708 pAcc->GetNode()->SetFlag(XFA_NodeFlag_UserInteractive, false); 709 return 1; 710 } 711 return 0; 712 } 713 case XFA_AttributeEnum::Ignore: 714 return 0; 715 case XFA_AttributeEnum::Disabled: 716 pAcc->GetNode()->SetFlag(XFA_NodeFlag_UserInteractive, false); 717 return 1; 718 default: 719 return 1; 720 } 721 } 722 723 bool CXFA_FFField::CommitData() { 724 return false; 725 } 726 727 bool CXFA_FFField::IsDataChanged() { 728 return false; 729 } 730 731 void CXFA_FFField::TranslateFWLMessage(CFWL_Message* pMessage) { 732 GetApp()->GetFWLWidgetMgr()->OnProcessMessageToForm(pMessage); 733 } 734 735 void CXFA_FFField::OnProcessMessage(CFWL_Message* pMessage) {} 736 737 void CXFA_FFField::OnProcessEvent(CFWL_Event* pEvent) { 738 switch (pEvent->GetType()) { 739 case CFWL_Event::Type::Mouse: { 740 CFWL_EventMouse* event = static_cast<CFWL_EventMouse*>(pEvent); 741 if (event->m_dwCmd == FWL_MouseCommand::Enter) { 742 CXFA_EventParam eParam; 743 eParam.m_eType = XFA_EVENT_MouseEnter; 744 eParam.m_pTarget = m_pNode->GetWidgetAcc(); 745 m_pNode->ProcessEvent(GetDocView(), XFA_AttributeEnum::MouseEnter, 746 &eParam); 747 } else if (event->m_dwCmd == FWL_MouseCommand::Leave) { 748 CXFA_EventParam eParam; 749 eParam.m_eType = XFA_EVENT_MouseExit; 750 eParam.m_pTarget = m_pNode->GetWidgetAcc(); 751 m_pNode->ProcessEvent(GetDocView(), XFA_AttributeEnum::MouseExit, 752 &eParam); 753 } else if (event->m_dwCmd == FWL_MouseCommand::LeftButtonDown) { 754 CXFA_EventParam eParam; 755 eParam.m_eType = XFA_EVENT_MouseDown; 756 eParam.m_pTarget = m_pNode->GetWidgetAcc(); 757 m_pNode->ProcessEvent(GetDocView(), XFA_AttributeEnum::MouseDown, 758 &eParam); 759 } else if (event->m_dwCmd == FWL_MouseCommand::LeftButtonUp) { 760 CXFA_EventParam eParam; 761 eParam.m_eType = XFA_EVENT_MouseUp; 762 eParam.m_pTarget = m_pNode->GetWidgetAcc(); 763 m_pNode->ProcessEvent(GetDocView(), XFA_AttributeEnum::MouseUp, 764 &eParam); 765 } 766 break; 767 } 768 case CFWL_Event::Type::Click: { 769 CXFA_EventParam eParam; 770 eParam.m_eType = XFA_EVENT_Click; 771 eParam.m_pTarget = m_pNode->GetWidgetAcc(); 772 m_pNode->ProcessEvent(GetDocView(), XFA_AttributeEnum::Click, &eParam); 773 break; 774 } 775 default: 776 break; 777 } 778 } 779 780 void CXFA_FFField::OnDrawWidget(CXFA_Graphics* pGraphics, 781 const CFX_Matrix& matrix) {} 782