diff options
Diffstat (limited to 'sw/source/core/access/accfrmobj.cxx')
-rw-r--r-- | sw/source/core/access/accfrmobj.cxx | 408 |
1 files changed, 408 insertions, 0 deletions
diff --git a/sw/source/core/access/accfrmobj.cxx b/sw/source/core/access/accfrmobj.cxx new file mode 100644 index 000000000..c09c0215e --- /dev/null +++ b/sw/source/core/access/accfrmobj.cxx @@ -0,0 +1,408 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include "accfrmobj.hxx" + +#include <accmap.hxx> +#include "acccontext.hxx" + +#include <viewsh.hxx> +#include <rootfrm.hxx> +#include <flyfrm.hxx> +#include <pagefrm.hxx> +#include <cellfrm.hxx> +#include <swtable.hxx> +#include <dflyobj.hxx> +#include <frmfmt.hxx> +#include <fmtanchr.hxx> +#include <dcontact.hxx> + +#include <vcl/window.hxx> + +namespace sw::access { + +SwAccessibleChild::SwAccessibleChild() + : mpFrame( nullptr ) + , mpDrawObj( nullptr ) + , mpWindow( nullptr ) +{} + +SwAccessibleChild::SwAccessibleChild( const SdrObject* pDrawObj ) + : mpFrame( nullptr ) + , mpDrawObj( nullptr ) + , mpWindow( nullptr ) +{ + Init( pDrawObj ); +} + +SwAccessibleChild::SwAccessibleChild( const SwFrame* pFrame ) + : mpFrame( nullptr ) + , mpDrawObj( nullptr ) + , mpWindow( nullptr ) +{ + Init( pFrame ); +} + +SwAccessibleChild::SwAccessibleChild( vcl::Window* pWindow ) + : mpFrame( nullptr ) + , mpDrawObj( nullptr ) + , mpWindow( nullptr ) +{ + Init( pWindow ); +} + +SwAccessibleChild::SwAccessibleChild( const SwFrame* pFrame, + const SdrObject* pDrawObj, + vcl::Window* pWindow ) + : mpFrame( nullptr ) + , mpDrawObj( nullptr ) + , mpWindow( nullptr ) +{ + if ( pFrame ) + { + Init( pFrame ); + } + else if ( pDrawObj ) + { + Init( pDrawObj ); + } + else if ( pWindow ) + { + Init( pWindow ); + } + OSL_ENSURE( (!pFrame || pFrame == mpFrame) && + (!pDrawObj || pDrawObj == mpDrawObj) && + (!pWindow || pWindow == mpWindow), + "invalid frame/object/window combination" ); + +} + +SwAccessibleChild::~SwAccessibleChild() = default; + +void SwAccessibleChild::Init( const SdrObject* pDrawObj ) +{ + mpDrawObj = pDrawObj; + const SwVirtFlyDrawObj* pFlyDrawObj = dynamic_cast<const SwVirtFlyDrawObj*>(mpDrawObj); + mpFrame = pFlyDrawObj ? pFlyDrawObj->GetFlyFrame() : nullptr; + mpWindow = nullptr; +} + +void SwAccessibleChild::Init( const SwFrame* pFrame ) +{ + mpFrame = pFrame; + mpDrawObj = mpFrame && mpFrame->IsFlyFrame() + ? static_cast < const SwFlyFrame * >( mpFrame )->GetVirtDrawObj() + : nullptr; + mpWindow = nullptr; +} + +void SwAccessibleChild::Init( vcl::Window* pWindow ) +{ + mpWindow = pWindow; + mpFrame = nullptr; + mpDrawObj = nullptr; +} + +bool SwAccessibleChild::IsAccessible( bool bPagePreview ) const +{ + bool bRet( false ); + + if ( mpFrame ) + { + bRet = mpFrame->IsAccessibleFrame() && + ( !mpFrame->IsCellFrame() || + static_cast<const SwCellFrame *>( mpFrame )->GetTabBox()->GetSttNd() != nullptr ) && + !mpFrame->IsInCoveredCell() && + ( bPagePreview || + !mpFrame->IsPageFrame() ); + } + else if ( mpDrawObj ) + { + bRet = true; + } + else if ( mpWindow ) + { + bRet = true; + } + + return bRet; +} + +bool SwAccessibleChild::IsBoundAsChar() const +{ + bool bRet( false ); + + if ( mpFrame ) + { + bRet = mpFrame->IsFlyFrame() && + static_cast< const SwFlyFrame *>(mpFrame)->IsFlyInContentFrame(); + } + else if ( mpDrawObj ) + { + const SwFrameFormat* pFrameFormat = ::FindFrameFormat( mpDrawObj ); + bRet = pFrameFormat + && (RndStdIds::FLY_AS_CHAR == pFrameFormat->GetAnchor().GetAnchorId()); + } + else if ( mpWindow ) + { + bRet = false; + } + + return bRet; +} + +SwAccessibleChild& SwAccessibleChild::operator=( const SdrObject* pDrawObj ) +{ + Init( pDrawObj ); + return *this; +} + +SwAccessibleChild& SwAccessibleChild::operator=( const SwFrame* pFrame ) +{ + Init( pFrame ); + return *this; +} + +SwAccessibleChild& SwAccessibleChild::operator=( vcl::Window* pWindow ) +{ + Init( pWindow ); + return *this; +} + +bool SwAccessibleChild::operator==( const SwAccessibleChild& r ) const +{ + return mpFrame == r.mpFrame && + mpDrawObj == r.mpDrawObj && + mpWindow == r.mpWindow; +} + +bool SwAccessibleChild::IsValid() const +{ + return mpFrame != nullptr || + mpDrawObj != nullptr || + mpWindow != nullptr; +} + +bool SwAccessibleChild::IsVisibleChildrenOnly() const +{ + bool bRet( false ); + + if ( !mpFrame ) + { + bRet = true; + } + else + { + bRet = mpFrame->IsRootFrame() || + !( mpFrame->IsTabFrame() || + mpFrame->IsInTab() || + ( IsBoundAsChar() && + static_cast<const SwFlyFrame*>(mpFrame)->GetAnchorFrame()->IsInTab() ) ); + } + + return bRet; +} + +SwRect SwAccessibleChild::GetBox( const SwAccessibleMap& rAccMap ) const +{ + SwRect aBox; + + if ( mpFrame ) + { + if ( mpFrame->IsPageFrame() && + static_cast< const SwPageFrame * >( mpFrame )->IsEmptyPage() ) + { + aBox = SwRect( mpFrame->getFrameArea().Left(), mpFrame->getFrameArea().Top()-1, 1, 1 ); + } + else if ( mpFrame->IsTabFrame() ) + { + aBox = mpFrame->getFrameArea(); + aBox.Intersection( mpFrame->GetUpper()->getFrameArea() ); + } + else + { + aBox = mpFrame->getFrameArea(); + } + } + else if( mpDrawObj ) + { + const SwContact* const pContact = ::GetUserCall(mpDrawObj); + // assume that a) the SwVirt* objects that don't have this are handled + // by the mpFrame case above b) for genuine SdrObject this must be set + // if it's connected to layout + assert(dynamic_cast<SwDrawContact const*>(pContact)); + SwPageFrame const*const pPage(const_cast<SwAnchoredObject *>( + pContact->GetAnchoredObj(mpDrawObj))->FindPageFrameOfAnchor()); + if (pPage) // may end up here with partial layout -> not visible + { + aBox = SwRect( mpDrawObj->GetCurrentBoundRect() ); + // tdf#91260 drawing object may be partially off-page + aBox.Intersection(pPage->getFrameArea()); + } + } + else if ( mpWindow ) + { + vcl::Window *pWin = rAccMap.GetShell()->GetWin(); + if (pWin) + { + aBox = SwRect( pWin->PixelToLogic( + tools::Rectangle( mpWindow->GetPosPixel(), + mpWindow->GetSizePixel() ) ) ); + } + } + + return aBox; +} + +SwRect SwAccessibleChild::GetBounds( const SwAccessibleMap& rAccMap ) const +{ + SwRect aBound; + + if( mpFrame ) + { + if( mpFrame->IsPageFrame() && + static_cast< const SwPageFrame * >( mpFrame )->IsEmptyPage() ) + { + aBound = SwRect( mpFrame->getFrameArea().Left(), mpFrame->getFrameArea().Top()-1, 0, 0 ); + } + else + aBound = mpFrame->GetPaintArea(); + } + else if( mpDrawObj ) + { + aBound = GetBox( rAccMap ); + } + else if ( mpWindow ) + { + aBound = GetBox( rAccMap ); + } + + return aBound; +} + +bool SwAccessibleChild::AlwaysIncludeAsChild() const +{ + bool bAlwaysIncludedAsChild( false ); + + if ( mpWindow ) + { + bAlwaysIncludedAsChild = true; + } + + return bAlwaysIncludedAsChild; +} + +const SwFrame* SwAccessibleChild::GetParent( const bool bInPagePreview ) const +{ + const SwFrame* pParent( nullptr ); + + if ( mpFrame ) + { + if( mpFrame->IsFlyFrame() ) + { + const SwFlyFrame* pFly = static_cast< const SwFlyFrame *>( mpFrame ); + if( pFly->IsFlyInContentFrame() ) + { + // For RndStdIds::FLY_AS_CHAR the parent is the anchor + pParent = pFly->GetAnchorFrame(); + OSL_ENSURE( SwAccessibleChild( pParent ).IsAccessible( bInPagePreview ), + "parent is not accessible" ); + } + else + { + // In any other case the parent is the root frm + // (in page preview, the page frame) + if( bInPagePreview ) + pParent = pFly->FindPageFrame(); + else + pParent = pFly->getRootFrame(); + } + } + else + { + SwAccessibleChild aUpper( mpFrame->GetUpper() ); + while( aUpper.GetSwFrame() && !aUpper.IsAccessible(bInPagePreview) ) + { + aUpper = aUpper.GetSwFrame()->GetUpper(); + } + pParent = aUpper.GetSwFrame(); + } + } + else if( mpDrawObj ) + { + const SwDrawContact *pContact = + static_cast< const SwDrawContact* >( GetUserCall( mpDrawObj ) ); + OSL_ENSURE( pContact, "sdr contact is missing" ); + if( pContact ) + { + const SwFrameFormat *pFrameFormat = pContact->GetFormat(); + OSL_ENSURE( pFrameFormat, "frame format is missing" ); + if( pFrameFormat && RndStdIds::FLY_AS_CHAR == pFrameFormat->GetAnchor().GetAnchorId() ) + { + // For RndStdIds::FLY_AS_CHAR the parent is the anchor + pParent = pContact->GetAnchorFrame(); + OSL_ENSURE( SwAccessibleChild( pParent ).IsAccessible( bInPagePreview ), + "parent is not accessible" ); + + } + else + { + // In any other case the parent is the root frm + SwFrame const*const pAnchor(pContact->GetAnchorFrame()); + if (pAnchor) // null if object removed from layout + { + if (bInPagePreview) + pParent = pAnchor->FindPageFrame(); + else + pParent = pAnchor->getRootFrame(); + } + } + } + } + else if ( mpWindow ) + { + css::uno::Reference < css::accessibility::XAccessible > xAcc = + mpWindow->GetAccessible(); + if ( xAcc.is() ) + { + css::uno::Reference < css::accessibility::XAccessibleContext > xAccContext = + xAcc->getAccessibleContext(); + if ( xAccContext.is() ) + { + css::uno::Reference < css::accessibility::XAccessible > xAccParent = + xAccContext->getAccessibleParent(); + if ( xAccParent.is() ) + { + SwAccessibleContext* pAccParentImpl = + dynamic_cast< SwAccessibleContext *>( xAccParent.get() ); + if ( pAccParentImpl ) + { + pParent = pAccParentImpl->GetFrame(); + } + } + } + } + } + + return pParent; +} + +} // namespace sw::access + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |