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_ffwidgethandler.h"
8
9#include <vector>
10
11#include "fxjs/xfa/cjx_object.h"
12#include "xfa/fxfa/cxfa_ffdoc.h"
13#include "xfa/fxfa/cxfa_ffdocview.h"
14#include "xfa/fxfa/cxfa_fffield.h"
15#include "xfa/fxfa/cxfa_ffwidget.h"
16#include "xfa/fxfa/cxfa_fwladapterwidgetmgr.h"
17#include "xfa/fxfa/parser/cxfa_calculate.h"
18#include "xfa/fxfa/parser/cxfa_checkbutton.h"
19#include "xfa/fxfa/parser/cxfa_layoutprocessor.h"
20#include "xfa/fxfa/parser/cxfa_measurement.h"
21#include "xfa/fxfa/parser/cxfa_node.h"
22#include "xfa/fxfa/parser/cxfa_ui.h"
23#include "xfa/fxfa/parser/cxfa_validate.h"
24
25CXFA_FFWidgetHandler::CXFA_FFWidgetHandler(CXFA_FFDocView* pDocView)
26    : m_pDocView(pDocView) {}
27
28CXFA_FFWidgetHandler::~CXFA_FFWidgetHandler() {}
29
30bool CXFA_FFWidgetHandler::OnMouseEnter(CXFA_FFWidget* hWidget) {
31  m_pDocView->LockUpdate();
32  bool bRet = hWidget->OnMouseEnter();
33  m_pDocView->UnlockUpdate();
34  m_pDocView->UpdateDocView();
35  return bRet;
36}
37
38bool CXFA_FFWidgetHandler::OnMouseExit(CXFA_FFWidget* hWidget) {
39  m_pDocView->LockUpdate();
40  bool bRet = hWidget->OnMouseExit();
41  m_pDocView->UnlockUpdate();
42  m_pDocView->UpdateDocView();
43  return bRet;
44}
45
46bool CXFA_FFWidgetHandler::OnLButtonDown(CXFA_FFWidget* hWidget,
47                                         uint32_t dwFlags,
48                                         const CFX_PointF& point) {
49  m_pDocView->LockUpdate();
50  bool bRet = hWidget->OnLButtonDown(dwFlags, hWidget->Rotate2Normal(point));
51  if (bRet && m_pDocView->SetFocus(hWidget)) {
52    m_pDocView->GetDoc()->GetDocEnvironment()->SetFocusWidget(
53        m_pDocView->GetDoc(), hWidget);
54  }
55  m_pDocView->UnlockUpdate();
56  m_pDocView->UpdateDocView();
57  return bRet;
58}
59
60bool CXFA_FFWidgetHandler::OnLButtonUp(CXFA_FFWidget* hWidget,
61                                       uint32_t dwFlags,
62                                       const CFX_PointF& point) {
63  m_pDocView->LockUpdate();
64  m_pDocView->m_bLayoutEvent = true;
65  bool bRet = hWidget->OnLButtonUp(dwFlags, hWidget->Rotate2Normal(point));
66  m_pDocView->UnlockUpdate();
67  m_pDocView->UpdateDocView();
68  return bRet;
69}
70
71bool CXFA_FFWidgetHandler::OnLButtonDblClk(CXFA_FFWidget* hWidget,
72                                           uint32_t dwFlags,
73                                           const CFX_PointF& point) {
74  bool bRet = hWidget->OnLButtonDblClk(dwFlags, hWidget->Rotate2Normal(point));
75  m_pDocView->RunInvalidate();
76  return bRet;
77}
78
79bool CXFA_FFWidgetHandler::OnMouseMove(CXFA_FFWidget* hWidget,
80                                       uint32_t dwFlags,
81                                       const CFX_PointF& point) {
82  bool bRet = hWidget->OnMouseMove(dwFlags, hWidget->Rotate2Normal(point));
83  m_pDocView->RunInvalidate();
84  return bRet;
85}
86
87bool CXFA_FFWidgetHandler::OnMouseWheel(CXFA_FFWidget* hWidget,
88                                        uint32_t dwFlags,
89                                        int16_t zDelta,
90                                        const CFX_PointF& point) {
91  bool bRet =
92      hWidget->OnMouseWheel(dwFlags, zDelta, hWidget->Rotate2Normal(point));
93  m_pDocView->RunInvalidate();
94  return bRet;
95}
96
97bool CXFA_FFWidgetHandler::OnRButtonDown(CXFA_FFWidget* hWidget,
98                                         uint32_t dwFlags,
99                                         const CFX_PointF& point) {
100  bool bRet = hWidget->OnRButtonDown(dwFlags, hWidget->Rotate2Normal(point));
101  if (bRet && m_pDocView->SetFocus(hWidget)) {
102    m_pDocView->GetDoc()->GetDocEnvironment()->SetFocusWidget(
103        m_pDocView->GetDoc(), hWidget);
104  }
105  m_pDocView->RunInvalidate();
106  return bRet;
107}
108
109bool CXFA_FFWidgetHandler::OnRButtonUp(CXFA_FFWidget* hWidget,
110                                       uint32_t dwFlags,
111                                       const CFX_PointF& point) {
112  bool bRet = hWidget->OnRButtonUp(dwFlags, hWidget->Rotate2Normal(point));
113  m_pDocView->RunInvalidate();
114  return bRet;
115}
116
117bool CXFA_FFWidgetHandler::OnRButtonDblClk(CXFA_FFWidget* hWidget,
118                                           uint32_t dwFlags,
119                                           const CFX_PointF& point) {
120  bool bRet = hWidget->OnRButtonDblClk(dwFlags, hWidget->Rotate2Normal(point));
121  m_pDocView->RunInvalidate();
122  return bRet;
123}
124
125bool CXFA_FFWidgetHandler::OnKeyDown(CXFA_FFWidget* hWidget,
126                                     uint32_t dwKeyCode,
127                                     uint32_t dwFlags) {
128  bool bRet = hWidget->OnKeyDown(dwKeyCode, dwFlags);
129  m_pDocView->RunInvalidate();
130  m_pDocView->UpdateDocView();
131  return bRet;
132}
133
134bool CXFA_FFWidgetHandler::OnKeyUp(CXFA_FFWidget* hWidget,
135                                   uint32_t dwKeyCode,
136                                   uint32_t dwFlags) {
137  bool bRet = hWidget->OnKeyUp(dwKeyCode, dwFlags);
138  m_pDocView->RunInvalidate();
139  return bRet;
140}
141
142bool CXFA_FFWidgetHandler::OnChar(CXFA_FFWidget* hWidget,
143                                  uint32_t dwChar,
144                                  uint32_t dwFlags) {
145  bool bRet = hWidget->OnChar(dwChar, dwFlags);
146  m_pDocView->RunInvalidate();
147  return bRet;
148}
149
150WideString CXFA_FFWidgetHandler::GetSelectedText(CXFA_FFWidget* widget) {
151  if (!widget->CanCopy())
152    return WideString();
153
154  return widget->Copy().value_or(WideString());
155}
156
157void CXFA_FFWidgetHandler::PasteText(CXFA_FFWidget* widget,
158                                     const WideString& text) {
159  if (!widget->CanPaste())
160    return;
161
162  widget->Paste(text);
163}
164
165FWL_WidgetHit CXFA_FFWidgetHandler::OnHitTest(CXFA_FFWidget* hWidget,
166                                              const CFX_PointF& point) {
167  if (!(hWidget->GetStatus() & XFA_WidgetStatus_Visible))
168    return FWL_WidgetHit::Unknown;
169  return hWidget->OnHitTest(hWidget->Rotate2Normal(point));
170}
171
172bool CXFA_FFWidgetHandler::OnSetCursor(CXFA_FFWidget* hWidget,
173                                       const CFX_PointF& point) {
174  return hWidget->OnSetCursor(hWidget->Rotate2Normal(point));
175}
176
177void CXFA_FFWidgetHandler::RenderWidget(CXFA_FFWidget* hWidget,
178                                        CXFA_Graphics* pGS,
179                                        const CFX_Matrix& matrix,
180                                        bool bHighlight) {
181  hWidget->RenderWidget(pGS, matrix,
182                        bHighlight ? XFA_WidgetStatus_Highlight : 0);
183}
184
185bool CXFA_FFWidgetHandler::HasEvent(CXFA_WidgetAcc* pWidgetAcc,
186                                    XFA_EVENTTYPE eEventType) {
187  if (eEventType == XFA_EVENT_Unknown)
188    return false;
189  if (!pWidgetAcc)
190    return false;
191
192  CXFA_Node* node = pWidgetAcc->GetNode();
193  if (!node || node->GetElementType() == XFA_Element::Draw)
194    return false;
195
196  switch (eEventType) {
197    case XFA_EVENT_Calculate: {
198      CXFA_Calculate* calc = node->GetCalculateIfExists();
199      return calc && calc->GetScriptIfExists();
200    }
201    case XFA_EVENT_Validate: {
202      CXFA_Validate* validate = node->GetValidateIfExists();
203      return validate && validate->GetScriptIfExists();
204    }
205    default:
206      break;
207  }
208  return !pWidgetAcc->GetEventByActivity(gs_EventActivity[eEventType], false)
209              .empty();
210}
211
212int32_t CXFA_FFWidgetHandler::ProcessEvent(CXFA_WidgetAcc* pWidgetAcc,
213                                           CXFA_EventParam* pParam) {
214  if (!pParam || pParam->m_eType == XFA_EVENT_Unknown)
215    return XFA_EVENTERROR_NotExist;
216  if (!pWidgetAcc)
217    return XFA_EVENTERROR_NotExist;
218
219  CXFA_Node* node = pWidgetAcc->GetNode();
220  if (!node || node->GetElementType() == XFA_Element::Draw)
221    return XFA_EVENTERROR_NotExist;
222
223  switch (pParam->m_eType) {
224    case XFA_EVENT_Calculate:
225      return node->ProcessCalculate(m_pDocView);
226    case XFA_EVENT_Validate:
227      if (m_pDocView->GetDoc()->GetDocEnvironment()->IsValidationsEnabled(
228              m_pDocView->GetDoc())) {
229        return node->ProcessValidate(m_pDocView, 0);
230      }
231      return XFA_EVENTERROR_Disabled;
232    case XFA_EVENT_InitCalculate: {
233      CXFA_Calculate* calc = node->GetCalculateIfExists();
234      if (!calc)
235        return XFA_EVENTERROR_NotExist;
236      if (node->IsUserInteractive())
237        return XFA_EVENTERROR_Disabled;
238      return node->ExecuteScript(m_pDocView, calc->GetScriptIfExists(), pParam);
239    }
240    default:
241      break;
242  }
243  int32_t iRet =
244      node->ProcessEvent(m_pDocView, gs_EventActivity[pParam->m_eType], pParam);
245  return iRet;
246}
247
248CXFA_FFWidget* CXFA_FFWidgetHandler::CreateWidget(CXFA_FFWidget* hParent,
249                                                  XFA_WIDGETTYPE eType,
250                                                  CXFA_FFWidget* hBefore) {
251  CXFA_Node* pParentFormItem = hParent ? hParent->GetNode() : nullptr;
252  CXFA_Node* pBeforeFormItem = hBefore ? hBefore->GetNode() : nullptr;
253  CXFA_Node* pNewFormItem =
254      CreateWidgetFormItem(eType, pParentFormItem, pBeforeFormItem);
255  if (!pNewFormItem)
256    return nullptr;
257
258  CXFA_Node* templateNode = pNewFormItem->GetTemplateNodeIfExists();
259  if (!templateNode)
260    return nullptr;
261
262  templateNode->SetFlag(XFA_NodeFlag_Initialized, true);
263  pNewFormItem->SetFlag(XFA_NodeFlag_Initialized, true);
264  m_pDocView->RunLayout();
265  CXFA_LayoutItem* pLayout =
266      m_pDocView->GetXFALayout()->GetLayoutItem(pNewFormItem);
267  return static_cast<CXFA_FFWidget*>(pLayout);
268}
269
270CXFA_Node* CXFA_FFWidgetHandler::CreateWidgetFormItem(
271    XFA_WIDGETTYPE eType,
272    CXFA_Node* pParent,
273    CXFA_Node* pBefore) const {
274  switch (eType) {
275    case XFA_WIDGETTYPE_Barcode:
276      return nullptr;
277    case XFA_WIDGETTYPE_PushButton:
278      return CreatePushButton(pParent, pBefore);
279    case XFA_WIDGETTYPE_CheckButton:
280      return CreateCheckButton(pParent, pBefore);
281    case XFA_WIDGETTYPE_ExcludeGroup:
282      return CreateExclGroup(pParent, pBefore);
283    case XFA_WIDGETTYPE_RadioButton:
284      return CreateRadioButton(pParent, pBefore);
285    case XFA_WIDGETTYPE_Arc:
286      return CreateArc(pParent, pBefore);
287    case XFA_WIDGETTYPE_Rectangle:
288      return CreateRectangle(pParent, pBefore);
289    case XFA_WIDGETTYPE_Image:
290      return CreateImage(pParent, pBefore);
291    case XFA_WIDGETTYPE_Line:
292      return CreateLine(pParent, pBefore);
293    case XFA_WIDGETTYPE_Text:
294      return CreateText(pParent, pBefore);
295    case XFA_WIDGETTYPE_DatetimeEdit:
296      return CreateDatetimeEdit(pParent, pBefore);
297    case XFA_WIDGETTYPE_DecimalField:
298      return CreateDecimalField(pParent, pBefore);
299    case XFA_WIDGETTYPE_NumericField:
300      return CreateNumericField(pParent, pBefore);
301    case XFA_WIDGETTYPE_Signature:
302      return CreateSignature(pParent, pBefore);
303    case XFA_WIDGETTYPE_TextEdit:
304      return CreateTextEdit(pParent, pBefore);
305    case XFA_WIDGETTYPE_DropdownList:
306      return CreateDropdownList(pParent, pBefore);
307    case XFA_WIDGETTYPE_ListBox:
308      return CreateListBox(pParent, pBefore);
309    case XFA_WIDGETTYPE_ImageField:
310      return CreateImageField(pParent, pBefore);
311    case XFA_WIDGETTYPE_PasswordEdit:
312      return CreatePasswordEdit(pParent, pBefore);
313    case XFA_WIDGETTYPE_Subform:
314      return CreateSubform(pParent, pBefore);
315    default:
316      return nullptr;
317  }
318}
319
320CXFA_Node* CXFA_FFWidgetHandler::CreatePushButton(CXFA_Node* pParent,
321                                                  CXFA_Node* pBefore) const {
322  CXFA_Node* pField = CreateField(XFA_Element::Button, pParent, pBefore);
323  CXFA_Node* pCaption = CreateCopyNode(XFA_Element::Caption, pField);
324  CXFA_Node* pValue = CreateCopyNode(XFA_Element::Value, pCaption);
325  CXFA_Node* pText = CreateCopyNode(XFA_Element::Text, pValue);
326  pText->JSObject()->SetContent(L"Button", L"Button", false, false, true);
327
328  CXFA_Node* pPara = CreateCopyNode(XFA_Element::Para, pCaption);
329  pPara->JSObject()->SetEnum(XFA_Attribute::VAlign, XFA_AttributeEnum::Middle,
330                             false);
331  pPara->JSObject()->SetEnum(XFA_Attribute::HAlign, XFA_AttributeEnum::Center,
332                             false);
333  CreateFontNode(pCaption);
334
335  CXFA_Node* pBorder = CreateCopyNode(XFA_Element::Border, pField);
336  pBorder->JSObject()->SetEnum(XFA_Attribute::Hand, XFA_AttributeEnum::Right,
337                               false);
338
339  CXFA_Node* pEdge = CreateCopyNode(XFA_Element::Edge, pBorder);
340  pEdge->JSObject()->SetEnum(XFA_Attribute::Stroke, XFA_AttributeEnum::Raised,
341                             false);
342
343  CXFA_Node* pFill = CreateCopyNode(XFA_Element::Fill, pBorder);
344  CXFA_Node* pColor = CreateCopyNode(XFA_Element::Color, pFill);
345  pColor->JSObject()->SetCData(XFA_Attribute::Value, L"212, 208, 200", false,
346                               false);
347
348  CXFA_Node* pBind = CreateCopyNode(XFA_Element::Bind, pField);
349  pBind->JSObject()->SetEnum(XFA_Attribute::Match, XFA_AttributeEnum::None,
350                             false);
351
352  return pField;
353}
354
355CXFA_Node* CXFA_FFWidgetHandler::CreateCheckButton(CXFA_Node* pParent,
356                                                   CXFA_Node* pBefore) const {
357  return CreateField(XFA_Element::CheckButton, pParent, pBefore);
358}
359
360CXFA_Node* CXFA_FFWidgetHandler::CreateExclGroup(CXFA_Node* pParent,
361                                                 CXFA_Node* pBefore) const {
362  return CreateFormItem(XFA_Element::ExclGroup, pParent, pBefore);
363}
364
365CXFA_Node* CXFA_FFWidgetHandler::CreateRadioButton(CXFA_Node* pParent,
366                                                   CXFA_Node* pBefore) const {
367  CXFA_Node* pField = CreateField(XFA_Element::CheckButton, pParent, pBefore);
368  CXFA_Ui* pUi = pField->GetFirstChildByClass<CXFA_Ui>(XFA_Element::Ui);
369  CXFA_CheckButton* pWidget =
370      pUi->GetFirstChildByClass<CXFA_CheckButton>(XFA_Element::CheckButton);
371  pWidget->JSObject()->SetEnum(XFA_Attribute::Shape, XFA_AttributeEnum::Round,
372                               false);
373  return pField;
374}
375
376CXFA_Node* CXFA_FFWidgetHandler::CreateDatetimeEdit(CXFA_Node* pParent,
377                                                    CXFA_Node* pBefore) const {
378  CXFA_Node* pField = CreateField(XFA_Element::DateTimeEdit, pParent, pBefore);
379  CreateValueNode(XFA_Element::Date, pField);
380  return pField;
381}
382
383CXFA_Node* CXFA_FFWidgetHandler::CreateDecimalField(CXFA_Node* pParent,
384                                                    CXFA_Node* pBefore) const {
385  CXFA_Node* pField = CreateNumericField(pParent, pBefore);
386  CreateValueNode(XFA_Element::Decimal, pField);
387  return pField;
388}
389
390CXFA_Node* CXFA_FFWidgetHandler::CreateNumericField(CXFA_Node* pParent,
391                                                    CXFA_Node* pBefore) const {
392  return CreateField(XFA_Element::NumericEdit, pParent, pBefore);
393}
394
395CXFA_Node* CXFA_FFWidgetHandler::CreateSignature(CXFA_Node* pParent,
396                                                 CXFA_Node* pBefore) const {
397  return CreateField(XFA_Element::Signature, pParent, pBefore);
398}
399
400CXFA_Node* CXFA_FFWidgetHandler::CreateTextEdit(CXFA_Node* pParent,
401                                                CXFA_Node* pBefore) const {
402  return CreateField(XFA_Element::TextEdit, pParent, pBefore);
403}
404
405CXFA_Node* CXFA_FFWidgetHandler::CreateDropdownList(CXFA_Node* pParent,
406                                                    CXFA_Node* pBefore) const {
407  return CreateField(XFA_Element::ChoiceList, pParent, pBefore);
408}
409
410CXFA_Node* CXFA_FFWidgetHandler::CreateListBox(CXFA_Node* pParent,
411                                               CXFA_Node* pBefore) const {
412  CXFA_Node* pField = CreateDropdownList(pParent, pBefore);
413  CXFA_Node* pUi = pField->GetFirstChild();
414  CXFA_Node* pListBox = pUi->GetFirstChild();
415  pListBox->JSObject()->SetEnum(XFA_Attribute::Open, XFA_AttributeEnum::Always,
416                                false);
417  pListBox->JSObject()->SetEnum(XFA_Attribute::CommitOn,
418                                XFA_AttributeEnum::Exit, false);
419  return pField;
420}
421
422CXFA_Node* CXFA_FFWidgetHandler::CreateImageField(CXFA_Node* pParent,
423                                                  CXFA_Node* pBefore) const {
424  return CreateField(XFA_Element::ImageEdit, pParent, pBefore);
425}
426
427CXFA_Node* CXFA_FFWidgetHandler::CreatePasswordEdit(CXFA_Node* pParent,
428                                                    CXFA_Node* pBefore) const {
429  CXFA_Node* pField = CreateField(XFA_Element::PasswordEdit, pParent, pBefore);
430  CXFA_Node* pBind = CreateCopyNode(XFA_Element::Bind, pField);
431  pBind->JSObject()->SetEnum(XFA_Attribute::Match, XFA_AttributeEnum::None,
432                             false);
433  return pField;
434}
435
436CXFA_Node* CXFA_FFWidgetHandler::CreateField(XFA_Element eElement,
437                                             CXFA_Node* pParent,
438                                             CXFA_Node* pBefore) const {
439  CXFA_Node* pField = CreateFormItem(XFA_Element::Field, pParent, pBefore);
440  CreateCopyNode(eElement, CreateCopyNode(XFA_Element::Ui, pField));
441  CreateFontNode(pField);
442  return pField;
443}
444
445CXFA_Node* CXFA_FFWidgetHandler::CreateArc(CXFA_Node* pParent,
446                                           CXFA_Node* pBefore) const {
447  return CreateDraw(XFA_Element::Arc, pParent, pBefore);
448}
449
450CXFA_Node* CXFA_FFWidgetHandler::CreateRectangle(CXFA_Node* pParent,
451                                                 CXFA_Node* pBefore) const {
452  return CreateDraw(XFA_Element::Rectangle, pParent, pBefore);
453}
454
455CXFA_Node* CXFA_FFWidgetHandler::CreateImage(CXFA_Node* pParent,
456                                             CXFA_Node* pBefore) const {
457  CXFA_Node* pField = CreateDraw(XFA_Element::Image, pParent, pBefore);
458  CreateCopyNode(XFA_Element::ImageEdit,
459                 CreateCopyNode(XFA_Element::Ui, pField));
460  return pField;
461}
462
463CXFA_Node* CXFA_FFWidgetHandler::CreateLine(CXFA_Node* pParent,
464                                            CXFA_Node* pBefore) const {
465  return CreateDraw(XFA_Element::Line, pParent, pBefore);
466}
467
468CXFA_Node* CXFA_FFWidgetHandler::CreateText(CXFA_Node* pParent,
469                                            CXFA_Node* pBefore) const {
470  CXFA_Node* pField = CreateDraw(XFA_Element::Text, pParent, pBefore);
471  CreateCopyNode(XFA_Element::TextEdit,
472                 CreateCopyNode(XFA_Element::Ui, pField));
473  CreateFontNode(pField);
474  return pField;
475}
476
477CXFA_Node* CXFA_FFWidgetHandler::CreateDraw(XFA_Element eElement,
478                                            CXFA_Node* pParent,
479                                            CXFA_Node* pBefore) const {
480  CXFA_Node* pDraw = CreateFormItem(XFA_Element::Draw, pParent, pBefore);
481  CreateValueNode(eElement, pDraw);
482  return pDraw;
483}
484
485CXFA_Node* CXFA_FFWidgetHandler::CreateSubform(CXFA_Node* pParent,
486                                               CXFA_Node* pBefore) const {
487  return CreateFormItem(XFA_Element::Subform, pParent, pBefore);
488}
489
490CXFA_Node* CXFA_FFWidgetHandler::CreateFormItem(XFA_Element eElement,
491                                                CXFA_Node* pParent,
492                                                CXFA_Node* pBefore) const {
493  if (!pParent)
494    return nullptr;
495
496  CXFA_Node* pTemplateParent = pParent->GetTemplateNodeIfExists();
497  if (!pTemplateParent)
498    return nullptr;
499
500  CXFA_Node* pNewFormItem = pTemplateParent->CloneTemplateToForm(false);
501  if (pParent)
502    pParent->InsertChild(pNewFormItem, pBefore);
503  return pNewFormItem;
504}
505
506CXFA_Node* CXFA_FFWidgetHandler::CreateCopyNode(XFA_Element eElement,
507                                                CXFA_Node* pParent,
508                                                CXFA_Node* pBefore) const {
509  if (!pParent)
510    return nullptr;
511
512  CXFA_Node* pTemplateParent = pParent->GetTemplateNodeIfExists();
513  CXFA_Node* pNewNode =
514      CreateTemplateNode(eElement, pTemplateParent,
515                         pBefore ? pBefore->GetTemplateNodeIfExists() : nullptr)
516          ->Clone(false);
517  if (pParent)
518    pParent->InsertChild(pNewNode, pBefore);
519  return pNewNode;
520}
521
522CXFA_Node* CXFA_FFWidgetHandler::CreateTemplateNode(XFA_Element eElement,
523                                                    CXFA_Node* pParent,
524                                                    CXFA_Node* pBefore) const {
525  CXFA_Document* pXFADoc = GetXFADoc();
526  CXFA_Node* pNewTemplateNode =
527      pXFADoc->CreateNode(XFA_PacketType::Template, eElement);
528  if (pParent)
529    pParent->InsertChild(pNewTemplateNode, pBefore);
530  return pNewTemplateNode;
531}
532
533CXFA_Node* CXFA_FFWidgetHandler::CreateFontNode(CXFA_Node* pParent) const {
534  CXFA_Node* pFont = CreateCopyNode(XFA_Element::Font, pParent);
535  pFont->JSObject()->SetCData(XFA_Attribute::Typeface, L"Myriad Pro", false,
536                              false);
537  return pFont;
538}
539
540CXFA_Node* CXFA_FFWidgetHandler::CreateMarginNode(CXFA_Node* pParent,
541                                                  uint32_t dwFlags,
542                                                  float fInsets[4]) const {
543  CXFA_Node* pMargin = CreateCopyNode(XFA_Element::Margin, pParent);
544  if (dwFlags & 0x01)
545    pMargin->JSObject()->SetMeasure(XFA_Attribute::LeftInset,
546                                    CXFA_Measurement(fInsets[0], XFA_Unit::Pt),
547                                    false);
548  if (dwFlags & 0x02)
549    pMargin->JSObject()->SetMeasure(XFA_Attribute::TopInset,
550                                    CXFA_Measurement(fInsets[1], XFA_Unit::Pt),
551                                    false);
552  if (dwFlags & 0x04)
553    pMargin->JSObject()->SetMeasure(XFA_Attribute::RightInset,
554                                    CXFA_Measurement(fInsets[2], XFA_Unit::Pt),
555                                    false);
556  if (dwFlags & 0x08)
557    pMargin->JSObject()->SetMeasure(XFA_Attribute::BottomInset,
558                                    CXFA_Measurement(fInsets[3], XFA_Unit::Pt),
559                                    false);
560  return pMargin;
561}
562
563CXFA_Node* CXFA_FFWidgetHandler::CreateValueNode(XFA_Element eValue,
564                                                 CXFA_Node* pParent) const {
565  CXFA_Node* pValue = CreateCopyNode(XFA_Element::Value, pParent);
566  CreateCopyNode(eValue, pValue);
567  return pValue;
568}
569
570CXFA_Document* CXFA_FFWidgetHandler::GetObjFactory() const {
571  return GetXFADoc();
572}
573
574CXFA_Document* CXFA_FFWidgetHandler::GetXFADoc() const {
575  return m_pDocView->GetDoc()->GetXFADoc();
576}
577