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 20 kB image not shown  

Quelle  svdmark.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 <sal/config.h>

#include <osl/time.h>
#include <svx/svdmark.hxx>
#include <svx/svdobj.hxx>
#include <svx/svdpage.hxx>
#include <svx/svdpagv.hxx>
#include <svx/strings.hrc>
#include <svx/dialmgr.hxx>


#include <svl/SfxBroadcaster.hxx>
#include <svx/svdoedge.hxx>
#include <osl/diagnose.h>
#include <tools/debug.hxx>

#include <cassert>

void SdrMark::setTime()
{
    TimeValue aNow;
    osl_getSystemTime(&aNow);
    mnTimeStamp = sal_Int64(aNow.Seconds) * 1000000000 + aNow.Nanosec;
}

SdrMark::SdrMark(SdrObject* pNewObj, SdrPageView* pNewPageView)
:   mpSelectedSdrObject(pNewObj),
    mpPageView(pNewPageView),
    mbCon1(false),
    mbCon2(false),
    mnUser(0)
{
    if(mpSelectedSdrObject)
    {
        mpSelectedSdrObject->AddObjectUser( *this );
    }
    setTime();
}

SdrMark::SdrMark(const SdrMark& rMark)
:   ObjectUser(),
    mnTimeStamp(0),
    mpSelectedSdrObject(nullptr),
    mpPageView(nullptr),
    mbCon1(false),
    mbCon2(false),
    mnUser(0)
{
    *this = rMark;
}

SdrMark::~SdrMark()
{
    if (mpSelectedSdrObject)
    {
        mpSelectedSdrObject->RemoveObjectUser( *this );
    }
}

void SdrMark::ObjectInDestruction(const SdrObject& rObject)
{
    (void) rObject; // avoid warnings
    OSL_ENSURE(mpSelectedSdrObject && mpSelectedSdrObject == &rObject, "SdrMark::ObjectInDestruction: called from object different from hosted one (!)");
    OSL_ENSURE(mpSelectedSdrObject, "SdrMark::ObjectInDestruction: still selected SdrObject is deleted, deselect first (!)");
    mpSelectedSdrObject = nullptr;
}

void SdrMark::SetMarkedSdrObj(SdrObject* pNewObj)
{
    if(mpSelectedSdrObject)
    {
        mpSelectedSdrObject->RemoveObjectUser( *this );
    }

    mpSelectedSdrObject = pNewObj;

    if(mpSelectedSdrObject)
    {
        mpSelectedSdrObject->AddObjectUser( *this );
    }
}

SdrMark& SdrMark::operator=(const SdrMark& rMark)
{
    SetMarkedSdrObj(rMark.mpSelectedSdrObject);

    mnTimeStamp = rMark.mnTimeStamp;
    mpPageView = rMark.mpPageView;
    mbCon1 = rMark.mbCon1;
    mbCon2 = rMark.mbCon2;
    mnUser = rMark.mnUser;
    maPoints = rMark.maPoints;
    maGluePoints = rMark.maGluePoints;

    return *this;
}

static bool ImpSdrMarkListSorter(std::unique_ptr<SdrMark> const& lhs, std::unique_ptr<SdrMark> const& rhs)
{
    SdrObject* pObj1 = lhs->GetMarkedSdrObj();
    SdrObject* pObj2 = rhs->GetMarkedSdrObj();
    SdrObjList* pOL1 = pObj1 ? pObj1->getParentSdrObjListFromSdrObject() : nullptr;
    SdrObjList* pOL2 = pObj2 ? pObj2->getParentSdrObjListFromSdrObject() : nullptr;

    if (pOL1 == pOL2)
    {
        // AF: Note that I reverted a change from sal_uInt32 to sal_uLong (made
        // for 64bit compliance, #i78198#) because internally in SdrObject
        // both nOrdNum and mnNavigationPosition are stored as sal_uInt32.
        sal_uInt32 nObjOrd1(pObj1 ? pObj1->GetNavigationPosition() : 0);
        sal_uInt32 nObjOrd2(pObj2 ? pObj2->GetNavigationPosition() : 0);

        return nObjOrd1 < nObjOrd2;
    }
    else
    {
        return pOL1 < pOL2;
    }
}


void SdrMarkList::ForceSort() const
{
    if(!mbSorted)
    {
        const_cast<SdrMarkList*>(this)->ImpForceSort();
    }
}

void SdrMarkList::ImpForceSort()
{
    if(mbSorted)
        return;

    mbSorted = true;
    size_t nCount = maList.size();

    // remove invalid
    if(nCount > 0 )
    {
        std::erase_if(maList, [](std::unique_ptr<SdrMark>& rItem) { return rItem->GetMarkedSdrObj() == nullptr; });
        nCount = maList.size();
    }

    if(nCount <= 1)
        return;

    std::sort(maList.begin(), maList.end(), ImpSdrMarkListSorter);

    // remove duplicates
    if(maList.size() <= 1)
        return;

    SdrMark* pCurrent = maList.back().get();
    for (size_t count = maList.size() - 1; count; --count)
    {
        size_t i = count - 1;
        SdrMark* pCmp = maList[i].get();
        assert(pCurrent->GetMarkedSdrObj());
        if(pCurrent->GetMarkedSdrObj() == pCmp->GetMarkedSdrObj())
        {
            // Con1/Con2 Merging
            if(pCmp->IsCon1())
                pCurrent->SetCon1(true);

            if(pCmp->IsCon2())
                pCurrent->SetCon2(true);

            // delete pCmp
            maList.erase(maList.begin() + i);
        }
        else
        {
            pCurrent = pCmp;
        }
    }
}

void SdrMarkList::Clear()
{
    maList.clear();
    mbSorted = true//we're empty, so can be considered sorted
    SetNameDirty();
}

SdrMarkList& SdrMarkList::operator=(const SdrMarkList& rLst)
{
    if (this != &rLst)
    {
        Clear();

        for(size_t i = 0; i < rLst.GetMarkCount(); ++i)
        {
            SdrMark* pMark = rLst.GetMark(i);
            maList.emplace_back(new SdrMark(*pMark));
        }

        maMarkName = rLst.maMarkName;
        mbNameOk = rLst.mbNameOk;
        maPointName = rLst.maPointName;
        mbPointNameOk = rLst.mbPointNameOk;
        maGluePointName = rLst.maGluePointName;
        mbSorted = rLst.mbSorted;
    }
    return *this;
}

SdrMark* SdrMarkList::GetMark(size_t nNum) const
{
    return (nNum < maList.size()) ? maList[nNum].get() : nullptr;
}

size_t SdrMarkList::FindObject(const SdrObject* pObj) const
{
    // Since relying on OrdNums is not allowed for the selection because objects in the
    // selection may not be inserted in a list if they are e.g. modified ATM, i changed
    // this loop to just look if the object pointer is in the selection.

    // Problem is that GetOrdNum() which is const, internally casts to non-const and
    // hardly sets the OrdNum member of the object (nOrdNum) to 0 (ZERO) if the object
    // is not inserted in an object list.
    // Since this may be by purpose and necessary somewhere else i decided that it is
    // less dangerous to change this method then changing SdrObject::GetOrdNum().
    if(pObj)
    {
        for(size_t a = 0; a < maList.size(); ++a)
        {
            if(maList[a]->GetMarkedSdrObj() == pObj)
            {
                return a;
            }
        }
    }

    return SAL_MAX_SIZE;
}

void SdrMarkList::InsertEntry(const SdrMark& rMark, bool bChkSort)
{
    SetNameDirty();
    const size_t nCount(maList.size());

    if(!bChkSort || !mbSorted || nCount == 0)
    {
        if(!bChkSort)
            mbSorted = false;

        maList.emplace_back(new SdrMark(rMark));
    }
    else
    {
        SdrMark* pLast = GetMark(nCount - 1);
        const SdrObject* pLastObj = pLast->GetMarkedSdrObj();
        const SdrObject* pNewObj = rMark.GetMarkedSdrObj();

        if(pLastObj == pNewObj)
        {
            // This one already exists.
            // Con1/Con2 Merging
            if(rMark.IsCon1())
                pLast->SetCon1(true);

            if(rMark.IsCon2())
                pLast->SetCon2(true);
        }
        else
        {
            maList.emplace_back(new SdrMark(rMark));

            // now check if the sort is ok
            const SdrObjList* pLastOL = pLastObj!=nullptr ? pLastObj->getParentSdrObjListFromSdrObject() : nullptr;
            const SdrObjList* pNewOL = pNewObj !=nullptr ? pNewObj->getParentSdrObjListFromSdrObject() : nullptr;

            if(pLastOL == pNewOL)
            {
                const sal_uInt32 nLastNum(pLastObj!=nullptr ? pLastObj->GetOrdNum() : 0);
                const sal_uInt32 nNewNum(pNewObj !=nullptr ? pNewObj ->GetOrdNum() : 0);

                if(nNewNum < nLastNum)
                {
                    // at some point, we have to sort
                    mbSorted = false;
                }
            }
            else
            {
                // at some point, we have to sort
                mbSorted = false;
            }
        }
    }
}

void SdrMarkList::DeleteMark(size_t nNum)
{
    SdrMark* pMark = GetMark(nNum);
    DBG_ASSERT(pMark!=nullptr,"DeleteMark: MarkEntry not found.");

    if(pMark)
    {
        maList.erase(maList.begin() + nNum);
        if (maList.empty())
            mbSorted = true//we're empty, so can be considered sorted
        SetNameDirty();
    }
}

void SdrMarkList::ReplaceMark(const SdrMark& rNewMark, size_t nNum)
{
    SdrMark* pMark = GetMark(nNum);
    DBG_ASSERT(pMark!=nullptr,"ReplaceMark: MarkEntry not found.");

    if(pMark)
    {
        SetNameDirty();
        maList[nNum].reset(new SdrMark(rNewMark));
        mbSorted = false;
    }
}

void SdrMarkList::Merge(const SdrMarkList& rSrcList, bool bReverse)
{
    const size_t nCount(rSrcList.maList.size());

    if(rSrcList.mbSorted)
    {
        // merge without forcing a Sort in rSrcList
        bReverse = false;
    }

    if(!bReverse)
    {
        for(size_t i = 0; i < nCount; ++i)
        {
            SdrMark* pM = rSrcList.maList[i].get();
            InsertEntry(*pM);
        }
    }
    else
    {
        for(size_t i = nCount; i > 0;)
        {
            --i;
            SdrMark* pM = rSrcList.maList[i].get();
            InsertEntry(*pM);
        }
    }
}

bool SdrMarkList::DeletePageView(const SdrPageView& rPV)
{
    bool bChgd(false);

    for(auto it = maList.begin(); it != maList.end(); )
    {
        SdrMark* pMark = it->get();

        if(pMark->GetPageView()==&rPV)
        {
            it = maList.erase(it);
            SetNameDirty();
            bChgd = true;
        }
        else
            ++it;
    }

    return bChgd;
}

bool SdrMarkList::InsertPageView(const SdrPageView& rPV)
{
    bool bChgd(false);
    DeletePageView(rPV); // delete all of them, then append the entire page
    const SdrObjList* pOL = rPV.GetObjList();

    for (const rtl::Reference<SdrObject>& pObj : *pOL)
    {
        bool bDoIt(rPV.IsObjMarkable(pObj.get()));

        if(bDoIt)
        {
            maList.emplace_back(new SdrMark(pObj.get(), const_cast<SdrPageView*>(&rPV)));
            SetNameDirty();
            bChgd = true;
        }
    }

    return bChgd;
}

const OUString& SdrMarkList::GetMarkDescription() const
{
    const size_t nCount(GetMarkCount());

    if(mbNameOk && 1 == nCount)
    {
        // if it's a single selection, cache only text frame
        const SdrObject* pObj = GetMark(0)->GetMarkedSdrObj();
        const SdrTextObj* pTextObj = DynCastSdrTextObj( pObj );

        if(!pTextObj || !pTextObj->IsTextFrame())
        {
            const_cast<SdrMarkList*>(this)->mbNameOk = false;
        }
    }

    if(!mbNameOk)
    {
        SdrMark* pMark = GetMark(0);
        OUString aNam;

        if(!nCount)
        {
            const_cast<SdrMarkList*>(this)->maMarkName = SvxResId(STR_ObjNameNoObj);
        }
        else if(1 == nCount)
        {
            if(pMark->GetMarkedSdrObj())
            {
                aNam = pMark->GetMarkedSdrObj()->TakeObjNameSingul();
            }
        }
        else
        {
            if(pMark->GetMarkedSdrObj())
            {
                aNam = pMark->GetMarkedSdrObj()->TakeObjNamePlural();
                bool bEq(true);

                for(size_t i = 1; i < GetMarkCount() && bEq; ++i)
                {
                    SdrMark* pMark2 = GetMark(i);
                    OUString aStr1(pMark2->GetMarkedSdrObj()->TakeObjNamePlural());
                    bEq = aNam == aStr1;
                }

                if(!bEq)
                {
                    aNam = SvxResId(STR_ObjNamePlural);
                }
            }

            aNam = OUString::number( nCount ) + " " + aNam;
        }

        const_cast<SdrMarkList*>(this)->maMarkName = aNam;
        const_cast<SdrMarkList*>(this)->mbNameOk = true;
    }

    return maMarkName;
}

const OUString& SdrMarkList::GetPointMarkDescription(bool bGlue) const
{
    bool& rNameOk = const_cast<bool&>(bGlue ? mbGluePointNameOk : mbPointNameOk);
    OUString& rName = const_cast<OUString&>(bGlue ? maGluePointName : maPointName);
    const size_t nMarkCount(GetMarkCount());
    size_t nMarkPtCnt(0);
    size_t nMarkPtObjCnt(0);
    size_t n1stMarkNum(SAL_MAX_SIZE);

    for(size_t nMarkNum = 0; nMarkNum < nMarkCount; ++nMarkNum)
    {
        const SdrMark* pMark = GetMark(nMarkNum);
        const SdrUShortCont& rPts = bGlue ? pMark->GetMarkedGluePoints() : pMark->GetMarkedPoints();

        if (!rPts.empty())
        {
            if(n1stMarkNum == SAL_MAX_SIZE)
            {
                n1stMarkNum = nMarkNum;
            }

            nMarkPtCnt += rPts.size();
            nMarkPtObjCnt++;
        }

        if(nMarkPtObjCnt > 1 && rNameOk)
        {
            // preliminary decision
            return rName;
        }
    }

    if(rNameOk && 1 == nMarkPtObjCnt)
    {
        // if it's a single selection, cache only text frame
        const SdrObject* pObj = GetMark(0)->GetMarkedSdrObj();
        const SdrTextObj* pTextObj = DynCastSdrTextObj( pObj );

        if(!pTextObj || !pTextObj->IsTextFrame())
        {
            rNameOk = false;
        }
    }

    if(!nMarkPtObjCnt)
    {
        rName.clear();
        rNameOk = true;
    }
    else if(!rNameOk)
    {
        const SdrMark* pMark = GetMark(n1stMarkNum);
        OUString aNam;

        if(1 == nMarkPtObjCnt)
        {
            if(pMark->GetMarkedSdrObj())
            {
                aNam = pMark->GetMarkedSdrObj()->TakeObjNameSingul();
            }
        }
        else
        {
            if(pMark->GetMarkedSdrObj())
            {
                aNam = pMark->GetMarkedSdrObj()->TakeObjNamePlural();
            }

            bool bEq(true);

            for(size_t i = n1stMarkNum + 1; i < GetMarkCount() && bEq; ++i)
            {
                const SdrMark* pMark2 = GetMark(i);
                const SdrUShortCont& rPts = bGlue ? pMark2->GetMarkedGluePoints() : pMark2->GetMarkedPoints();

                if (!rPts.empty() && pMark2->GetMarkedSdrObj())
                {
                    OUString aStr1(pMark2->GetMarkedSdrObj()->TakeObjNamePlural());
                    bEq = aNam == aStr1;
                }
            }

            if(!bEq)
            {
                aNam = SvxResId(STR_ObjNamePlural);
            }

            aNam = OUString::number( nMarkPtObjCnt ) + " " + aNam;
        }

        OUString aStr1;

        if(1 == nMarkPtCnt)
        {
            aStr1 = SvxResId(bGlue ? STR_ViewMarkedGluePoint : STR_ViewMarkedPoint);
        }
        else
        {
            aStr1 = SvxResId(bGlue ? STR_ViewMarkedGluePoints : STR_ViewMarkedPoints);
            aStr1 = aStr1.replaceFirst("%2", OUString::number( nMarkPtCnt ));
        }

        aStr1 = aStr1.replaceFirst("%1", aNam);
        rName = aStr1;
        rNameOk = true;
    }

    return rName;
}

bool SdrMarkList::TakeBoundRect(SdrPageView const * pPV, tools::Rectangle& rRect) const
{
    bool bFnd(false);
    tools::Rectangle aR;

    for(size_t i = 0; i < GetMarkCount(); ++i)
    {
        SdrMark* pMark = GetMark(i);

        if(!pPV || pMark->GetPageView() == pPV)
        {
            if(pMark->GetMarkedSdrObj())
            {
                aR = pMark->GetMarkedSdrObj()->GetCurrentBoundRect();

                if(bFnd)
                {
                    rRect.Union(aR);
                }
                else
                {
                    rRect = aR;
                    bFnd = true;
                }
            }
        }
    }

    return bFnd;
}

bool SdrMarkList::TakeSnapRect(SdrPageView const * pPV, tools::Rectangle& rRect) const
{
    bool bFnd(false);

    for(size_t i = 0; i < GetMarkCount(); ++i)
    {
        SdrMark* pMark = GetMark(i);

        if(!pPV || pMark->GetPageView() == pPV)
        {
            if(pMark->GetMarkedSdrObj())
            {
                tools::Rectangle aR(pMark->GetMarkedSdrObj()->GetSnapRect());

                if(bFnd)
                {
                    rRect.Union(aR);
                }
                else
                {
                    rRect = aR;
                    bFnd = true;
                }
            }
        }
    }

    return bFnd;
}


namespace sdr
{
    ViewSelection::ViewSelection()
    :   mbEdgesOfMarkedNodesDirty(false)
    {
    }

    void ViewSelection::SetEdgesOfMarkedNodesDirty()
    {
        if(!mbEdgesOfMarkedNodesDirty)
        {
            mbEdgesOfMarkedNodesDirty = true;
            maEdgesOfMarkedNodes.Clear();
            maMarkedEdgesOfMarkedNodes.Clear();
            maAllMarkedObjects.clear();
        }
    }

    const SdrMarkList& ViewSelection::GetEdgesOfMarkedNodes() const
    {
        if(mbEdgesOfMarkedNodesDirty)
        {
            const_cast<ViewSelection*>(this)->ImpForceEdgesOfMarkedNodes();
        }

        return maEdgesOfMarkedNodes;
    }

    const SdrMarkList& ViewSelection::GetMarkedEdgesOfMarkedNodes() const
    {
        if(mbEdgesOfMarkedNodesDirty)
        {
            const_cast<ViewSelection*>(this)->ImpForceEdgesOfMarkedNodes();
        }

        return maMarkedEdgesOfMarkedNodes;
    }

    const std::vector<SdrObject*>& ViewSelection::GetAllMarkedObjects() const
    {
        if(mbEdgesOfMarkedNodesDirty)
            const_cast<ViewSelection*>(this)->ImpForceEdgesOfMarkedNodes();

        return maAllMarkedObjects;
    }

    void ViewSelection::ImplCollectCompleteSelection(SdrObject* pObj)
    {
        if(!pObj)
            return;

        bool bIsGroup(pObj->IsGroupObject());

        if(bIsGroup && DynCastE3dObject(pObj) != nullptr && DynCastE3dScene(pObj) == nullptr)
        {
            bIsGroup = false;
        }

        if(bIsGroup)
        {
            SdrObjList* pList = pObj->GetSubList();

            for (const rtl::Reference<SdrObject>& pObj2 : *pList)
                ImplCollectCompleteSelection(pObj2.get());
        }

        maAllMarkedObjects.push_back(pObj);
    }

    void ViewSelection::ImpForceEdgesOfMarkedNodes()
    {
        if(!mbEdgesOfMarkedNodesDirty)
            return;

        mbEdgesOfMarkedNodesDirty = false;
        maMarkedObjectList.ForceSort();
        maEdgesOfMarkedNodes.Clear();
        maMarkedEdgesOfMarkedNodes.Clear();
        maAllMarkedObjects.clear();

        // GetMarkCount after ForceSort
        const size_t nMarkCount(maMarkedObjectList.GetMarkCount());

        for(size_t a = 0; a < nMarkCount; ++a)
        {
            SdrObject* pCandidate = maMarkedObjectList.GetMark(a)->GetMarkedSdrObj();
            if(!pCandidate)
                continue;

            // build transitive hull
            ImplCollectCompleteSelection(pCandidate);

            // travel over broadcaster/listener to access edges connected to the selected object
            const SfxBroadcaster* pBC = pCandidate->GetBroadcaster();
            if(!pBC)
                continue;

            pBC->ForAllListeners(
                [this, &pCandidate, &a] (SfxListener* pLst)
                {
                    SdrEdgeObj* pEdge = dynamic_cast<SdrEdgeObj*>( pLst );

                    if(pEdge && pEdge->IsInserted() && pEdge->getSdrPageFromSdrObject() == pCandidate->getSdrPageFromSdrObject())
                    {
                        SdrMark aM(pEdge, maMarkedObjectList.GetMark(a)->GetPageView());

                        if(pEdge->GetConnectedNode(true) == pCandidate)
                        {
                            aM.SetCon1(true);
                        }

                        if(pEdge->GetConnectedNode(false) == pCandidate)
                        {
                            aM.SetCon2(true);
                        }

                        if(SAL_MAX_SIZE == maMarkedObjectList.FindObject(pEdge))
                        {
                            // check if it itself is selected
                            maEdgesOfMarkedNodes.InsertEntry(aM);
                        }
                        else
                        {
                            maMarkedEdgesOfMarkedNodes.InsertEntry(aM);
                        }
                    }
                    return false;
                });
        }
        maEdgesOfMarkedNodes.ForceSort();
        maMarkedEdgesOfMarkedNodes.ForceSort();
    }
// end of namespace sdr

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

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

¤ Dauer der Verarbeitung: 0.6 Sekunden  ¤

*© 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.