Home | History | Annotate | Download | only in app
      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