| // Copyright 2014 PDFium Authors. All rights reserved. | |
| // 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_ffwidget.h" | |
| #include <algorithm> | |
| #include <cmath> | |
| #include <memory> | |
| #include <utility> | |
| #include "core/fxcodec/fx_codec.h" | |
| #include "core/fxcodec/progressive_decoder.h" | |
| #include "core/fxcrt/maybe_owned.h" | |
| #include "core/fxge/cfx_fillrenderoptions.h" | |
| #include "core/fxge/cfx_pathdata.h" | |
| #include "core/fxge/cfx_renderdevice.h" | |
| #include "core/fxge/dib/cfx_dibitmap.h" | |
| #include "xfa/fwl/fwl_widgethit.h" | |
| #include "xfa/fxfa/cxfa_eventparam.h" | |
| #include "xfa/fxfa/cxfa_ffapp.h" | |
| #include "xfa/fxfa/cxfa_ffdoc.h" | |
| #include "xfa/fxfa/cxfa_ffdocview.h" | |
| #include "xfa/fxfa/cxfa_ffpageview.h" | |
| #include "xfa/fxfa/cxfa_ffwidgethandler.h" | |
| #include "xfa/fxfa/cxfa_imagerenderer.h" | |
| #include "xfa/fxfa/layout/cxfa_layoutprocessor.h" | |
| #include "xfa/fxfa/parser/cxfa_border.h" | |
| #include "xfa/fxfa/parser/cxfa_box.h" | |
| #include "xfa/fxfa/parser/cxfa_edge.h" | |
| #include "xfa/fxfa/parser/cxfa_image.h" | |
| #include "xfa/fxfa/parser/cxfa_margin.h" | |
| #include "xfa/fxfa/parser/cxfa_node.h" | |
| #include "xfa/fxgraphics/cxfa_graphics.h" | |
| namespace { | |
| FXDIB_Format XFA_GetDIBFormat(FXCODEC_IMAGE_TYPE type, | |
| int32_t iComponents, | |
| int32_t iBitsPerComponent) { | |
| FXDIB_Format dibFormat = FXDIB_Argb; | |
| switch (type) { | |
| case FXCODEC_IMAGE_JPG: | |
| #ifdef PDF_ENABLE_XFA_BMP | |
| case FXCODEC_IMAGE_BMP: | |
| #endif // PDF_ENABLE_XFA_BMP | |
| #ifdef PDF_ENABLE_XFA_TIFF | |
| case FXCODEC_IMAGE_TIFF: | |
| #endif // PDF_ENABLE_XFA_TIFF | |
| { | |
| dibFormat = FXDIB_Rgb32; | |
| int32_t bpp = iComponents * iBitsPerComponent; | |
| if (bpp <= 24) { | |
| dibFormat = FXDIB_Rgb; | |
| } | |
| } break; | |
| #ifdef PDF_ENABLE_XFA_PNG | |
| case FXCODEC_IMAGE_PNG: | |
| #endif // PDF_ENABLE_XFA_PNG | |
| default: | |
| break; | |
| } | |
| return dibFormat; | |
| } | |
| bool IsFXCodecErrorStatus(FXCODEC_STATUS status) { | |
| return (status == FXCODEC_STATUS_ERROR || | |
| status == FXCODEC_STATUS_ERR_MEMORY || | |
| status == FXCODEC_STATUS_ERR_READ || | |
| status == FXCODEC_STATUS_ERR_FLUSH || | |
| status == FXCODEC_STATUS_ERR_FORMAT || | |
| status == FXCODEC_STATUS_ERR_PARAMS); | |
| } | |
| } // namespace | |
| void XFA_DrawImage(CXFA_Graphics* pGS, | |
| const CFX_RectF& rtImage, | |
| const CFX_Matrix& matrix, | |
| const RetainPtr<CFX_DIBitmap>& pDIBitmap, | |
| XFA_AttributeValue iAspect, | |
| const CFX_Size& dpi, | |
| XFA_AttributeValue iHorzAlign, | |
| XFA_AttributeValue iVertAlign) { | |
| if (rtImage.IsEmpty()) | |
| return; | |
| if (!pDIBitmap || !pDIBitmap->GetBuffer()) | |
| return; | |
| CFX_RectF rtFit(rtImage.TopLeft(), | |
| XFA_UnitPx2Pt(pDIBitmap->GetWidth(), dpi.width), | |
| XFA_UnitPx2Pt(pDIBitmap->GetHeight(), dpi.height)); | |
| switch (iAspect) { | |
| case XFA_AttributeValue::Fit: { | |
| float f1 = rtImage.height / rtFit.height; | |
| float f2 = rtImage.width / rtFit.width; | |
| f1 = std::min(f1, f2); | |
| rtFit.height = rtFit.height * f1; | |
| rtFit.width = rtFit.width * f1; | |
| break; | |
| } | |
| case XFA_AttributeValue::Height: { | |
| float f1 = rtImage.height / rtFit.height; | |
| rtFit.height = rtImage.height; | |
| rtFit.width = f1 * rtFit.width; | |
| break; | |
| } | |
| case XFA_AttributeValue::None: | |
| rtFit.height = rtImage.height; | |
| rtFit.width = rtImage.width; | |
| break; | |
| case XFA_AttributeValue::Width: { | |
| float f1 = rtImage.width / rtFit.width; | |
| rtFit.width = rtImage.width; | |
| rtFit.height = rtFit.height * f1; | |
| break; | |
| } | |
| case XFA_AttributeValue::Actual: | |
| default: | |
| break; | |
| } | |
| if (iHorzAlign == XFA_AttributeValue::Center) | |
| rtFit.left += (rtImage.width - rtFit.width) / 2; | |
| else if (iHorzAlign == XFA_AttributeValue::Right) | |
| rtFit.left = rtImage.right() - rtFit.width; | |
| if (iVertAlign == XFA_AttributeValue::Middle) | |
| rtFit.top += (rtImage.height - rtFit.height) / 2; | |
| else if (iVertAlign == XFA_AttributeValue::Bottom) | |
| rtFit.top = rtImage.bottom() - rtImage.height; | |
| CFX_RenderDevice* pRenderDevice = pGS->GetRenderDevice(); | |
| CFX_RenderDevice::StateRestorer restorer(pRenderDevice); | |
| CFX_PathData path; | |
| path.AppendRect(rtImage.left, rtImage.bottom(), rtImage.right(), rtImage.top); | |
| pRenderDevice->SetClip_PathFill(&path, &matrix, | |
| CFX_FillRenderOptions::WindingOptions()); | |
| CFX_Matrix mtImage(1, 0, 0, -1, 0, 1); | |
| mtImage.Concat( | |
| CFX_Matrix(rtFit.width, 0, 0, rtFit.height, rtFit.left, rtFit.top)); | |
| mtImage.Concat(matrix); | |
| CXFA_ImageRenderer imageRender(pRenderDevice, pDIBitmap, &mtImage); | |
| if (!imageRender.Start()) { | |
| return; | |
| } | |
| while (imageRender.Continue()) | |
| continue; | |
| } | |
| RetainPtr<CFX_DIBitmap> XFA_LoadImageFromBuffer( | |
| const RetainPtr<IFX_SeekableReadStream>& pImageFileRead, | |
| FXCODEC_IMAGE_TYPE type, | |
| int32_t& iImageXDpi, | |
| int32_t& iImageYDpi) { | |
| auto pProgressiveDecoder = std::make_unique<ProgressiveDecoder>(); | |
| CFX_DIBAttribute dibAttr; | |
| pProgressiveDecoder->LoadImageInfo(pImageFileRead, type, &dibAttr, false); | |
| switch (dibAttr.m_wDPIUnit) { | |
| case FXCODEC_RESUNIT_CENTIMETER: | |
| dibAttr.m_nXDPI = (int32_t)(dibAttr.m_nXDPI * 2.54f); | |
| dibAttr.m_nYDPI = (int32_t)(dibAttr.m_nYDPI * 2.54f); | |
| break; | |
| case FXCODEC_RESUNIT_METER: | |
| dibAttr.m_nXDPI = (int32_t)(dibAttr.m_nXDPI / (float)100 * 2.54f); | |
| dibAttr.m_nYDPI = (int32_t)(dibAttr.m_nYDPI / (float)100 * 2.54f); | |
| break; | |
| default: | |
| break; | |
| } | |
| iImageXDpi = dibAttr.m_nXDPI > 1 ? dibAttr.m_nXDPI : (96); | |
| iImageYDpi = dibAttr.m_nYDPI > 1 ? dibAttr.m_nYDPI : (96); | |
| if (pProgressiveDecoder->GetWidth() <= 0 || | |
| pProgressiveDecoder->GetHeight() <= 0) { | |
| return nullptr; | |
| } | |
| type = pProgressiveDecoder->GetType(); | |
| int32_t iComponents = pProgressiveDecoder->GetNumComponents(); | |
| int32_t iBpc = pProgressiveDecoder->GetBPC(); | |
| FXDIB_Format dibFormat = XFA_GetDIBFormat(type, iComponents, iBpc); | |
| RetainPtr<CFX_DIBitmap> pBitmap = pdfium::MakeRetain<CFX_DIBitmap>(); | |
| pBitmap->Create(pProgressiveDecoder->GetWidth(), | |
| pProgressiveDecoder->GetHeight(), dibFormat); | |
| pBitmap->Clear(0xffffffff); | |
| size_t nFrames; | |
| FXCODEC_STATUS status; | |
| std::tie(status, nFrames) = pProgressiveDecoder->GetFrames(); | |
| if (status != FXCODEC_STATUS_DECODE_READY || nFrames == 0) | |
| return nullptr; | |
| status = pProgressiveDecoder->StartDecode(pBitmap, 0, 0, pBitmap->GetWidth(), | |
| pBitmap->GetHeight()); | |
| if (IsFXCodecErrorStatus(status)) | |
| return nullptr; | |
| while (status == FXCODEC_STATUS_DECODE_TOBECONTINUE) { | |
| status = pProgressiveDecoder->ContinueDecode(); | |
| if (IsFXCodecErrorStatus(status)) | |
| return nullptr; | |
| } | |
| return pBitmap; | |
| } | |
| void XFA_RectWithoutMargin(CFX_RectF* rt, const CXFA_Margin* margin) { | |
| if (!margin) | |
| return; | |
| rt->Deflate(margin->GetLeftInset(), margin->GetTopInset(), | |
| margin->GetRightInset(), margin->GetBottomInset()); | |
| } | |
| CXFA_FFWidget* XFA_GetWidgetFromLayoutItem(CXFA_LayoutItem* pLayoutItem) { | |
| if (!pLayoutItem->GetFormNode()->HasCreatedUIWidget()) | |
| return nullptr; | |
| return GetFFWidget(ToContentLayoutItem(pLayoutItem)); | |
| } | |
| CXFA_FFWidget::CXFA_FFWidget(CXFA_Node* node) : m_pNode(node) {} | |
| CXFA_FFWidget::~CXFA_FFWidget() = default; | |
| void CXFA_FFWidget::PreFinalize() {} | |
| void CXFA_FFWidget::Trace(cppgc::Visitor* visitor) const { | |
| visitor->Trace(m_pLayoutItem); | |
| visitor->Trace(m_pDocView); | |
| visitor->Trace(m_pPageView); | |
| visitor->Trace(m_pNode); | |
| } | |
| CFWL_App* CXFA_FFWidget::GetFWLApp() const { | |
| return GetPageView()->GetDocView()->GetDoc()->GetApp()->GetFWLApp(); | |
| } | |
| CXFA_FFWidget* CXFA_FFWidget::GetNextFFWidget() const { | |
| return GetFFWidget(GetLayoutItem()->GetNext()); | |
| } | |
| const CFX_RectF& CXFA_FFWidget::GetWidgetRect() const { | |
| if (!GetLayoutItem()->TestStatusBits(XFA_WidgetStatus_RectCached)) | |
| RecacheWidgetRect(); | |
| return m_WidgetRect; | |
| } | |
| const CFX_RectF& CXFA_FFWidget::RecacheWidgetRect() const { | |
| GetLayoutItem()->SetStatusBits(XFA_WidgetStatus_RectCached); | |
| m_WidgetRect = GetLayoutItem()->GetRect(false); | |
| return m_WidgetRect; | |
| } | |
| CFX_RectF CXFA_FFWidget::GetRectWithoutRotate() { | |
| CFX_RectF rtWidget = GetWidgetRect(); | |
| float fValue = 0; | |
| switch (m_pNode->GetRotate()) { | |
| case 90: | |
| rtWidget.top = rtWidget.bottom(); | |
| fValue = rtWidget.width; | |
| rtWidget.width = rtWidget.height; | |
| rtWidget.height = fValue; | |
| break; | |
| case 180: | |
| rtWidget.left = rtWidget.right(); | |
| rtWidget.top = rtWidget.bottom(); | |
| break; | |
| case 270: | |
| rtWidget.left = rtWidget.right(); | |
| fValue = rtWidget.width; | |
| rtWidget.width = rtWidget.height; | |
| rtWidget.height = fValue; | |
| break; | |
| } | |
| return rtWidget; | |
| } | |
| void CXFA_FFWidget::ModifyStatus(uint32_t dwAdded, uint32_t dwRemoved) { | |
| GetLayoutItem()->ClearStatusBits(dwRemoved); | |
| GetLayoutItem()->SetStatusBits(dwAdded); | |
| } | |
| CXFA_FFField* CXFA_FFWidget::AsField() { | |
| return nullptr; | |
| } | |
| CFX_RectF CXFA_FFWidget::GetBBox(FocusOption focus) { | |
| if (focus == kDrawFocus || !m_pPageView) | |
| return CFX_RectF(); | |
| return m_pPageView->GetPageViewRect(); | |
| } | |
| void CXFA_FFWidget::RenderWidget(CXFA_Graphics* pGS, | |
| const CFX_Matrix& matrix, | |
| HighlightOption highlight) { | |
| if (!HasVisibleStatus()) | |
| return; | |
| CXFA_Border* border = m_pNode->GetBorderIfExists(); | |
| if (!border) | |
| return; | |
| CFX_RectF rtBorder = GetRectWithoutRotate(); | |
| CXFA_Margin* margin = border->GetMarginIfExists(); | |
| XFA_RectWithoutMargin(&rtBorder, margin); | |
| rtBorder.Normalize(); | |
| DrawBorder(pGS, border, rtBorder, matrix); | |
| } | |
| bool CXFA_FFWidget::IsLoaded() { | |
| return !!m_pPageView; | |
| } | |
| bool CXFA_FFWidget::LoadWidget() { | |
| PerformLayout(); | |
| return true; | |
| } | |
| bool CXFA_FFWidget::PerformLayout() { | |
| RecacheWidgetRect(); | |
| return true; | |
| } | |
| bool CXFA_FFWidget::UpdateFWLData() { | |
| return false; | |
| } | |
| void CXFA_FFWidget::UpdateWidgetProperty() {} | |
| bool CXFA_FFWidget::HasEventUnderHandler(XFA_EVENTTYPE eEventType, | |
| CXFA_FFWidgetHandler* pHandler) { | |
| CXFA_Node* pNode = GetNode(); | |
| return pNode->IsWidgetReady() && pHandler->HasEvent(pNode, eEventType); | |
| } | |
| bool CXFA_FFWidget::ProcessEventUnderHandler(CXFA_EventParam* params, | |
| CXFA_FFWidgetHandler* pHandler) { | |
| CXFA_Node* pNode = GetNode(); | |
| if (!pNode->IsWidgetReady()) | |
| return false; | |
| params->m_pTarget = pNode; | |
| return pHandler->ProcessEvent(pNode, params) == XFA_EventError::kSuccess; | |
| } | |
| void CXFA_FFWidget::DrawBorder(CXFA_Graphics* pGS, | |
| CXFA_Box* box, | |
| const CFX_RectF& rtBorder, | |
| const CFX_Matrix& matrix) { | |
| if (box) | |
| box->Draw(pGS, rtBorder, matrix, false); | |
| } | |
| void CXFA_FFWidget::DrawBorderWithFlag(CXFA_Graphics* pGS, | |
| CXFA_Box* box, | |
| const CFX_RectF& rtBorder, | |
| const CFX_Matrix& matrix, | |
| bool forceRound) { | |
| if (box) | |
| box->Draw(pGS, rtBorder, matrix, forceRound); | |
| } | |
| void CXFA_FFWidget::InvalidateRect() { | |
| CFX_RectF rtWidget = GetBBox(kDoNotDrawFocus); | |
| rtWidget.Inflate(2, 2); | |
| m_pDocView->InvalidateRect(m_pPageView.Get(), rtWidget); | |
| } | |
| bool CXFA_FFWidget::OnMouseEnter() { | |
| return false; | |
| } | |
| bool CXFA_FFWidget::OnMouseExit() { | |
| return false; | |
| } | |
| bool CXFA_FFWidget::AcceptsFocusOnButtonDown(uint32_t dwFlags, | |
| const CFX_PointF& point, | |
| FWL_MouseCommand command) { | |
| return false; | |
| } | |
| bool CXFA_FFWidget::OnLButtonDown(uint32_t dwFlags, const CFX_PointF& point) { | |
| return false; | |
| } | |
| bool CXFA_FFWidget::OnLButtonUp(uint32_t dwFlags, const CFX_PointF& point) { | |
| return false; | |
| } | |
| bool CXFA_FFWidget::OnLButtonDblClk(uint32_t dwFlags, const CFX_PointF& point) { | |
| return false; | |
| } | |
| bool CXFA_FFWidget::OnMouseMove(uint32_t dwFlags, const CFX_PointF& point) { | |
| return false; | |
| } | |
| bool CXFA_FFWidget::OnMouseWheel(uint32_t dwFlags, | |
| const CFX_PointF& point, | |
| const CFX_Vector& delta) { | |
| return false; | |
| } | |
| bool CXFA_FFWidget::OnRButtonDown(uint32_t dwFlags, const CFX_PointF& point) { | |
| return false; | |
| } | |
| bool CXFA_FFWidget::OnRButtonUp(uint32_t dwFlags, const CFX_PointF& point) { | |
| return false; | |
| } | |
| bool CXFA_FFWidget::OnRButtonDblClk(uint32_t dwFlags, const CFX_PointF& point) { | |
| return false; | |
| } | |
| bool CXFA_FFWidget::OnSetFocus(CXFA_FFWidget* pOldWidget) { | |
| CXFA_FFWidget* pParent = GetFFWidget(ToContentLayoutItem(GetParent())); | |
| if (pParent && !pParent->IsAncestorOf(pOldWidget)) { | |
| if (!pParent->OnSetFocus(pOldWidget)) | |
| return false; | |
| } | |
| GetLayoutItem()->SetStatusBits(XFA_WidgetStatus_Focused); | |
| CXFA_EventParam eParam; | |
| eParam.m_eType = XFA_EVENT_Enter; | |
| eParam.m_pTarget = m_pNode.Get(); | |
| m_pNode->ProcessEvent(GetDocView(), XFA_AttributeValue::Enter, &eParam); | |
| return true; | |
| } | |
| bool CXFA_FFWidget::OnKillFocus(CXFA_FFWidget* pNewWidget) { | |
| GetLayoutItem()->ClearStatusBits(XFA_WidgetStatus_Focused); | |
| EventKillFocus(); | |
| if (!pNewWidget) | |
| return true; | |
| CXFA_FFWidget* pParent = GetFFWidget(ToContentLayoutItem(GetParent())); | |
| if (pParent && !pParent->IsAncestorOf(pNewWidget)) { | |
| if (!pParent->OnKillFocus(pNewWidget)) | |
| return false; | |
| } | |
| return true; | |
| } | |
| bool CXFA_FFWidget::OnKeyDown(uint32_t dwKeyCode, uint32_t dwFlags) { | |
| return false; | |
| } | |
| bool CXFA_FFWidget::OnKeyUp(uint32_t dwKeyCode, uint32_t dwFlags) { | |
| return false; | |
| } | |
| bool CXFA_FFWidget::OnChar(uint32_t dwChar, uint32_t dwFlags) { | |
| return false; | |
| } | |
| FWL_WidgetHit CXFA_FFWidget::HitTest(const CFX_PointF& point) { | |
| return FWL_WidgetHit::Unknown; | |
| } | |
| bool CXFA_FFWidget::CanUndo() { | |
| return false; | |
| } | |
| bool CXFA_FFWidget::CanRedo() { | |
| return false; | |
| } | |
| bool CXFA_FFWidget::CanCopy() { | |
| return false; | |
| } | |
| bool CXFA_FFWidget::CanCut() { | |
| return false; | |
| } | |
| bool CXFA_FFWidget::CanPaste() { | |
| return false; | |
| } | |
| bool CXFA_FFWidget::CanSelectAll() { | |
| return false; | |
| } | |
| bool CXFA_FFWidget::CanDelete() { | |
| return CanCut(); | |
| } | |
| bool CXFA_FFWidget::CanDeSelect() { | |
| return CanCopy(); | |
| } | |
| bool CXFA_FFWidget::Undo() { | |
| return false; | |
| } | |
| bool CXFA_FFWidget::Redo() { | |
| return false; | |
| } | |
| Optional<WideString> CXFA_FFWidget::Copy() { | |
| return {}; | |
| } | |
| Optional<WideString> CXFA_FFWidget::Cut() { | |
| return {}; | |
| } | |
| bool CXFA_FFWidget::Paste(const WideString& wsPaste) { | |
| return false; | |
| } | |
| void CXFA_FFWidget::SelectAll() {} | |
| void CXFA_FFWidget::Delete() {} | |
| void CXFA_FFWidget::DeSelect() {} | |
| WideString CXFA_FFWidget::GetText() { | |
| return WideString(); | |
| } | |
| FormFieldType CXFA_FFWidget::GetFormFieldType() { | |
| return FormFieldType::kXFA; | |
| } | |
| CFX_PointF CXFA_FFWidget::Rotate2Normal(const CFX_PointF& point) { | |
| CFX_Matrix mt = GetRotateMatrix(); | |
| if (mt.IsIdentity()) | |
| return point; | |
| return mt.GetInverse().Transform(point); | |
| } | |
| CFX_Matrix CXFA_FFWidget::GetRotateMatrix() { | |
| int32_t iRotate = m_pNode->GetRotate(); | |
| if (!iRotate) | |
| return CFX_Matrix(); | |
| CFX_RectF rcWidget = GetRectWithoutRotate(); | |
| CFX_Matrix mt; | |
| switch (iRotate) { | |
| case 90: | |
| mt.a = 0; | |
| mt.b = -1; | |
| mt.c = 1; | |
| mt.d = 0; | |
| mt.e = rcWidget.left - rcWidget.top; | |
| mt.f = rcWidget.left + rcWidget.top; | |
| break; | |
| case 180: | |
| mt.a = -1; | |
| mt.b = 0; | |
| mt.c = 0; | |
| mt.d = -1; | |
| mt.e = rcWidget.left * 2; | |
| mt.f = rcWidget.top * 2; | |
| break; | |
| case 270: | |
| mt.a = 0; | |
| mt.b = 1; | |
| mt.c = -1; | |
| mt.d = 0; | |
| mt.e = rcWidget.left + rcWidget.top; | |
| mt.f = rcWidget.top - rcWidget.left; | |
| break; | |
| } | |
| return mt; | |
| } | |
| void CXFA_FFWidget::DisplayCaret(bool bVisible, const CFX_RectF* pRtAnchor) { | |
| GetDoc()->DisplayCaret(this, bVisible, pRtAnchor); | |
| } | |
| void CXFA_FFWidget::GetBorderColorAndThickness(FX_ARGB* cr, float* fWidth) { | |
| ASSERT(GetNode()->IsWidgetReady()); | |
| CXFA_Border* borderUI = GetNode()->GetUIBorder(); | |
| if (!borderUI) | |
| return; | |
| CXFA_Edge* edge = borderUI->GetEdgeIfExists(0); | |
| if (!edge) | |
| return; | |
| *cr = edge->GetColor(); | |
| *fWidth = edge->GetThickness(); | |
| } | |
| bool CXFA_FFWidget::IsLayoutRectEmpty() { | |
| CFX_RectF rtLayout = GetRectWithoutRotate(); | |
| return rtLayout.width < 0.1f && rtLayout.height < 0.1f; | |
| } | |
| CXFA_LayoutItem* CXFA_FFWidget::GetParent() { | |
| CXFA_Node* pParentNode = m_pNode->GetParent(); | |
| if (!pParentNode) | |
| return nullptr; | |
| CXFA_LayoutProcessor* layout = GetDocView()->GetLayoutProcessor(); | |
| return layout->GetLayoutItem(pParentNode); | |
| } | |
| bool CXFA_FFWidget::IsAncestorOf(CXFA_FFWidget* pWidget) { | |
| if (!pWidget) | |
| return false; | |
| CXFA_Node* pChildNode = pWidget->GetNode(); | |
| while (pChildNode) { | |
| if (pChildNode == m_pNode) | |
| return true; | |
| pChildNode = pChildNode->GetParent(); | |
| } | |
| return false; | |
| } | |
| bool CXFA_FFWidget::PtInActiveRect(const CFX_PointF& point) { | |
| return GetWidgetRect().Contains(point); | |
| } | |
| CXFA_FFDoc* CXFA_FFWidget::GetDoc() { | |
| return m_pDocView->GetDoc(); | |
| } | |
| CXFA_FFApp* CXFA_FFWidget::GetApp() { | |
| return GetDoc()->GetApp(); | |
| } | |
| IXFA_AppProvider* CXFA_FFWidget::GetAppProvider() { | |
| return GetApp()->GetAppProvider(); | |
| } | |
| bool CXFA_FFWidget::HasVisibleStatus() const { | |
| return GetLayoutItem()->TestStatusBits(XFA_WidgetStatus_Visible); | |
| } | |
| void CXFA_FFWidget::EventKillFocus() { | |
| CXFA_ContentLayoutItem* pItem = GetLayoutItem(); | |
| if (pItem->TestStatusBits(XFA_WidgetStatus_Access)) { | |
| pItem->ClearStatusBits(XFA_WidgetStatus_Access); | |
| return; | |
| } | |
| CXFA_EventParam eParam; | |
| eParam.m_eType = XFA_EVENT_Exit; | |
| eParam.m_pTarget = m_pNode.Get(); | |
| m_pNode->ProcessEvent(GetDocView(), XFA_AttributeValue::Exit, &eParam); | |
| } | |
| bool CXFA_FFWidget::IsButtonDown() { | |
| return GetLayoutItem()->TestStatusBits(XFA_WidgetStatus_ButtonDown); | |
| } | |
| void CXFA_FFWidget::SetButtonDown(bool bSet) { | |
| CXFA_ContentLayoutItem* pItem = GetLayoutItem(); | |
| if (bSet) | |
| pItem->SetStatusBits(XFA_WidgetStatus_ButtonDown); | |
| else | |
| pItem->ClearStatusBits(XFA_WidgetStatus_ButtonDown); | |
| } |