• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2014 PDFium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6 
7 #include "xfa/fxfa/app/xfa_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 
CXFA_FFField(CXFA_WidgetAcc * pDataAcc)28 CXFA_FFField::CXFA_FFField(CXFA_WidgetAcc* pDataAcc)
29     : CXFA_FFWidget(pDataAcc), m_pNormalWidget(nullptr) {}
30 
~CXFA_FFField()31 CXFA_FFField::~CXFA_FFField() {
32   CXFA_FFField::UnloadWidget();
33 }
34 
GetBBox(uint32_t dwStatus,bool bDrawFocus)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 
RenderWidget(CFX_Graphics * pGS,CFX_Matrix * pMatrix,uint32_t dwStatus)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 }
DrawHighlight(CFX_Graphics * pGS,CFX_Matrix * pMatrix,uint32_t dwStatus,bool bEllipse)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 }
DrawFocus(CFX_Graphics * pGS,CFX_Matrix * pMatrix)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 }
SetFWLThemeProvider()106 void CXFA_FFField::SetFWLThemeProvider() {
107   if (m_pNormalWidget)
108     m_pNormalWidget->SetThemeProvider(GetApp()->GetFWLTheme());
109 }
IsLoaded()110 bool CXFA_FFField::IsLoaded() {
111   return m_pNormalWidget && CXFA_FFWidget::IsLoaded();
112 }
LoadWidget()113 bool CXFA_FFField::LoadWidget() {
114   SetFWLThemeProvider();
115   m_pDataAcc->LoadCaption();
116   PerformLayout();
117   return true;
118 }
UnloadWidget()119 void CXFA_FFField::UnloadWidget() {
120   delete m_pNormalWidget;
121   m_pNormalWidget = nullptr;
122 }
SetEditScrollOffset()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 }
PerformLayout()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 }
CapPlacement()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 }
CapTopBottomPlacement(CXFA_Caption caption,const CFX_RectF & rtWidget,int32_t iCapPlacement)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 }
CapLeftRightPlacement(CXFA_Caption caption,const CFX_RectF & rtWidget,int32_t iCapPlacement)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 }
UpdateFWL()305 void CXFA_FFField::UpdateFWL() {
306   if (m_pNormalWidget) {
307     m_pNormalWidget->Update();
308   }
309 }
UpdateUIProperty()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 }
SetFWLRect()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 }
OnMouseEnter()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 }
OnMouseExit()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 
FWLToClient(const CFX_PointF & point)352 CFX_PointF CXFA_FFField::FWLToClient(const CFX_PointF& point) {
353   return m_pNormalWidget ? point - m_pNormalWidget->GetWidgetRect().TopLeft()
354                          : point;
355 }
356 
OnLButtonDown(uint32_t dwFlags,const CFX_PointF & point)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 
OnLButtonUp(uint32_t dwFlags,const CFX_PointF & point)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 
OnLButtonDblClk(uint32_t dwFlags,const CFX_PointF & point)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 
OnMouseMove(uint32_t dwFlags,const CFX_PointF & point)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 
OnMouseWheel(uint32_t dwFlags,int16_t zDelta,const CFX_PointF & point)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 
OnRButtonDown(uint32_t dwFlags,const CFX_PointF & point)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 
OnRButtonUp(uint32_t dwFlags,const CFX_PointF & point)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 
OnRButtonDblClk(uint32_t dwFlags,const CFX_PointF & point)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 
OnSetFocus(CXFA_FFWidget * pOldWidget)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 }
OnKillFocus(CXFA_FFWidget * pNewWidget)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 }
OnKeyDown(uint32_t dwKeyCode,uint32_t dwFlags)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 }
OnKeyUp(uint32_t dwKeyCode,uint32_t dwFlags)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 }
OnChar(uint32_t dwChar,uint32_t dwFlags)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 }
OnHitTest(const CFX_PointF & point)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 
OnSetCursor(const CFX_PointF & point)553 bool CXFA_FFField::OnSetCursor(const CFX_PointF& point) {
554   return true;
555 }
556 
PtInActiveRect(const CFX_PointF & point)557 bool CXFA_FFField::PtInActiveRect(const CFX_PointF& point) {
558   return m_pNormalWidget && m_pNormalWidget->GetWidgetRect().Contains(point);
559 }
560 
LayoutCaption()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 
RenderCaption(CFX_Graphics * pGS,CFX_Matrix * pMatrix)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 
ProcessCommittedData()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 
CalculateOverride()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 }
CalculateWidgetAcc(CXFA_WidgetAcc * pAcc)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 }
CommitData()698 bool CXFA_FFField::CommitData() {
699   return false;
700 }
IsDataChanged()701 bool CXFA_FFField::IsDataChanged() {
702   return false;
703 }
TranslateFWLMessage(CFWL_Message * pMessage)704 void CXFA_FFField::TranslateFWLMessage(CFWL_Message* pMessage) {
705   GetApp()->GetWidgetMgrDelegate()->OnProcessMessageToForm(pMessage);
706 }
OnProcessMessage(CFWL_Message * pMessage)707 void CXFA_FFField::OnProcessMessage(CFWL_Message* pMessage) {}
708 
OnProcessEvent(CFWL_Event * pEvent)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 
OnDrawWidget(CFX_Graphics * pGraphics,const CFX_Matrix * pMatrix)748 void CXFA_FFField::OnDrawWidget(CFX_Graphics* pGraphics,
749                                 const CFX_Matrix* pMatrix) {}
750