Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/LibreOffice/svx/source/svdraw/   (Office von Apache Version 25.8.3.2©)  Datei vom 5.10.2025 mit Größe 34 kB image not shown  

Quelle  svdedtv.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 <svx/svdedtv.hxx>
#include <svx/svdundo.hxx>
#include <svx/svdograf.hxx>
#include <svx/svdoole2.hxx>
#include <svx/svdoedge.hxx>
#include <svx/svdlayer.hxx>
#include <svx/svdpagv.hxx>
#include <svx/svdpage.hxx>
#include <svx/svdpoev.hxx>
#include <svx/strings.hrc>
#include <svx/dialmgr.hxx>
#include <svx/e3dsceneupdater.hxx>
#include <rtl/strbuf.hxx>
#include <svx/svdview.hxx>
#include <clonelist.hxx>
#include <svx/svdogrp.hxx>
#include <svx/xfillit0.hxx>
#include <osl/diagnose.h>
#include <sfx2/viewsh.hxx>

#include <com/sun/star/lang/XServiceInfo.hpp>

using namespace com::sun::star;

void SdrEditView::ImpResetPossibilityFlags()
{
    m_bReadOnly               =false;

    m_bGroupPossible          =false;
    m_bUnGroupPossible        =false;
    m_bGrpEnterPossible       =false;
    m_bToTopPossible          =false;
    m_bToBtmPossible          =false;
    m_bReverseOrderPossible   =false;

    m_bImportMtfPossible      =false;
    m_bCombinePossible        =false;
    m_bDismantlePossible      =false;
    m_bCombineNoPolyPolyPossible =false;
    m_bDismantleMakeLinesPossible=false;
    m_bOrthoDesiredOnMarked   =false;

    m_bOneOrMoreMovable       =false;
    m_bMoreThanOneNoMovRot    =false;
    m_bContortionPossible     =false;
    m_bMoveAllowed            =false;
    m_bResizeFreeAllowed      =false;
    m_bResizePropAllowed      =false;
    m_bRotateFreeAllowed      =false;
    m_bRotate90Allowed        =false;
    m_bMirrorFreeAllowed      =false;
    m_bMirror45Allowed        =false;
    m_bMirror90Allowed        =false;
    m_bTransparenceAllowed    =false;
    m_bCropAllowed            =false;
    m_bGradientAllowed        =false;
    m_bShearAllowed           =false;
    m_bEdgeRadiusAllowed      =false;
    m_bCanConvToPath          =false;
    m_bCanConvToPoly          =false;
    m_bCanConvToContour       =false;
    m_bMoveProtect            =false;
    m_bResizeProtect          =false;
}

SdrEditView::SdrEditView(SdrModel& rSdrModel, OutputDevice* pOut)
    : SdrMarkView(rSdrModel, pOut)
    , m_bPossibilitiesDirty(true)
    , m_bReadOnly(false)
    , m_bGroupPossible(false)
    , m_bUnGroupPossible(false)
    , m_bGrpEnterPossible(false)
    , m_bToTopPossible(false)
    , m_bToBtmPossible(false)
    , m_bReverseOrderPossible(false)
    , m_bImportMtfPossible(false)
    , m_bCombinePossible(false)
    , m_bDismantlePossible(false)
    , m_bCombineNoPolyPolyPossible(false)
    , m_bDismantleMakeLinesPossible(false)
    , m_bOrthoDesiredOnMarked(false)
    , m_bOneOrMoreMovable(false)
    , m_bMoreThanOneNoMovRot(false)
    , m_bContortionPossible(false)
    , m_bMoveAllowed(false)
    , m_bResizeFreeAllowed(false)
    , m_bResizePropAllowed(false)
    , m_bRotateFreeAllowed(false)
    , m_bRotate90Allowed(false)
    , m_bMirrorFreeAllowed(false)
    , m_bMirror45Allowed(false)
    , m_bMirror90Allowed(false)
    , m_bShearAllowed(false)
    , m_bEdgeRadiusAllowed(false)
    , m_bTransparenceAllowed(false)
    , m_bCropAllowed(false)
    , m_bGradientAllowed(false)
    , m_bCanConvToPath(false)
    , m_bCanConvToPoly(false)
    , m_bCanConvToContour(false)
    , m_bMoveProtect(false)
    , m_bResizeProtect(false)
{
}

SdrEditView::~SdrEditView()
{
}

void SdrEditView::InsertNewLayer(const OUString& rName, sal_uInt16 nPos)
{
    SdrLayerAdmin& rLA = GetModel().GetLayerAdmin();
    sal_uInt16 nMax=rLA.GetLayerCount();
    if (nPos>nMax) nPos=nMax;
    rLA.NewLayer(rName,nPos);

    if( GetModel().IsUndoEnabled() )
        AddUndo(GetModel().GetSdrUndoFactory().CreateUndoNewLayer(nPos,rLA, GetModel()));

    GetModel().SetChanged();
}

bool SdrEditView::ImpDelLayerCheck(SdrObjList const * pOL, SdrLayerID nDelID) const
{
    bool bDelAll(true);

    for(size_t nObjNum = pOL->GetObjCount(); nObjNum > 0 && bDelAll;)
    {
        nObjNum--;
        SdrObject* pObj = pOL->GetObj(nObjNum);
        assert(pObj);
        SdrObjList* pSubOL = pObj->GetSubList();

        // explicitly test for group objects and 3d scenes
        if(pSubOL && (dynamic_cast<const SdrObjGroup*>(pObj) != nullptr || DynCastE3dScene(pObj)))
        {
            if(!ImpDelLayerCheck(pSubOL, nDelID))
            {
                bDelAll = false;
            }
        }
        else
        {
            if(pObj->GetLayer() != nDelID)
            {
                bDelAll = false;
            }
        }
    }

    return bDelAll;
}

void SdrEditView::ImpDelLayerDelObjs(SdrObjList* pOL, SdrLayerID nDelID)
{
    const size_t nObjCount(pOL->GetObjCount());
    // make sure OrdNums are correct
    pOL->GetObj(0)->GetOrdNum();

    const bool bUndo = GetModel().IsUndoEnabled();

    for(size_t nObjNum = nObjCount; nObjNum > 0;)
    {
        nObjNum--;
        SdrObject* pObj = pOL->GetObj(nObjNum);
        assert(pObj);
        SdrObjList* pSubOL = pObj->GetSubList();


        // explicitly test for group objects and 3d scenes
        if(pSubOL && (dynamic_cast<const SdrObjGroup*>( pObj) != nullptr || DynCastE3dScene(pObj)))
        {
            if(ImpDelLayerCheck(pSubOL, nDelID))
            {
                if( bUndo )
                    AddUndo(GetModel().GetSdrUndoFactory().CreateUndoDeleteObject(*pObj, true));
                pOL->RemoveObject(nObjNum);
            }
            else
            {
                ImpDelLayerDelObjs(pSubOL, nDelID);
            }
        }
        else
        {
            if(pObj->GetLayer() == nDelID)
            {
                if( bUndo )
                    AddUndo(GetModel().GetSdrUndoFactory().CreateUndoDeleteObject(*pObj, true));
                pOL->RemoveObject(nObjNum);
            }
        }
    }
}

void SdrEditView::DeleteLayer(const OUString& rName)
{
    SdrLayerAdmin& rLA = GetModel().GetLayerAdmin();
    SdrLayer* pLayer = rLA.GetLayer(rName);

    if(!pLayer)
        return;

    sal_uInt16 nLayerNum(rLA.GetLayerPos(pLayer));
    SdrLayerID nDelID = pLayer->GetID();

    const bool bUndo = IsUndoEnabled();
    if( bUndo )
        BegUndo(SvxResId(STR_UndoDelLayer));

    bool bMaPg(true);

    for(sal_uInt16 nPageKind(0); nPageKind < 2; nPageKind++)
    {
        // MasterPages and DrawPages
        sal_uInt16 nPgCount(bMaPg ? GetModel().GetMasterPageCount() : GetModel().GetPageCount());

        for(sal_uInt16 nPgNum(0); nPgNum < nPgCount; nPgNum++)
        {
            // over all pages
            SdrPage* pPage = bMaPg ? GetModel().GetMasterPage(nPgNum) : GetModel().GetPage(nPgNum);
            const size_t nObjCount(pPage->GetObjCount());

            // make sure OrdNums are correct
            if(nObjCount)
                pPage->GetObj(0)->GetOrdNum();

            for(size_t nObjNum(nObjCount); nObjNum > 0;)
            {
                nObjNum--;
                SdrObject* pObj = pPage->GetObj(nObjNum);
                assert(pObj);
                SdrObjList* pSubOL = pObj->GetSubList();

                // explicitly test for group objects and 3d scenes
                if(pSubOL && (dynamic_cast<const SdrObjGroup*>(pObj) != nullptr || DynCastE3dScene(pObj)))
                {
                    if(ImpDelLayerCheck(pSubOL, nDelID))
                    {
                        if( bUndo )
                            AddUndo(GetModel().GetSdrUndoFactory().CreateUndoDeleteObject(*pObj, true));
                        pPage->RemoveObject(nObjNum);
                    }
                    else
                    {
                        ImpDelLayerDelObjs(pSubOL, nDelID);
                    }
                }
                else
                {
                    if(pObj->GetLayer() == nDelID)
                    {
                        if( bUndo )
                            AddUndo(GetModel().GetSdrUndoFactory().CreateUndoDeleteObject(*pObj, true));
                        pPage->RemoveObject(nObjNum);
                    }
                }
            }
        }
        bMaPg = false;
    }

    if( bUndo )
    {
        AddUndo(GetModel().GetSdrUndoFactory().CreateUndoDeleteLayer(nLayerNum, rLA, GetModel()));
        // coverity[leaked_storage] - ownership transferred to UndoDeleteLayer
        rLA.RemoveLayer(nLayerNum).release();
        EndUndo();
    }
    else
    {
        rLA.RemoveLayer(nLayerNum);
    }

    GetModel().SetChanged();
}


void SdrEditView::EndUndo()
{
    // #i13033#
    // Comparison changed to 1L since EndUndo() is called later now
    // and EndUndo WILL change count to count-1
    if(1 == GetModel().GetUndoBracketLevel())
    {
        ImpBroadcastEdgesOfMarkedNodes();
    }

    // #i13033#
    // moved to bottom to still have access to UNDOs inside of
    // ImpBroadcastEdgesOfMarkedNodes()
    GetModel().EndUndo();
}

void SdrEditView::ImpBroadcastEdgesOfMarkedNodes()
{
    std::vector<SdrObject*>::const_iterator iterPos;
    const std::vector<SdrObject*>& rAllMarkedObjects = GetTransitiveHullOfMarkedObjects();

    // #i13033#
    // New mechanism to search for necessary disconnections for
    // changed connectors inside the transitive hull of all at
    // the beginning of UNDO selected objects
    for(size_t a(0); a < rAllMarkedObjects.size(); a++)
    {
        SdrEdgeObj* pEdge = dynamic_cast<SdrEdgeObj*>( rAllMarkedObjects[a] );

        if(pEdge)
        {
            SdrObject* pObj1 = pEdge->GetConnectedNode(false);
            SdrObject* pObj2 = pEdge->GetConnectedNode(true);

            if(pObj1 && !pEdge->CheckNodeConnection(false))
            {
                iterPos = std::find(rAllMarkedObjects.begin(),rAllMarkedObjects.end(),pObj1);

                if (iterPos == rAllMarkedObjects.end())
                {
                    if( IsUndoEnabled() )
                        AddUndo(GetModel().GetSdrUndoFactory().CreateUndoGeoObject(*pEdge));
                    pEdge->DisconnectFromNode(false);
                }
            }

            if(pObj2 && !pEdge->CheckNodeConnection(true))
            {
                iterPos = std::find(rAllMarkedObjects.begin(),rAllMarkedObjects.end(),pObj2);

                if (iterPos == rAllMarkedObjects.end())
                {
                    if( IsUndoEnabled() )
                        AddUndo(GetModel().GetSdrUndoFactory().CreateUndoGeoObject(*pEdge));
                    pEdge->DisconnectFromNode(true);
                }
            }
        }
    }

    const size_t nMarkedEdgeCnt = GetMarkedEdgesOfMarkedNodes().GetMarkCount();

    for (size_t i=0; i<nMarkedEdgeCnt; ++i) {
        SdrMark* pEM = GetMarkedEdgesOfMarkedNodes().GetMark(i);
        SdrObject* pEdgeTmp=pEM->GetMarkedSdrObj();
        SdrEdgeObj* pEdge=dynamic_cast<SdrEdgeObj*>( pEdgeTmp );
        if (pEdge!=nullptr) {
            pEdge->SetEdgeTrackDirty();
        }
    }
}


// Possibilities


void SdrEditView::MarkListHasChanged()
{
    SdrMarkView::MarkListHasChanged();
    m_bPossibilitiesDirty=true;
}

void SdrEditView::ModelHasChanged()
{
    SdrMarkView::ModelHasChanged();
    m_bPossibilitiesDirty=true;
}

bool SdrEditView::IsResizeAllowed(bool bProp) const
{
    ForcePossibilities();
    if (m_bResizeProtect) return false;
    if (bProp) return m_bResizePropAllowed;
    return m_bResizeFreeAllowed;
}

bool SdrEditView::IsRotateAllowed(bool b90Deg) const
{
    ForcePossibilities();
    if (m_bMoveProtect) return false;
    if (b90Deg) return m_bRotate90Allowed;
    return m_bRotateFreeAllowed;
}

bool SdrEditView::IsMirrorAllowed(bool b45Deg, bool b90Deg) const
{
    ForcePossibilities();
    if (m_bMoveProtect) return false;
    if (b90Deg) return m_bMirror90Allowed;
    if (b45Deg) return m_bMirror45Allowed;
    return m_bMirrorFreeAllowed;
}

bool SdrEditView::IsTransparenceAllowed() const
{
    ForcePossibilities();
    return m_bTransparenceAllowed;
}

bool SdrEditView::IsCropAllowed() const
{
    ForcePossibilities();
    return m_bCropAllowed;
}

bool SdrEditView::IsGradientAllowed() const
{
    ForcePossibilities();
    return m_bGradientAllowed;
}

bool SdrEditView::IsShearAllowed() const
{
    ForcePossibilities();
    if (m_bResizeProtect) return false;
    return m_bShearAllowed;
}

bool SdrEditView::IsEdgeRadiusAllowed() const
{
    ForcePossibilities();
    return m_bEdgeRadiusAllowed;
}

bool SdrEditView::IsCrookAllowed(bool bNoContortion) const
{
    // CrookMode missing here (no rotations allowed when shearing ...)
    ForcePossibilities();
    if (bNoContortion) {
        if (!m_bRotateFreeAllowed) return false;
        return !m_bMoveProtect && m_bMoveAllowed;
    } else {
        return !m_bResizeProtect && m_bContortionPossible;
    }
}

bool SdrEditView::IsDistortAllowed(bool bNoContortion) const
{
    ForcePossibilities();
    if (bNoContortion) {
        return false;
    } else {
        return !m_bResizeProtect && m_bContortionPossible;
    }
}

bool SdrEditView::IsCombinePossible(bool bNoPolyPoly) const
{
    ForcePossibilities();
    if (bNoPolyPoly) return m_bCombineNoPolyPolyPossible;
    else return m_bCombinePossible;
}

bool SdrEditView::IsDismantlePossible(bool bMakeLines) const
{
    ForcePossibilities();
    if (bMakeLines) return m_bDismantleMakeLinesPossible;
    else return m_bDismantlePossible;
}

void SdrEditView::CheckPossibilities()
{
    if (mbSomeObjChgdFlag)
    {
        m_bPossibilitiesDirty = true;

        // This call IS necessary to correct the MarkList, in which
        // no longer to the model belonging objects still can reside.
        // These ones need to be removed.
        CheckMarked();
    }

    if (!m_bPossibilitiesDirty)
        return;

    const SdrMarkList& rMarkList = GetMarkedObjectList();
    ImpResetPossibilityFlags();
    rMarkList.ForceSort();
    const size_t nMarkCount = rMarkList.GetMarkCount();
    if (nMarkCount != 0)
    {
        m_bReverseOrderPossible = (nMarkCount >= 2);

        size_t nMovableCount=0;
        m_bGroupPossible=nMarkCount>=2;
        m_bCombinePossible=nMarkCount>=2;
        if (nMarkCount==1)
        {
            // check bCombinePossible more thoroughly
            // still missing ...
            const SdrObject* pObj=rMarkList.GetMark(0)->GetMarkedSdrObj();
            //const SdrPathObj* pPath=dynamic_cast<SdrPathObj*>( pObj );
            bool bGroup=pObj->GetSubList()!=nullptr;
            bool bHasText=pObj->GetOutlinerParaObject()!=nullptr;
            if (bGroup || bHasText) {
                m_bCombinePossible=true;
            }
        }
        m_bCombineNoPolyPolyPossible=m_bCombinePossible;
        // accept transformations for now
        m_bMoveAllowed      =true;
        m_bResizeFreeAllowed=true;
        m_bResizePropAllowed=true;
        m_bRotateFreeAllowed=true;
        m_bRotate90Allowed  =true;
        m_bMirrorFreeAllowed=true;
        m_bMirror45Allowed  =true;
        m_bMirror90Allowed  =true;
        m_bShearAllowed     =true;
        m_bEdgeRadiusAllowed=false;
        m_bContortionPossible=true;
        m_bCanConvToContour = true;

        // these ones are only allowed when single object is selected
        m_bTransparenceAllowed = (nMarkCount == 1);
        m_bGradientAllowed = (nMarkCount == 1);
        m_bCropAllowed = (nMarkCount == 1);
        if(m_bGradientAllowed)
        {
            // gradient depends on fill style
            const SdrMark* pM = rMarkList.GetMark(0);
            const SdrObject* pObj = pM->GetMarkedSdrObj();

            // may be group object, so get merged ItemSet
            const SfxItemSet& rSet = pObj->GetMergedItemSet();
            SfxItemState eState = rSet.GetItemState(XATTR_FILLSTYLE, false);

            if(SfxItemState::INVALID != eState)
            {
                // If state is not DONTCARE, test the item
                drawing::FillStyle eFillStyle = rSet.Get(XATTR_FILLSTYLE).GetValue();

                if(eFillStyle != drawing::FillStyle_GRADIENT)
                {
                    m_bGradientAllowed = false;
                }
            }
        }

        bool bNoMovRotFound=false;
        const SdrPageView* pPV0=nullptr;

        for (size_t nm=0; nm<nMarkCount; ++nm) {
            const SdrMark* pM=rMarkList.GetMark(nm);
            const SdrObject* pObj=pM->GetMarkedSdrObj();
            const SdrPageView* pPV=pM->GetPageView();
            if (pPV!=pPV0) {
                if (pPV->IsReadOnly()) m_bReadOnly=true;
                pPV0=pPV;
            }

            SdrObjTransformInfoRec aInfo;
            pObj->TakeObjInfo(aInfo);
            bool bMovPrt=pObj->IsMoveProtect();
            bool bSizPrt=pObj->IsResizeProtect();
            if (!bMovPrt && aInfo.bMoveAllowed) nMovableCount++; // count MovableObjs
            if (bMovPrt) m_bMoveProtect=true;
            if (bSizPrt) m_bResizeProtect=true;

            // not allowed when not allowed at one object
            if(!aInfo.bTransparenceAllowed)
                m_bTransparenceAllowed = false;

            // If one of these can't do something, none can
            if (!aInfo.bMoveAllowed      ) m_bMoveAllowed      =false;
            if (!aInfo.bResizeFreeAllowed) m_bResizeFreeAllowed=false;
            if (!aInfo.bResizePropAllowed) m_bResizePropAllowed=false;
            if (!aInfo.bRotateFreeAllowed) m_bRotateFreeAllowed=false;
            if (!aInfo.bRotate90Allowed  ) m_bRotate90Allowed  =false;
            if (!aInfo.bMirrorFreeAllowed) m_bMirrorFreeAllowed=false;
            if (!aInfo.bMirror45Allowed  ) m_bMirror45Allowed  =false;
            if (!aInfo.bMirror90Allowed  ) m_bMirror90Allowed  =false;
            if (!aInfo.bShearAllowed     ) m_bShearAllowed     =false;
            if (aInfo.bEdgeRadiusAllowed) m_bEdgeRadiusAllowed=true;
            if (aInfo.bNoContortion      ) m_bContortionPossible=false;
            // For Crook with Contortion: all objects have to be
            // Movable and Rotatable, except for a maximum of 1 of them
            if (!m_bMoreThanOneNoMovRot) {
                if (!aInfo.bMoveAllowed || !aInfo.bResizeFreeAllowed) {
                    m_bMoreThanOneNoMovRot=bNoMovRotFound;
                    bNoMovRotFound=true;
                }
            }

            // Must be resizable to allow cropping
            if (!aInfo.bResizeFreeAllowed && !aInfo.bResizePropAllowed)
                m_bCropAllowed = false;

            // if one member cannot be converted, no conversion is possible
            if(!aInfo.bCanConvToContour)
                m_bCanConvToContour = false;

            // Ungroup
            if (!m_bUnGroupPossible) m_bUnGroupPossible=pObj->GetSubList()!=nullptr;
            // ConvertToCurve: If at least one can be converted, that is fine.
            if (aInfo.bCanConvToPath          ) m_bCanConvToPath          =true;
            if (aInfo.bCanConvToPoly          ) m_bCanConvToPoly          =true;

            // Combine/Dismantle
            if(m_bCombinePossible)
            {
                m_bCombinePossible = ImpCanConvertForCombine(pObj);
                m_bCombineNoPolyPolyPossible = m_bCombinePossible;
            }

            if (!m_bDismantlePossible) m_bDismantlePossible = ImpCanDismantle(pObj, false);
            if (!m_bDismantleMakeLinesPossible) m_bDismantleMakeLinesPossible = ImpCanDismantle(pObj, true);
            // check OrthoDesiredOnMarked
            if (!m_bOrthoDesiredOnMarked && !aInfo.bNoOrthoDesired) m_bOrthoDesiredOnMarked=true;
            // check ImportMtf

            if (!m_bImportMtfPossible)
            {
                const SdrGrafObj* pSdrGrafObj = dynamic_castconst SdrGrafObj* >(pObj);
                if (pSdrGrafObj != nullptr)
                {
                    if ((pSdrGrafObj->HasGDIMetaFile() && !pSdrGrafObj->IsEPS()) ||
                        pSdrGrafObj->isEmbeddedVectorGraphicData())
                    {
                        m_bImportMtfPossible = true;
                    }
                }

                const SdrOle2Obj* pSdrOle2Obj = dynamic_castconst SdrOle2Obj* >(pObj);
                if (pSdrOle2Obj)
                {
                    m_bImportMtfPossible = pSdrOle2Obj->GetObjRef().is();
                }
            }
        }

        m_bOneOrMoreMovable=nMovableCount!=0;
        m_bGrpEnterPossible=m_bUnGroupPossible;
    }
    ImpCheckToTopBtmPossible();
    static_cast<SdrPolyEditView*>(this)->ImpCheckPolyPossibilities();
    m_bPossibilitiesDirty=false;

    if (m_bReadOnly || SfxViewShell::IsCurrentLokViewReadOnly() ) {
        bool bTemp=m_bGrpEnterPossible;
        ImpResetPossibilityFlags();
        m_bReadOnly=true;
        m_bGrpEnterPossible=bTemp;
    }
    if (!m_bMoveAllowed)        return;

    // Don't allow moving glued connectors.
    // Currently only implemented for single selection.
    if (nMarkCount==1) {
        SdrObject* pObj=rMarkList.GetMark(0)->GetMarkedSdrObj();
        SdrEdgeObj* pEdge=dynamic_cast<SdrEdgeObj*>( pObj );
        if (pEdge!=nullptr) {
            SdrObject* pNode1=pEdge->GetConnectedNode(true);
            SdrObject* pNode2=pEdge->GetConnectedNode(false);
            if (pNode1!=nullptr || pNode2!=nullptr) m_bMoveAllowed=false;
        }
    }

    // Don't allow enter Diagrams
    if (1 == nMarkCount && m_bGrpEnterPossible)
    {
        SdrObject* pCandidate(rMarkList.GetMark(0)->GetMarkedSdrObj());

        if(nullptr != pCandidate && pCandidate->isDiagram())
            m_bGrpEnterPossible = false;
    }
}


void SdrEditView::ForceMarkedObjToAnotherPage()
{
    const SdrMarkList& rMarkList = GetMarkedObjectList();
    bool bFlg=false;
    for (size_t nm=0; nm<rMarkList.GetMarkCount(); ++nm) {
        SdrMark* pM=rMarkList.GetMark(nm);
        SdrObject* pObj=pM->GetMarkedSdrObj();
        tools::Rectangle aObjRect(pObj->GetCurrentBoundRect());
        tools::Rectangle aPgRect(pM->GetPageView()->GetPageRect());
        if (!aObjRect.Overlaps(aPgRect)) {
            bool bFnd=false;
            SdrPageView* pPV = GetSdrPageView();

            if(pPV)
            {
                bFnd = aObjRect.Overlaps(pPV->GetPageRect());
            }

            if(bFnd)
            {
                pM->GetPageView()->GetObjList()->RemoveObject(pObj->GetOrdNum());
                pPV->GetObjList()->InsertObject(pObj, SAL_MAX_SIZE);
                pM->SetPageView(pPV);
                InvalidateAllWin(aObjRect);
                bFlg=true;
            }
        }
    }
    if (bFlg) {
        MarkListHasChanged();
    }
}

std::vector<rtl::Reference<SdrObject>> SdrEditView::DeleteMarkedList(SdrMarkList const&&nbsp;rMark)
{
    std::vector<rtl::Reference<SdrObject>> ret;
    if (rMark.GetMarkCount()!=0)
    {
        rMark.ForceSort();

        const bool bUndo = IsUndoEnabled();
        if( bUndo )
            BegUndo();
        const size_t nMarkCount(rMark.GetMarkCount());

        if(nMarkCount)
        {
            std::vector< E3DModifySceneSnapRectUpdater* > aUpdaters;

            if( bUndo )
            {
                for(size_t nm = nMarkCount; nm > 0;)
                {
                    --nm;
                    SdrMark* pM = rMark.GetMark(nm);
                    SdrObject* pObj = pM->GetMarkedSdrObj();

                    // extra undo actions for changed connector which now may hold its laid out path (SJ)
                    AddUndoActions(CreateConnectorUndo( *pObj ));

                    AddUndo(GetModel().GetSdrUndoFactory().CreateUndoDeleteObject(*pObj));
                }
            }

            // make sure, OrderNums are correct:
            rMark.GetMark(0)->GetMarkedSdrObj()->GetOrdNum();

            for(size_t nm = nMarkCount; nm > 0;)
            {
                --nm;
                SdrMark* pM = rMark.GetMark(nm);
                SdrObject* pObj = pM->GetMarkedSdrObj();
                SdrObjList*  pOL = pObj->getParentSdrObjListFromSdrObject();
                const size_t nOrdNum(pObj->GetOrdNumDirect());

                bool bIs3D = DynCastE3dObject(pObj);
                // set up a scene updater if object is a 3d object
                if(bIs3D)
                {
                    aUpdaters.push_back(new E3DModifySceneSnapRectUpdater(pObj));
                }

                if( !bUndo )
                {
                    // tdf#108863 and tdf#108889 don't delete objects before EndUndo()
                    ret.push_back(pObj);
                }

                pOL->RemoveObject(nOrdNum);
            }

            // fire scene updaters
            while(!aUpdaters.empty())
            {
                delete aUpdaters.back();
                aUpdaters.pop_back();
            }
        }

        if( bUndo )
            EndUndo();
    }
    return ret;
}

static void lcl_LazyDelete(std::vector<rtl::Reference<SdrObject>> & rLazyDelete)
{
    // now delete removed scene objects
    while (!rLazyDelete.empty())
        rLazyDelete.pop_back();
}

void SdrEditView::DeleteMarkedObj()
{
    const SdrMarkList& rMarkList = GetMarkedObjectList();
    // #i110981# return when nothing is to be done at all
    if(!rMarkList.GetMarkCount())
    {
        return;
    }

    // moved breaking action and undo start outside loop
    BrkAction();
    BegUndo(SvxResId(STR_EditDelete),rMarkList.GetMarkDescription(),SdrRepeatFunc::Delete);

    std::vector<rtl::Reference<SdrObject>> lazyDeleteObjects;
    // remove as long as something is selected. This allows to schedule objects for
    // removal for a next run as needed
    while(rMarkList.GetMarkCount())
    {
        // vector to remember the parents which may be empty after object removal
        std::vector< SdrObject* > aParents;

        {
            const size_t nCount(rMarkList.GetMarkCount());

            for(size_t a = 0; a < nCount; ++a)
            {
                // in the first run, add all found parents, but only once
                SdrMark* pMark(rMarkList.GetMark(a));
                SdrObject* pObject(pMark->GetMarkedSdrObj());
                SdrObject* pParent(pObject->getParentSdrObjectFromSdrObject());

                if(pParent)
                {
                    if(!aParents.empty())
                    {
                        std::vector< SdrObject* >::iterator aFindResult =
                            std::find(aParents.begin(), aParents.end(), pParent);

                        if(aFindResult == aParents.end())
                        {
                            aParents.push_back(pParent);
                        }
                    }
                    else
                    {
                        aParents.push_back(pParent);
                    }
                }
            }

            if(!aParents.empty())
            {
                // in a 2nd run, remove all objects which may already be scheduled for
                // removal. I am not sure if this can happen, but theoretically
                // a to-be-removed object may already be the group/3DScene itself
                for(size_t a = 0; a < nCount; ++a)
                {
                    SdrMark* pMark = rMarkList.GetMark(a);
                    SdrObject* pObject = pMark->GetMarkedSdrObj();

                    std::vector< SdrObject* >::iterator aFindResult =
                        std::find(aParents.begin(), aParents.end(), pObject);

                    if(aFindResult != aParents.end())
                    {
                        aParents.erase(aFindResult);
                    }
                }
            }
        }

        // original stuff: remove selected objects. Handle clear will
        // do something only once
        auto temp(DeleteMarkedList(rMarkList));
        lazyDeleteObjects.insert(lazyDeleteObjects.end(), temp.begin(), temp.end());
        GetMarkedObjectListWriteAccess().Clear();
        maHdlList.Clear();

        while(!aParents.empty() && !rMarkList.GetMarkCount())
        {
            // iterate over remembered parents
            SdrObject* pParent = aParents.back();
            aParents.pop_back();

            if(pParent->GetSubList() && 0 == pParent->GetSubList()->GetObjCount())
            {
                // we detected an empty parent, a candidate to leave group/3DScene
                // if entered
                if(GetSdrPageView()->GetCurrentGroup()
                    && GetSdrPageView()->GetCurrentGroup() == pParent)
                {
                    GetSdrPageView()->LeaveOneGroup();
                }

                // schedule empty parent for removal
                GetMarkedObjectListWriteAccess().InsertEntry(
                    SdrMark(pParent, GetSdrPageView()));
            }
        }
    }

    // end undo and change messaging moved at the end
    EndUndo();
    MarkListHasChanged();

    lcl_LazyDelete(lazyDeleteObjects);
}

void SdrEditView::CopyMarkedObj()
{
    const SdrMarkList& rMarkList = GetMarkedObjectList();
    rMarkList.ForceSort();

    SdrMarkList aSourceObjectsForCopy(rMarkList);
    // The following loop is used instead of MarkList::Merge(), to be
    // able to flag the MarkEntries.
    const size_t nEdgeCnt = GetEdgesOfMarkedNodes().GetMarkCount();
    for (size_t nEdgeNum=0; nEdgeNum<nEdgeCnt; ++nEdgeNum) {
        SdrMark aM(*GetEdgesOfMarkedNodes().GetMark(nEdgeNum));
        aM.SetUser(1);
        aSourceObjectsForCopy.InsertEntry(aM);
    }
    aSourceObjectsForCopy.ForceSort();

    // #i13033#
    // New mechanism to re-create the connections of cloned connectors
    CloneList aCloneList;

    const bool bUndo = IsUndoEnabled();

    GetMarkedObjectListWriteAccess().Clear();
    size_t nCloneErrCnt=0;
    std::unordered_set<rtl::OUString> aNameSet;
    const size_t nMarkCount=aSourceObjectsForCopy.GetMarkCount();
    for (size_t nm=0; nm<nMarkCount; ++nm) {
        SdrMark* pM=aSourceObjectsForCopy.GetMark(nm);
        SdrObject* pSource(pM->GetMarkedSdrObj());
        rtl::Reference<SdrObject> pO(pSource->CloneSdrObject(pSource->getSdrModelFromSdrObject()));
        if (pO!=nullptr) {
            pM->GetPageView()->GetObjList()->InsertObjectThenMakeNameUnique(pO.get(), aNameSet);

            if( bUndo )
                AddUndo(GetModel().GetSdrUndoFactory().CreateUndoCopyObject(*pO));

            SdrMark aME(*pM);
            aME.SetMarkedSdrObj(pO.get());
            aCloneList.AddPair(pM->GetMarkedSdrObj(), pO.get());

            if (pM->GetUser()==0)
            {
                // otherwise it is only an Edge we have to copy as well
                GetMarkedObjectListWriteAccess().InsertEntry(aME);
            }
        } else {
            nCloneErrCnt++;
        }
    }

    // #i13033#
    // New mechanism to re-create the connections of cloned connectors
    aCloneList.CopyConnections();

    if(nCloneErrCnt)
    {
#ifdef DBG_UTIL
        OStringBuffer aStr("SdrEditView::CopyMarkedObj(): Error when cloning ");

        if(nCloneErrCnt == 1)
        {
            aStr.append("a drawing object.");
        }
        else
        {
            aStr.append(OString::number(static_cast<sal_Int32>(nCloneErrCnt))
                + " drawing objects.");
        }

        aStr.append(" This object's/These objects's connections will not be copied.");
        OSL_FAIL(aStr.getStr());
#endif
    }
    MarkListHasChanged();
}


bool SdrEditView::InsertObjectAtView(SdrObject* pObj, SdrPageView& rPV, SdrInsertFlags nOptions)
{
    if (nOptions & SdrInsertFlags::SETDEFLAYER) {
        SdrLayerID nLayer=rPV.GetPage()->GetLayerAdmin().GetLayerID(maActualLayer);
        if (nLayer==SDRLAYER_NOTFOUND) nLayer=SdrLayerID(0);
        if (rPV.GetLockedLayers().IsSet(nLayer) || !rPV.GetVisibleLayers().IsSet(nLayer)) {
            return false;
        }
        pObj->NbcSetLayer(nLayer);
    }
    if (nOptions & SdrInsertFlags::SETDEFATTR) {
        if (mpDefaultStyleSheet!=nullptr) pObj->NbcSetStyleSheet(mpDefaultStyleSheet, false);
        pObj->SetMergedItemSet(maDefaultAttr);
    }
    if (!pObj->IsInserted()) {
        rPV.GetObjList()->InsertObject(pObj, SAL_MAX_SIZE);
    }

    css::uno::Reference<lang::XServiceInfo> xServices(GetModel().getUnoModel(),
                                                      css::uno::UNO_QUERY);
    if (xServices.is() && (xServices->supportsService(u"com.sun.star.sheet.SpreadsheetDocument"_ustr) ||
                           xServices->supportsService(u"com.sun.star.text.TextDocument"_ustr)))
    {
        const bool bUndo(IsUndoEnabled());
        GetModel().EnableUndo(false);
        pObj->MakeNameUnique();
        GetModel().EnableUndo(bUndo);
    }

    if( IsUndoEnabled())
    {
        bool bDontDeleteReally = true;
        EndTextEditCurrentView(bDontDeleteReally);
        AddUndo(GetModel().GetSdrUndoFactory().CreateUndoNewObject(*pObj));
    }

    if (!(nOptions & SdrInsertFlags::DONTMARK)) {
        if (!(nOptions & SdrInsertFlags::ADDMARK)) UnmarkAllObj();
        MarkObj(pObj,&rPV);
    }
    return true;
}

void SdrEditView::ReplaceObjectAtView(SdrObject* pOldObj, SdrPageView& rPV, SdrObject* pNewObj, bool bMark)
{
    if(IsTextEdit())
    {
#ifdef DBG_UTIL
        if(auto pTextObj = DynCastSdrTextObj(pOldObj))
            if (pTextObj->IsTextEditActive())
                OSL_ENSURE(false"OldObject is in TextEdit mode, this has to be ended before replacing it using SdrEndTextEdit (!)");

        if(auto pTextObj = DynCastSdrTextObj(pNewObj))
            if (pTextObj->IsTextEditActive())
                OSL_ENSURE(false"NewObject is in TextEdit mode, this has to be ended before replacing it using SdrEndTextEdit (!)");
#endif

        // #i123468# emergency repair situation, needs to cast up to a class derived from
        // this one; (aw080 has a mechanism for that and the view hierarchy is secured to
        // always be a SdrView)
        SdrView *pSdrView = dynamic_cast<SdrView*>(this);
        if (pSdrView)
            pSdrView->SdrEndTextEdit();
    }

    SdrObjList* pOL=pOldObj->getParentSdrObjListFromSdrObject();
    const bool bUndo = IsUndoEnabled();
    if( bUndo  )
        AddUndo(GetModel().GetSdrUndoFactory().CreateUndoReplaceObject(*pOldObj,*pNewObj));

    if( IsObjMarked( pOldObj ) )
        MarkObj( pOldObj, &rPV, true /*unmark!*/ );

    pOL->ReplaceObject(pNewObj,pOldObj->GetOrdNum());

    if (bMark) MarkObj(pNewObj,&rPV);
}


bool SdrEditView::IsUndoEnabled() const
{
    return GetModel().IsUndoEnabled();
}

void SdrEditView::EndTextEditAllViews() const
{
    GetModel().ForAllListeners(
        [](SfxListener* pListener)
        {
            SdrObjEditView* pView = dynamic_cast<SdrObjEditView*>(pListener);
            if (pView && pView->IsTextEdit())
                pView->SdrEndTextEdit();
            return false;
        });
}

void SdrEditView::EndTextEditCurrentView(bool bDontDeleteReally)
{
    if (IsTextEdit())
    {
        SdrView* pSdrView = dynamic_cast<SdrView*>(this);
        if (pSdrView)
            pSdrView->SdrEndTextEdit(bDontDeleteReally);
    }
}

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

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

¤ Dauer der Verarbeitung: 0.15 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.