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