Quellcodebibliothek Statistik Leitseite products/sources/formale Sprachen/C/LibreOffice/sw/source/core/draw/   (Office von Apache Version 25.8.3.2©)  Datei vom 5.10.2025 mit Größe 36 kB image not shown  

Quelle  dview.cxx   Sprache: C

 
/* -*- 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 <config_wasm_strip.h>

#include <hintids.hxx>
#include <svtools/optionsdrawinglayer.hxx>
#include <officecfg/Office/Common.hxx>
#include <svx/svdpage.hxx>
#include <svx/svdpagv.hxx>
#include <svx/fmmodel.hxx>
#include <sot/exchange.hxx>
#include <svx/sdrundomanager.hxx>
#include <tools/globname.hxx>
#include <editeng/outliner.hxx>
#include <osl/diagnose.h>
#include <com/sun/star/embed/EmbedMisc.hpp>
#include <com/sun/star/embed/XEmbeddedObject.hpp>
#include <unotools/configmgr.hxx>

#include <pagefrm.hxx>
#include <rootfrm.hxx>
#include <cntfrm.hxx>
#include <notxtfrm.hxx>
#include <flyfrm.hxx>
#include <frmfmt.hxx>
#include <dflyobj.hxx>
#include <dcontact.hxx>
#include <textboxhelper.hxx>
#include <viewsh.hxx>
#include <viewimp.hxx>
#include <dview.hxx>
#include <doc.hxx>
#include <mdiexp.hxx>
#include <ndole.hxx>
#include <ndgrf.hxx>
#include <fmtanchr.hxx>
#include <IDocumentUndoRedo.hxx>
#include <DocumentSettingManager.hxx>
#include <IDocumentLayoutAccess.hxx>

#include <com/sun/star/embed/Aspects.hpp>

#include <vector>

#include <sortedobjs.hxx>

using namespace com::sun::star;

namespace {

class SwSdrHdl : public SdrHdl
{
public:
    SwSdrHdl(const Point& rPnt, bool bTopRight ) :
        SdrHdl( rPnt, bTopRight ? SdrHdlKind::Anchor_TR : SdrHdlKind::Anchor ) {}
    virtual bool IsFocusHdl() const override;
};

}

bool SwSdrHdl::IsFocusHdl() const
{
    if( SdrHdlKind::Anchor == m_eKind || SdrHdlKind::Anchor_TR == m_eKind )
        return true;
    return SdrHdl::IsFocusHdl();
}

static const SwFrame *lcl_FindAnchor( const SdrObject *pObj, bool bAll )
{
    const SwVirtFlyDrawObj *pVirt = dynamic_castconst SwVirtFlyDrawObj *>( pObj );
    if ( pVirt )
    {
        if ( bAll || !pVirt->GetFlyFrame()->IsFlyInContentFrame() )
            return pVirt->GetFlyFrame()->GetAnchorFrame();
    }
    else
    {
        const SwDrawContact *pCont = static_cast<const SwDrawContact*>(GetUserCall(pObj));
        if ( pCont )
            return pCont->GetAnchorFrame( pObj );
    }
    return nullptr;
}

SwDrawView::SwDrawView(
    SwViewShellImp& rI,
    FmFormModel& rFmFormModel,
    OutputDevice* pOutDev)
:   FmFormView(rFmFormModel, pOutDev),
    m_rImp( rI )
{
    SetPageVisible( false );
    SetBordVisible( false );
    SetGridVisible( false );
    SetHlplVisible( false );
    SetGlueVisible( false );
    SetFrameDragSingles();
    SetSwapAsynchron();

    EnableExtendedKeyInputDispatcher( false );
    EnableExtendedMouseEventDispatcher( false );

    SetHitTolerancePixel( GetMarkHdlSizePixel()/2 );

    SetPrintPreview( rI.GetShell().IsPreview() );

    // #i73602# Use default from the configuration
    SetBufferedOverlayAllowed(!comphelper::IsFuzzing() && officecfg::Office::Common::Drawinglayer::OverlayBuffer_Writer::get());

    // #i74769#, #i75172# Use default from the configuration
    SetBufferedOutputAllowed(!comphelper::IsFuzzing() && officecfg::Office::Common::Drawinglayer::OverlayBuffer_DrawImpress::get());
}

// #i99665#
bool SwDrawView::IsAntiAliasing()
{
    return SvtOptionsDrawinglayer::IsAntiAliasing();
}

static SdrObject* impLocalHitCorrection(SdrObject* pRetval, const Point& rPnt, sal_uInt16 nTol, const SdrMarkList &rMrkList)
{
    if(!nTol)
    {
        // the old method forced back to outer bounds test when nTol == 0, so
        // do not try to correct when nTol is not set (used from HelpContent)
    }
    else
    {
        // rebuild logic from former SwVirtFlyDrawObj::CheckSdrObjectHit. This is needed since
        // the SdrObject-specific CheckHit implementations are now replaced with primitives and
        // 'tricks' like in the old implementation (e.g. using a view from a model-data class to
        // detect if object is selected) are no longer valid.
        // The standard primitive hit-test for SwVirtFlyDrawObj now is the outer bound. The old
        // implementation reduced this excluding the inner bound when the object was not selected.
        SwVirtFlyDrawObj* pSwVirtFlyDrawObj = dynamic_cast< SwVirtFlyDrawObj* >(pRetval);

        if(pSwVirtFlyDrawObj)
        {
            SwFrame* pLower = pSwVirtFlyDrawObj->GetFlyFrame()->Lower();
            if(pLower && pLower->IsNoTextFrame())
            {
                // the old method used IsNoTextFrame (should be for SW's own OLE and
                // graphic's) to accept hit only based on outer bounds; nothing to do
            }
            else
            {
                // check if the object is selected in this view
                const size_t nMarkCount(rMrkList.GetMarkCount());
                bool bSelected(false);

                for(size_t a = 0; !bSelected && a < nMarkCount; ++a)
                {
                    if(pSwVirtFlyDrawObj == rMrkList.GetMark(a)->GetMarkedSdrObj())
                    {
                        bSelected = true;
                    }
                }

                if(!bSelected)
                {
                    // when not selected, the object is not hit when hit position is inside
                    // inner range. Get and shrink inner range
                    basegfx::B2DRange aInnerBound(pSwVirtFlyDrawObj->getInnerBound());

                    aInnerBound.grow(-1.0 * nTol);

                    if(aInnerBound.isInside(basegfx::B2DPoint(rPnt.X(), rPnt.Y())))
                    {
                        // exclude this hit
                        pRetval = nullptr;
                    }
                }
            }
        }
    }

    return pRetval;
}

SdrObject* SwDrawView::CheckSingleSdrObjectHit(const Point& rPnt, sal_uInt16 nTol, SdrObject* pObj, SdrPageView* pPV, SdrSearchOptions nOptions, const SdrLayerIDSet* pMVisLay) const
{
    // call parent
    SdrObject* pRetval = FmFormView::CheckSingleSdrObjectHit(rPnt, nTol, pObj, pPV, nOptions, pMVisLay);

    if(pRetval)
    {
        // override to allow extra handling when picking SwVirtFlyDrawObj's
        pRetval = impLocalHitCorrection(pRetval, rPnt, nTol, GetMarkedObjectList());
    }

    return pRetval;
}

/// Gets called every time the handles need to be build
void SwDrawView::AddCustomHdl()
{
    const SdrMarkList &rMrkList = GetMarkedObjectList();

    if(rMrkList.GetMarkCount() != 1)
        return;

    SdrObject *pObj = rMrkList.GetMark(0)->GetMarkedSdrObj();
    SwContact* pContact = ::GetUserCall( pObj );
    if (!pContact)
        return;

    // make code robust
    SwFrameFormat* pFrameFormat( ::FindFrameFormat( pObj ) );
    if ( !pFrameFormat )
    {
        OSL_FAIL( " - missing frame format!" );
        return;
    }
    const SwFormatAnchor &rAnchor = pFrameFormat->GetAnchor();

    if (RndStdIds::FLY_AS_CHAR == rAnchor.GetAnchorId())
        return;

    const SwFrame* pAnch = CalcAnchor();
    if(nullptr == pAnch)
        return;

    Point aPos(m_aAnchorPoint);

    if ( RndStdIds::FLY_AT_CHAR == rAnchor.GetAnchorId() )
    {
        // #i28701# - use last character rectangle saved at object
        // in order to avoid a format of the anchor frame
        SwAnchoredObject* pAnchoredObj = pContact->GetAnchoredObj( pObj );

        // Invalidate/recalc LastCharRect which can contain invalid frame offset because
        // of later frame changes
        pAnchoredObj->CheckCharRectAndTopOfLine(false);

        SwRect aAutoPos = pAnchoredObj->GetLastCharRect();
        if ( aAutoPos.Height() )
        {
            aPos = aAutoPos.Pos();
        }
    }

    // add anchor handle:
    std::unique_ptr<SdrHdl> hdl = std::make_unique<SwSdrHdl>( aPos, ( pAnch->IsVertical() && !pAnch->IsVertLR() ) ||
                                     pAnch->IsRightToLeft() );
    hdl->SetObjHdlNum(maHdlList.GetHdlCount());
    maHdlList.AddHdl(std::move(hdl));
}

SdrObject* SwDrawView::GetMaxToTopObj( SdrObject* pObj ) const
{
    if ( GetUserCall(pObj) )
    {
        const SwFrame *pAnch = ::lcl_FindAnchor( pObj, false );
        if ( pAnch )
        {
            //The topmost Obj within the anchor must not be overtaken.
            const SwFlyFrame *pFly = pAnch->FindFlyFrame();
            if ( pFly )
            {
                const SwPageFrame *pPage = pFly->FindPageFrame();
                if ( pPage->GetSortedObjs() )
                {
                    size_t nOrdNum = 0;
                    for (SwAnchoredObject* i : *pPage->GetSortedObjs())
                    {
                        const SdrObject *pO = i->GetDrawObj();

                        if ( pO->GetOrdNumDirect() > nOrdNum )
                        {
                            const SwFrame *pTmpAnch = ::lcl_FindAnchor( pO, false );
                            if ( pFly->IsAnLower( pTmpAnch ) )
                            {
                                nOrdNum = pO->GetOrdNumDirect();
                            }
                        }
                    }
                    if ( nOrdNum )
                    {
                        SdrPage *pTmpPage = GetModel().GetPage( 0 );
                        ++nOrdNum;
                        if ( nOrdNum < pTmpPage->GetObjCount() )
                        {
                            return pTmpPage->GetObj( nOrdNum );
                        }
                    }
                }
            }
        }
    }
    return nullptr;
}

SdrObject* SwDrawView::GetMaxToBtmObj(SdrObject* pObj) const
{
    if ( GetUserCall(pObj) )
    {
        const SwFrame *pAnch = ::lcl_FindAnchor( pObj, false );
        if ( pAnch )
        {
            //The Fly of the anchor must not be "flying under".
            const SwFlyFrame *pFly = pAnch->FindFlyFrame();
            if ( pFly )
            {
                SdrObject *pRet = const_cast<SdrObject*>(static_cast<SdrObject const *>(pFly->GetVirtDrawObj()));
                return pRet != pObj ? pRet : nullptr;
            }
        }
    }
    return nullptr;
}

/// determine maximal order number for a 'child' object of given 'parent' object
sal_uInt32 SwDrawView::GetMaxChildOrdNum( const SwFlyFrame& _rParentObj,
                                           const SdrObject* _pExclChildObj )
{
    sal_uInt32 nMaxChildOrdNum = _rParentObj.GetDrawObj()->GetOrdNum();

    const SdrPage* pDrawPage = _rParentObj.GetDrawObj()->getSdrPageFromSdrObject();
    assert(pDrawPage && ");

    const size_t nObjCount = pDrawPage->GetObjCount();
    for ( size_t i = nObjCount-1; i > _rParentObj.GetDrawObj()->GetOrdNum() ; --i )
    {
        const SdrObject* pObj = pDrawPage->GetObj( i );

        // Don't consider 'child' object <_pExclChildObj>
        if ( pObj == _pExclChildObj )
        {
            continue;
        }

        if ( pObj->GetOrdNum() > nMaxChildOrdNum &&
             _rParentObj.IsAnLower( lcl_FindAnchor( pObj, true ) ) )
        {
            nMaxChildOrdNum = pObj->GetOrdNum();
            break;
        }
    }

    return nMaxChildOrdNum;
}

/// method to move 'repeated' objects of the given moved object to the according level
void SwDrawView::MoveRepeatedObjs( const SwAnchoredObject& _rMovedAnchoredObj,
                                    const std::vector<SdrObject*>& _rMovedChildObjs ) const
{
    // determine 'repeated' objects of already moved object <_rMovedAnchoredObj>
    std::vector<SwAnchoredObject*> aAnchoredObjs;
    {
        const SwContact* pContact = ::GetUserCall( _rMovedAnchoredObj.GetDrawObj() );
        assert(pContact && "SwDrawView::MoveRepeatedObjs(..) - missing contact object -> crash.");
        if (pContact)
            pContact->GetAnchoredObjs( aAnchoredObjs );
    }

    // check, if 'repeated' objects exists.
    if ( aAnchoredObjs.size() <= 1 )
        return;

    SdrPage* pDrawPage = GetModel().GetPage( 0 );

    // move 'repeated' ones to the same order number as the already moved one.
    const size_t nNewPos = _rMovedAnchoredObj.GetDrawObj()->GetOrdNum();
    while ( !aAnchoredObjs.empty() )
    {
        SwAnchoredObject* pAnchoredObj = aAnchoredObjs.back();
        if ( pAnchoredObj != &_rMovedAnchoredObj )
        {
            pDrawPage->SetObjectOrdNum( pAnchoredObj->GetDrawObj()->GetOrdNum(),
                                        nNewPos );
            pDrawPage->RecalcObjOrdNums();
            // adjustments for accessibility API
#if !ENABLE_WASM_STRIP_ACCESSIBILITY
            if ( auto pTmpFlyFrame = pAnchoredObj->DynCastFlyFrame() )
            {
                m_rImp.DisposeAccessibleFrame( pTmpFlyFrame );
                m_rImp.AddAccessibleFrame( pTmpFlyFrame );
            }
            else
            {
                m_rImp.DisposeAccessibleObj(pAnchoredObj->GetDrawObj(), true);
                m_rImp.AddAccessibleObj( pAnchoredObj->GetDrawObj() );
            }
#endif
        }
        aAnchoredObjs.pop_back();
    }

    // move 'repeated' ones of 'child' objects
    for ( SdrObject* pChildObj : _rMovedChildObjs )
    {
        {
            const SwContact* pContact = ::GetUserCall( pChildObj );
            assert(pContact && "SwDrawView::MoveRepeatedObjs(..) - missing contact object -> crash.");
            if (pContact)
                pContact->GetAnchoredObjs( aAnchoredObjs );
        }
        // move 'repeated' ones to the same order number as the already moved one.
        const size_t nTmpNewPos = pChildObj->GetOrdNum();
        while ( !aAnchoredObjs.empty() )
        {
            SwAnchoredObject* pAnchoredObj = aAnchoredObjs.back();
            if ( pAnchoredObj->GetDrawObj() != pChildObj )
            {
                pDrawPage->SetObjectOrdNum( pAnchoredObj->GetDrawObj()->GetOrdNum(),
                                            nTmpNewPos );
                pDrawPage->RecalcObjOrdNums();
                // adjustments for accessibility API
#if !ENABLE_WASM_STRIP_ACCESSIBILITY
                if ( auto pTmpFlyFrame = pAnchoredObj->DynCastFlyFrame() )
                {
                    m_rImp.DisposeAccessibleFrame( pTmpFlyFrame );
                    m_rImp.AddAccessibleFrame( pTmpFlyFrame );
                }
                else
                {
                    m_rImp.DisposeAccessibleObj(pAnchoredObj->GetDrawObj(), true);
                    m_rImp.AddAccessibleObj( pAnchoredObj->GetDrawObj() );
                }
#endif
            }
            aAnchoredObjs.pop_back();
        }
    }
}

// --> adjustment and re-factoring of method
void SwDrawView::ObjOrderChanged( SdrObject* pObj, size_t nOldPos,
                                          size_t nNewPos )
{
    // nothing to do for group members
    if ( pObj->getParentSdrObjectFromSdrObject() )
    {
        return;
    }

    // determine drawing page and assure that the order numbers are correct.
    SdrPage* pDrawPage = GetModel().GetPage( 0 );
    if ( pDrawPage->IsObjOrdNumsDirty() )
        pDrawPage->RecalcObjOrdNums();
    const size_t nObjCount = pDrawPage->GetObjCount();

    SwContact* pContact = ::GetUserCall( pObj );
    if (!pContact)
        return;

    SwAnchoredObject* pMovedAnchoredObj = pContact->GetAnchoredObj( pObj );
    const SwFlyFrame* pParentAnchoredObj =
                                pMovedAnchoredObj->GetAnchorFrame()->FindFlyFrame();

    const bool bMovedForward = nOldPos < nNewPos;

    // assure for a 'child' object, that it doesn't exceed the limits of its 'parent'
    if ( pParentAnchoredObj )
    {
        if ( bMovedForward )
        {
            const size_t nMaxChildOrdNumWithoutMoved =
                    GetMaxChildOrdNum( *pParentAnchoredObj, pMovedAnchoredObj->GetDrawObj() );
            if ( nNewPos > nMaxChildOrdNumWithoutMoved+1 )
            {
                // set position to the top of the 'child' object group
                pDrawPage->SetObjectOrdNum( nNewPos, nMaxChildOrdNumWithoutMoved+1 );
                nNewPos = nMaxChildOrdNumWithoutMoved+1;
            }
        }
        else
        {
            const size_t nParentOrdNum = pParentAnchoredObj->GetDrawObj()->GetOrdNum();
            if ( nNewPos < nParentOrdNum )
            {
                // set position to the bottom of the 'child' object group
                pDrawPage->SetObjectOrdNum( nNewPos, nParentOrdNum );
                nNewPos = nParentOrdNum;
            }
        }
        if ( pDrawPage->IsObjOrdNumsDirty() )
            pDrawPage->RecalcObjOrdNums();
    }

    // Assure, that object isn't positioned between 'repeated' ones
    if ( ( bMovedForward && nNewPos < nObjCount - 1 ) ||
         ( !bMovedForward && nNewPos > 0 ) )
    {
        const SdrObject* pTmpObj =
                pDrawPage->GetObj( bMovedForward ? nNewPos - 1 : nNewPos + 1 );
        if ( pTmpObj )
        {
            size_t nTmpNewPos( nNewPos );
            if (const SwContact* pContact2 = ::GetUserCall( pTmpObj ))
            {
                if ( bMovedForward )
                {
                    // move before the top 'repeated' object
                    const sal_uInt32 nTmpMaxOrdNum = pContact2->GetMaxOrdNum();
                    if ( nTmpMaxOrdNum > nNewPos )
                        nTmpNewPos = nTmpMaxOrdNum;
                }
                else
                {
                    // move behind the bottom 'repeated' object
                    const sal_uInt32 nTmpMinOrdNum = pContact2->GetMinOrdNum();
                    if ( nTmpMinOrdNum < nNewPos )
                        nTmpNewPos = nTmpMinOrdNum;
                }
            }
            if ( nTmpNewPos != nNewPos )
            {
                pDrawPage->SetObjectOrdNum( nNewPos, nTmpNewPos );
                nNewPos = nTmpNewPos;
                pDrawPage->RecalcObjOrdNums();
            }
        }
    }

    // On move forward, assure that object is moved before its own children.
    // Only Writer fly frames can have children.
    if ( pMovedAnchoredObj->DynCastFlyFrame() &&
         bMovedForward && nNewPos < nObjCount - 1 )
    {
        sal_uInt32 nMaxChildOrdNum =
                    GetMaxChildOrdNum( *static_cast<const SwFlyFrame*>(pMovedAnchoredObj) );
        if ( nNewPos < nMaxChildOrdNum )
        {
            // determine position before the object before its top 'child' object
            const SdrObject* pTmpObj = pDrawPage->GetObj( nMaxChildOrdNum );
            if (SwContact* pContact2 = ::GetUserCall( pTmpObj ))
            {
                size_t nTmpNewPos = pContact2->GetMaxOrdNum() + 1;
                if ( nTmpNewPos >= nObjCount )
                {
                    --nTmpNewPos;
                }
                // assure, that determined position isn't between 'repeated' objects
                pTmpObj = pDrawPage->GetObj( nTmpNewPos );
                pContact2 = ::GetUserCall( pTmpObj );
                if (pContact2)
                {
                    nTmpNewPos = pContact2->GetMaxOrdNum();
                    // apply new position
                    pDrawPage->SetObjectOrdNum( nNewPos, nTmpNewPos );
                    nNewPos = nTmpNewPos;
                    pDrawPage->RecalcObjOrdNums();
                }
            }
        }
    }

    // Assure, that object isn't positioned between nested objects
    if ( ( bMovedForward && nNewPos < nObjCount - 1 ) ||
         ( !bMovedForward && nNewPos > 0 ) )
    {
        size_t nTmpNewPos( nNewPos );
        const SwFrameFormat* pParentFrameFormat =
                pParentAnchoredObj ? pParentAnchoredObj->GetFrameFormat() : nullptr;
        const SdrObject* pTmpObj = pDrawPage->GetObj( nNewPos + 1 );
        while ( pTmpObj )
        {
            // #i38563# - assure, that anchor frame exists.
            // If object is anchored inside an invisible part of the document
            // (e.g. page header, whose page style isn't applied, or hidden
            // section), no anchor frame exists.
            const SwFrame* pTmpAnchorFrame = lcl_FindAnchor( pTmpObj, true );
            const SwFlyFrame* pTmpParentObj = pTmpAnchorFrame
                                            ? pTmpAnchorFrame->FindFlyFrame() : nullptr;
            if ( pTmpParentObj &&
                 pTmpParentObj->GetFrameFormat() != pParentFrameFormat )
            {
                if (const SwContact* pContact2 = ::GetUserCall( pTmpObj ))
                {
                    if ( bMovedForward )
                    {
                        nTmpNewPos = pContact2->GetMaxOrdNum();
                        pTmpObj = pDrawPage->GetObj( nTmpNewPos + 1 );
                    }
                    else
                    {
                        nTmpNewPos = pContact2->GetMinOrdNum();
                        pTmpObj = pTmpParentObj->GetDrawObj();
                    }
                }
            }
            else
                break;
        }
        if ( nTmpNewPos != nNewPos )
        {
            pDrawPage->SetObjectOrdNum( nNewPos, nTmpNewPos );
            nNewPos = nTmpNewPos;
            pDrawPage->RecalcObjOrdNums();
        }
    }

    // setup collection of moved 'child' objects to move its 'repeated' objects.
    std::vector< SdrObject* > aMovedChildObjs;

    // move 'children' accordingly
    if ( auto pFlyFrame = pMovedAnchoredObj->DynCastFlyFrame() )
    {
        // adjustments for accessibility API
#if !ENABLE_WASM_STRIP_ACCESSIBILITY
        m_rImp.DisposeAccessibleFrame( pFlyFrame );
        m_rImp.AddAccessibleFrame( pFlyFrame );
#endif

        const sal_uInt32 nChildNewPos = bMovedForward ? nNewPos : nNewPos+1;
        size_t i = bMovedForward ? nOldPos : nObjCount-1;
        do
        {
            SdrObject* pTmpObj = pDrawPage->GetObj( i );
            if ( pTmpObj == pObj )
                break;

            // #i38563# - assure, that anchor frame exists.
            // If object is anchored inside an invisible part of the document
            // (e.g. page header, whose page style isn't applied, or hidden
            // section), no anchor frame exists.
            const SwFrame* pTmpAnchorFrame = lcl_FindAnchor( pTmpObj, true );
            const SwFlyFrame* pTmpParentObj = pTmpAnchorFrame
                                            ? pTmpAnchorFrame->FindFlyFrame() : nullptr;
            if ( pTmpParentObj &&
                 ( ( pTmpParentObj == pFlyFrame ) ||
                   ( pFlyFrame->IsUpperOf( *pTmpParentObj ) ) ) )
            {
                // move child object.,
                pDrawPage->SetObjectOrdNum( i, nChildNewPos );
                pDrawPage->RecalcObjOrdNums();
                // collect 'child' object
                aMovedChildObjs.push_back( pTmpObj );
                // adjustments for accessibility API
#if !ENABLE_WASM_STRIP_ACCESSIBILITY
                if ( auto pFlyDrawObj = dynamic_cast<SwVirtFlyDrawObj *>( pTmpObj ) )
                {
                    const SwFlyFrame *pTmpFlyFrame = pFlyDrawObj->GetFlyFrame();
                    m_rImp.DisposeAccessibleFrame( pTmpFlyFrame );
                    m_rImp.AddAccessibleFrame( pTmpFlyFrame );
                }
                else
                {
                    m_rImp.DisposeAccessibleObj(pTmpObj, true);
                    m_rImp.AddAccessibleObj( pTmpObj );
                }
#endif
            }
            else
            {
                // adjust loop counter
                if ( bMovedForward )
                    ++i;
                else if (i > 0)
                    --i;
            }

        } while ( ( bMovedForward && i < ( nObjCount - aMovedChildObjs.size() ) ) ||
                  ( !bMovedForward && i > ( nNewPos + aMovedChildObjs.size() ) ) );
    }
#if !ENABLE_WASM_STRIP_ACCESSIBILITY
    else
    {
        // adjustments for accessibility API
        m_rImp.DisposeAccessibleObj(pObj, true);
        m_rImp.AddAccessibleObj( pObj );
    }
#endif

    MoveRepeatedObjs( *pMovedAnchoredObj, aMovedChildObjs );
}

bool SwDrawView::TakeDragLimit( SdrDragMode eMode,
                                            tools::Rectangle& rRect ) const
{
    const SdrMarkList &rMrkList = GetMarkedObjectList();
    bool bRet = false;
    if( 1 == rMrkList.GetMarkCount() )
    {
        const SdrObject *pObj = rMrkList.GetMark( 0 )->GetMarkedSdrObj();
        SwRect aRect;
        if( ::CalcClipRect( pObj, aRect, eMode == SdrDragMode::Move ) )
        {
            rRect = aRect.SVRect();
            bRet = true;
        }
    }
    return bRet;
}

const SwFrame* SwDrawView::CalcAnchor()
{
    const SdrMarkList &rMrkList = GetMarkedObjectList();
    if ( rMrkList.GetMarkCount() != 1 )
        return nullptr;

    SdrObject* pObj = rMrkList.GetMark( 0 )->GetMarkedSdrObj();

    //Search for paragraph bound objects, otherwise only the
    //current anchor. Search only if we currently drag.
    const SwFrame* pAnch = nullptr;
    tools::Rectangle aMyRect;
    auto pFlyDrawObj = dynamic_cast<SwVirtFlyDrawObj *>( pObj );
    if ( pFlyDrawObj )
    {
        pAnch = pFlyDrawObj->GetFlyFrame()->GetAnchorFrame();
        aMyRect = pFlyDrawObj->GetFlyFrame()->getFrameArea().SVRect();
    }
    else
    {
        // determine correct anchor position for 'virtual' drawing objects.
        // #i26791#
        if (SwDrawContact* pContact = static_cast<SwDrawContact*>(GetUserCall(pObj)))
        {
            pAnch = pContact->GetAnchorFrame( pObj );
            if( !pAnch )
            {
                pContact->ConnectToLayout();
                // determine correct anchor position for 'virtual' drawing objects.
                // #i26791#
                pAnch = pContact->GetAnchorFrame( pObj );
            }
        }
        aMyRect = pObj->GetSnapRect();
    }

    const bool bTopRight = pAnch && ( ( pAnch->IsVertical() &&
                                            !pAnch->IsVertLR() ) ||
                                             pAnch->IsRightToLeft() );
    const Point aMyPt = bTopRight ? aMyRect.TopRight() : aMyRect.TopLeft();

    Point aPt;
    if ( IsAction() )
    {
        if ( !TakeDragObjAnchorPos( aPt, bTopRight ) )
            return nullptr;
    }
    else
    {
        tools::Rectangle aRect = pObj->GetSnapRect();
        aPt = bTopRight ? aRect.TopRight() : aRect.TopLeft();
    }

    if ( aPt != aMyPt )
    {
        if ( pAnch && pAnch->IsContentFrame() )
        {
            // allow drawing objects in header/footer,
            // but exclude control objects.
            bool bBodyOnly = CheckControlLayer( pObj );
            pAnch = ::FindAnchor( static_cast<const SwContentFrame*>(pAnch), aPt, bBodyOnly );
        }
        else if ( !pFlyDrawObj )
        {
            const SwRect aRect( aPt.getX(), aPt.getY(), 1, 1 );

            if (SwDrawContact* pContact = static_cast<SwDrawContact*>(GetUserCall(pObj)))
            {
                if ( pContact->GetAnchorFrame( pObj ) &&
                     pContact->GetAnchorFrame( pObj )->IsPageFrame() )
                    pAnch = pContact->GetPageFrame();
                else
                    pAnch = pContact->FindPage( aRect );
            }
        }
    }
    if( pAnch && !pAnch->IsProtected() )
        m_aAnchorPoint = pAnch->GetFrameAnchorPos( ::HasWrap( pObj ) );
    else
        pAnch = nullptr;
    return pAnch;
}

void SwDrawView::ShowDragAnchor()
{
    SdrHdl* pHdl = maHdlList.GetHdl(SdrHdlKind::Anchor);
    if ( ! pHdl )
        pHdl = maHdlList.GetHdl(SdrHdlKind::Anchor_TR);

    if(pHdl)
    {
        CalcAnchor();
        pHdl->SetPos(m_aAnchorPoint);
    }
}

void SwDrawView::MarkListHasChanged()
{
    Imp().GetShell().DrawSelChanged();
    FmFormView::MarkListHasChanged();
}

// #i7672#
void SwDrawView::ModelHasChanged()
{
    // The ModelHasChanged() call in DrawingLayer also updates
    // an eventually active text edit view (OutlinerView). This also leads
    // to newly setting the background color for that edit view. Thus,
    // this method rescues the current background color if an OutlinerView
    // exists and re-establishes it then. To be more safe, the OutlinerView
    // will be fetched again (maybe textedit has ended).
    OutlinerView* pView = GetTextEditOutlinerView();
    Color aBackColor;
    bool bColorWasSaved(false);

    if(pView)
    {
        aBackColor = pView->GetBackgroundColor();
        bColorWasSaved = true;
    }

    // call parent
    FmFormView::ModelHasChanged();

    if(bColorWasSaved)
    {
        pView = GetTextEditOutlinerView();

        if(pView)
        {
            pView->SetBackgroundColor(aBackColor);
        }
    }
}

void SwDrawView::MakeVisible( const tools::Rectangle &rRect, vcl::Window & )
{
    OSL_ENSURE( m_rImp.GetShell().GetWin(), "MakeVisible, unknown Window");
    m_rImp.GetShell().MakeVisible( SwRect( rRect ) );
}

void SwDrawView::CheckPossibilities()
{
    FmFormView::CheckPossibilities();

    //In addition to the existing flags of the objects themselves,
    //which are evaluated by the DrawingEngine, other circumstances
    //lead to a protection.
    //Objects that are anchored in frames need to be protected
    //if the content of the frame is protected.
    //OLE-Objects may themselves wish a resize protection (StarMath)

    const SdrMarkList &rMrkList = GetMarkedObjectList();
    bool bProtect = false;
    bool bSzProtect = false;
    bool bRotate(false);

    for ( size_t i = 0; !bProtect && i < rMrkList.GetMarkCount(); ++i )
    {
        const SdrObject *pObj = rMrkList.GetMark( i )->GetMarkedSdrObj();
        const SwFrame *pFrame = nullptr;
        if ( auto pVirtFlyDrawObj = dynamic_castconst SwVirtFlyDrawObj *>( pObj ) )
        {
            const SwFlyFrame *pFly = pVirtFlyDrawObj->GetFlyFrame();
            if ( pFly  )
            {
                pFrame = pFly->GetAnchorFrame();
                const SwFrame* pLower = pFly->Lower();
                if ( pLower && pLower->IsNoTextFrame() )
                {
                    const SwNoTextFrame *const pNTF(static_cast<const SwNoTextFrame*>(pLower));
                    const SwOLENode *const pOLENd = pNTF->GetNode()->GetOLENode();
                    const SwGrfNode *const pGrfNd = pNTF->GetNode()->GetGrfNode();

                    if ( pOLENd )
                    {
                        const uno::Reference < embed::XEmbeddedObject > xObj = const_cast< SwOLEObj& >(pOLENd->GetOLEObj()).GetOleRef();

                        if ( xObj.is() )
                        {
                            // --> improvement for the future, when more
                            // than one Writer fly frame can be selected.

                            // TODO/LATER: retrieve Aspect - from where?!
                            bSzProtect |= ( embed::EmbedMisc::EMBED_NEVERRESIZE & xObj->getStatus( embed::Aspects::MSOLE_CONTENT ) ) != 0;

                            // #i972: protect position if it is a Math object anchored 'as char' and baseline alignment is activated
                            SwDoc* pDoc = Imp().GetShell().GetDoc();
                            const bool bProtectMathPos = SotExchange::IsMath( xObj->getClassID() )
                                    && RndStdIds::FLY_AS_CHAR == pFly->GetFormat()->GetAnchor().GetAnchorId()
                                    && pDoc->GetDocumentSettingManager().get( DocumentSettingId::MATH_BASELINE_ALIGNMENT );
                            if (bProtectMathPos)
                                m_bMoveProtect = true;
                        }
                    }
                    else if(pGrfNd)
                    {
                        // RotGrfFlyFrame: GraphicNode allows rotation(s). The loop ew are in stops
                        // as soon as bMoveProtect is set, but since rotation is valid only with
                        // a single object selected this makes no difference
                        bRotate = true;
                    }
                }
            }
        }
        else
        {
            SwDrawContact *pC = static_cast<SwDrawContact*>(GetUserCall(pObj));
            if ( pC )
                pFrame = pC->GetAnchorFrame( pObj );
        }
        if ( pFrame )
            bProtect = pFrame->IsProtected(); //Frames, areas etc.
        {
            SwFrameFormat* pFrameFormat( ::FindFrameFormat( const_cast<SdrObject*>(pObj) ) );
            if ( !pFrameFormat )
            {
                OSL_FAIL( " - missing frame format" );
                bProtect = true;
            }
            else if ((RndStdIds::FLY_AS_CHAR == pFrameFormat->GetAnchor().GetAnchorId()) &&
                      rMrkList.GetMarkCount() > 1 )
            {
                bProtect = true;
            }
        }
    }
    m_bMoveProtect    |= bProtect;
    m_bResizeProtect  |= bProtect || bSzProtect;

    // RotGrfFlyFrame: allow rotation when SwGrfNode is selected and not size protected
    m_bRotateFreeAllowed |= bRotate && !bProtect;
    m_bRotate90Allowed |= m_bRotateFreeAllowed;
}

/// replace marked <SwDrawVirtObj>-objects by its reference object for delete marked objects.
void SwDrawView::ReplaceMarkedDrawVirtObjs( SdrMarkView& _rMarkView )
{
    SdrPageView* pDrawPageView = _rMarkView.GetSdrPageView();
    const SdrMarkList& rMarkList = _rMarkView.GetMarkedObjectList();

    if( !rMarkList.GetMarkCount() )
        return;

    // collect marked objects in a local data structure
    std::vector<SdrObject*> aMarkedObjs;
    for( size_t i = 0; i < rMarkList.GetMarkCount(); ++i )
    {
        SdrObject* pMarkedObj = rMarkList.GetMark( i )->GetMarkedSdrObj();
        aMarkedObjs.push_back( pMarkedObj );
    }
    // unmark all objects
    _rMarkView.UnmarkAllObj();
    // re-mark objects, but for marked <SwDrawVirtObj>-objects marked its
    // reference object.
    while ( !aMarkedObjs.empty() )
    {
        SdrObject* pMarkObj = aMarkedObjs.back();
        if ( auto pVirtObj = dynamic_cast<SwDrawVirtObj *>( pMarkObj ) )
        {
            SdrObject* pRefObj = &(pVirtObj->ReferencedObj());
            if ( !_rMarkView.IsObjMarked( pRefObj )  )
            {
                _rMarkView.MarkObj( pRefObj, pDrawPageView );
            }
        }
        else
        {
            _rMarkView.MarkObj( pMarkObj, pDrawPageView );
        }

        aMarkedObjs.pop_back();
    }
    // sort marked list in order to assure consistent state in drawing layer
    _rMarkView.GetMarkedObjectList().ForceSort();
}

SfxViewShell* SwDrawView::GetSfxViewShell() const
{
    return m_rImp.GetShell().GetSfxViewShell();
}

void SwDrawView::DeleteMarked()
{
    SwDoc* pDoc = Imp().GetShell().GetDoc();
    SwRootFrame *pTmpRoot = pDoc->getIDocumentLayoutAccess().GetCurrentLayout();
    if ( pTmpRoot )
        pTmpRoot->StartAllAction();
    pDoc->GetIDocumentUndoRedo().StartUndo(SwUndoId::EMPTY, nullptr);
    // replace marked <SwDrawVirtObj>-objects by its reference objects.
    if (SdrPageView* pDrawPageView = m_rImp.GetPageView())
    {
        ReplaceMarkedDrawVirtObjs(pDrawPageView->GetView());
    }

    // Check what textboxes have to be deleted afterwards.
    const SdrMarkList& rMarkList = GetMarkedObjectList();
    std::vector<SwFrameFormat*> aTextBoxesToDelete;
    for (size_t i = 0; i < rMarkList.GetMarkCount(); ++i)
    {
        SdrObject *pObject = rMarkList.GetMark(i)->GetMarkedSdrObj();
        SwContact* pContact = GetUserCall(pObject);
        if (pContact)
        {
            SwFrameFormat* pFormat = pContact->GetFormat();
            if (pObject->getChildrenOfSdrObject())
            {
                auto pChildTextBoxes = SwTextBoxHelper::CollectTextBoxes(pObject, pFormat);
                for (auto& rChildTextBox : pChildTextBoxes)
                    aTextBoxesToDelete.push_back(rChildTextBox);
            }
            else if (SwFrameFormat* pTextBox
                     = SwTextBoxHelper::getOtherTextBoxFormat(pFormat, RES_DRAWFRMFMT))
                aTextBoxesToDelete.push_back(pTextBox);
        }
    }

    if ( pDoc->DeleteSelection( *this ) )
    {
        FmFormView::DeleteMarked();
        ::FrameNotify( &Imp().GetShell(), FLY_DRAG_END );
    }

    // Only delete these now: earlier deletion would clear the mark list as well.
    // Delete in reverse order, assuming that the container is sorted by anchor positions.
    for (int i = aTextBoxesToDelete.size() - 1; i >= 0; --i)
    {
        SwFrameFormat*& rpTextBox = aTextBoxesToDelete[i];
        pDoc->getIDocumentLayoutAccess().DelLayoutFormat(rpTextBox);
    }

    pDoc->GetIDocumentUndoRedo().EndUndo(SwUndoId::EMPTY, nullptr);
    if( pTmpRoot )
        pTmpRoot->EndAllAction();
}

// Create a new view-local UndoManager manager for Writer
std::unique_ptr<SdrUndoManager> SwDrawView::createLocalTextUndoManager()
{
    std::unique_ptr<SdrUndoManager> pUndoManager(new SdrUndoManager);
    pUndoManager->SetDocShell(SfxObjectShell::Current());
    return pUndoManager;
}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Messung V0.5
C=95 H=95 G=94

¤ Dauer der Verarbeitung: 0.18 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.