| // Copyright 2014 The PDFium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com |
| |
| #include "xfa/fxfa/cxfa_ffwidgethandler.h" |
| |
| #include "fxjs/xfa/cjx_object.h" |
| #include "xfa/fxfa/cxfa_ffdoc.h" |
| #include "xfa/fxfa/cxfa_ffdocview.h" |
| #include "xfa/fxfa/cxfa_fffield.h" |
| #include "xfa/fxfa/cxfa_ffwidget.h" |
| #include "xfa/fxfa/cxfa_fwladapterwidgetmgr.h" |
| #include "xfa/fxfa/layout/cxfa_layoutprocessor.h" |
| #include "xfa/fxfa/parser/cxfa_calculate.h" |
| #include "xfa/fxfa/parser/cxfa_checkbutton.h" |
| #include "xfa/fxfa/parser/cxfa_measurement.h" |
| #include "xfa/fxfa/parser/cxfa_node.h" |
| #include "xfa/fxfa/parser/cxfa_ui.h" |
| #include "xfa/fxfa/parser/cxfa_validate.h" |
| |
| CXFA_FFWidgetHandler::CXFA_FFWidgetHandler(CXFA_FFDocView* pDocView) |
| : m_pDocView(pDocView) {} |
| |
| CXFA_FFWidgetHandler::~CXFA_FFWidgetHandler() = default; |
| |
| void CXFA_FFWidgetHandler::Trace(cppgc::Visitor* visitor) const { |
| visitor->Trace(m_pDocView); |
| } |
| |
| bool CXFA_FFWidgetHandler::OnMouseEnter(CXFA_FFWidget* hWidget) { |
| CXFA_FFDocView::UpdateScope scope(m_pDocView); |
| return hWidget->OnMouseEnter(); |
| } |
| |
| bool CXFA_FFWidgetHandler::OnMouseExit(CXFA_FFWidget* hWidget) { |
| CXFA_FFDocView::UpdateScope scope(m_pDocView); |
| return hWidget->OnMouseExit(); |
| } |
| |
| bool CXFA_FFWidgetHandler::OnLButtonDown(CXFA_FFWidget* hWidget, |
| Mask<XFA_FWL_KeyFlag> dwFlags, |
| const CFX_PointF& point) { |
| CXFA_FFDocView::UpdateScope scope(m_pDocView); |
| if (!hWidget->AcceptsFocusOnButtonDown( |
| dwFlags, hWidget->Rotate2Normal(point), |
| CFWL_MessageMouse::MouseCommand::kLeftButtonDown)) { |
| return false; |
| } |
| // May re-enter JS. |
| if (m_pDocView->SetFocus(hWidget)) |
| m_pDocView->GetDoc()->SetFocusWidget(hWidget); |
| |
| return hWidget->OnLButtonDown(dwFlags, hWidget->Rotate2Normal(point)); |
| } |
| |
| bool CXFA_FFWidgetHandler::OnLButtonUp(CXFA_FFWidget* hWidget, |
| Mask<XFA_FWL_KeyFlag> dwFlags, |
| const CFX_PointF& point) { |
| CXFA_FFDocView::UpdateScope scope(m_pDocView); |
| m_pDocView->SetLayoutEvent(); |
| return hWidget->OnLButtonUp(dwFlags, hWidget->Rotate2Normal(point)); |
| } |
| |
| bool CXFA_FFWidgetHandler::OnLButtonDblClk(CXFA_FFWidget* hWidget, |
| Mask<XFA_FWL_KeyFlag> dwFlags, |
| const CFX_PointF& point) { |
| return hWidget->OnLButtonDblClk(dwFlags, hWidget->Rotate2Normal(point)); |
| } |
| |
| bool CXFA_FFWidgetHandler::OnMouseMove(CXFA_FFWidget* hWidget, |
| Mask<XFA_FWL_KeyFlag> dwFlags, |
| const CFX_PointF& point) { |
| return hWidget->OnMouseMove(dwFlags, hWidget->Rotate2Normal(point)); |
| } |
| |
| bool CXFA_FFWidgetHandler::OnMouseWheel(CXFA_FFWidget* hWidget, |
| Mask<XFA_FWL_KeyFlag> dwFlags, |
| const CFX_PointF& point, |
| const CFX_Vector& delta) { |
| return hWidget->OnMouseWheel(dwFlags, hWidget->Rotate2Normal(point), delta); |
| } |
| |
| bool CXFA_FFWidgetHandler::OnRButtonDown(CXFA_FFWidget* hWidget, |
| Mask<XFA_FWL_KeyFlag> dwFlags, |
| const CFX_PointF& point) { |
| if (!hWidget->AcceptsFocusOnButtonDown( |
| dwFlags, hWidget->Rotate2Normal(point), |
| CFWL_MessageMouse::MouseCommand::kRightButtonDown)) { |
| return false; |
| } |
| // May re-enter JS. |
| if (m_pDocView->SetFocus(hWidget)) { |
| m_pDocView->GetDoc()->SetFocusWidget(hWidget); |
| } |
| return hWidget->OnRButtonDown(dwFlags, hWidget->Rotate2Normal(point)); |
| } |
| |
| bool CXFA_FFWidgetHandler::OnRButtonUp(CXFA_FFWidget* hWidget, |
| Mask<XFA_FWL_KeyFlag> dwFlags, |
| const CFX_PointF& point) { |
| return hWidget->OnRButtonUp(dwFlags, hWidget->Rotate2Normal(point)); |
| } |
| |
| bool CXFA_FFWidgetHandler::OnRButtonDblClk(CXFA_FFWidget* hWidget, |
| Mask<XFA_FWL_KeyFlag> dwFlags, |
| const CFX_PointF& point) { |
| return hWidget->OnRButtonDblClk(dwFlags, hWidget->Rotate2Normal(point)); |
| } |
| |
| bool CXFA_FFWidgetHandler::OnKeyDown(CXFA_FFWidget* hWidget, |
| XFA_FWL_VKEYCODE dwKeyCode, |
| Mask<XFA_FWL_KeyFlag> dwFlags) { |
| bool bRet = hWidget->OnKeyDown(dwKeyCode, dwFlags); |
| m_pDocView->UpdateDocView(); |
| return bRet; |
| } |
| |
| bool CXFA_FFWidgetHandler::OnChar(CXFA_FFWidget* hWidget, |
| uint32_t dwChar, |
| Mask<XFA_FWL_KeyFlag> dwFlags) { |
| return hWidget->OnChar(dwChar, dwFlags); |
| } |
| |
| WideString CXFA_FFWidgetHandler::GetText(CXFA_FFWidget* widget) { |
| return widget->GetText(); |
| } |
| |
| WideString CXFA_FFWidgetHandler::GetSelectedText(CXFA_FFWidget* widget) { |
| if (!widget->CanCopy()) |
| return WideString(); |
| |
| return widget->Copy().value_or(WideString()); |
| } |
| |
| void CXFA_FFWidgetHandler::PasteText(CXFA_FFWidget* widget, |
| const WideString& text) { |
| if (!widget->CanPaste()) |
| return; |
| |
| widget->Paste(text); |
| } |
| |
| bool CXFA_FFWidgetHandler::SelectAllText(CXFA_FFWidget* widget) { |
| if (!widget->CanSelectAll()) |
| return false; |
| |
| widget->SelectAll(); |
| return true; |
| } |
| |
| bool CXFA_FFWidgetHandler::CanUndo(CXFA_FFWidget* widget) { |
| return widget->CanUndo(); |
| } |
| |
| bool CXFA_FFWidgetHandler::CanRedo(CXFA_FFWidget* widget) { |
| return widget->CanRedo(); |
| } |
| |
| bool CXFA_FFWidgetHandler::Undo(CXFA_FFWidget* widget) { |
| return widget->Undo(); |
| } |
| |
| bool CXFA_FFWidgetHandler::Redo(CXFA_FFWidget* widget) { |
| return widget->Redo(); |
| } |
| |
| FWL_WidgetHit CXFA_FFWidgetHandler::HitTest(CXFA_FFWidget* pWidget, |
| const CFX_PointF& point) { |
| if (!pWidget->GetLayoutItem()->TestStatusBits(XFA_WidgetStatus::kVisible)) |
| return FWL_WidgetHit::Unknown; |
| return pWidget->HitTest(pWidget->Rotate2Normal(point)); |
| } |
| |
| void CXFA_FFWidgetHandler::RenderWidget(CXFA_FFWidget* hWidget, |
| CFGAS_GEGraphics* pGS, |
| const CFX_Matrix& matrix, |
| bool bHighlight) { |
| hWidget->RenderWidget( |
| pGS, matrix, |
| bHighlight ? CXFA_FFWidget::kHighlight : CXFA_FFWidget::kNoHighlight); |
| } |
| |
| bool CXFA_FFWidgetHandler::HasEvent(CXFA_Node* pNode, |
| XFA_EVENTTYPE eEventType) { |
| if (eEventType == XFA_EVENT_Unknown) |
| return false; |
| if (!pNode || pNode->GetElementType() == XFA_Element::Draw) |
| return false; |
| |
| switch (eEventType) { |
| case XFA_EVENT_Calculate: { |
| CXFA_Calculate* calc = pNode->GetCalculateIfExists(); |
| return calc && calc->GetScriptIfExists(); |
| } |
| case XFA_EVENT_Validate: { |
| CXFA_Validate* validate = pNode->GetValidateIfExists(); |
| return validate && validate->GetScriptIfExists(); |
| } |
| default: |
| break; |
| } |
| return !pNode->GetEventByActivity(kXFAEventActivity[eEventType], false) |
| .empty(); |
| } |
| |
| XFA_EventError CXFA_FFWidgetHandler::ProcessEvent(CXFA_Node* pNode, |
| CXFA_EventParam* pParam) { |
| if (!pParam || pParam->m_eType == XFA_EVENT_Unknown) |
| return XFA_EventError::kNotExist; |
| if (!pNode || pNode->GetElementType() == XFA_Element::Draw) |
| return XFA_EventError::kNotExist; |
| |
| switch (pParam->m_eType) { |
| case XFA_EVENT_Calculate: |
| return pNode->ProcessCalculate(m_pDocView.Get()); |
| case XFA_EVENT_Validate: |
| if (m_pDocView->GetDoc()->IsValidationsEnabled()) |
| return pNode->ProcessValidate(m_pDocView.Get(), 0); |
| return XFA_EventError::kDisabled; |
| case XFA_EVENT_InitCalculate: { |
| CXFA_Calculate* calc = pNode->GetCalculateIfExists(); |
| if (!calc) |
| return XFA_EventError::kNotExist; |
| if (pNode->IsUserInteractive()) |
| return XFA_EventError::kDisabled; |
| return pNode->ExecuteScript(m_pDocView.Get(), calc->GetScriptIfExists(), |
| pParam); |
| } |
| default: |
| break; |
| } |
| return pNode->ProcessEvent(m_pDocView.Get(), |
| kXFAEventActivity[pParam->m_eType], pParam); |
| } |