diff options
Diffstat (limited to 'svx/source/svdraw/svdmrkv1.cxx')
-rw-r--r-- | svx/source/svdraw/svdmrkv1.cxx | 547 |
1 files changed, 547 insertions, 0 deletions
diff --git a/svx/source/svdraw/svdmrkv1.cxx b/svx/source/svdraw/svdmrkv1.cxx new file mode 100644 index 0000000000..9c732262bc --- /dev/null +++ b/svx/source/svdraw/svdmrkv1.cxx @@ -0,0 +1,547 @@ +/* -*- 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/svdmrkv.hxx> +#include <svx/svdpagv.hxx> +#include <osl/diagnose.h> + + +// Point Selection + + +bool SdrMarkView::HasMarkablePoints() const +{ + ForceUndirtyMrkPnt(); + bool bRet=false; + if (!ImpIsFrameHandles()) { + const size_t nMarkCount=GetMarkedObjectCount(); + if (nMarkCount<=static_cast<size_t>(mnFrameHandlesLimit)) { + for (size_t nMarkNum=0; nMarkNum<nMarkCount && !bRet; ++nMarkNum) { + const SdrMark* pM=GetSdrMarkByIndex(nMarkNum); + const SdrObject* pObj=pM->GetMarkedSdrObj(); + bRet=pObj->IsPolyObj(); + } + } + } + return bRet; +} + +sal_Int32 SdrMarkView::GetMarkablePointCount() const +{ + ForceUndirtyMrkPnt(); + sal_Int32 nCount=0; + if (!ImpIsFrameHandles()) { + const size_t nMarkCount=GetMarkedObjectCount(); + if (nMarkCount<=static_cast<size_t>(mnFrameHandlesLimit)) { + for (size_t nMarkNum=0; nMarkNum<nMarkCount; ++nMarkNum) { + const SdrMark* pM=GetSdrMarkByIndex(nMarkNum); + const SdrObject* pObj=pM->GetMarkedSdrObj(); + if (pObj->IsPolyObj()) { + nCount+=pObj->GetPointCount(); + } + } + } + } + return nCount; +} + +bool SdrMarkView::HasMarkedPoints() const +{ + ForceUndirtyMrkPnt(); + bool bRet=false; + if (!ImpIsFrameHandles()) { + const size_t nMarkCount=GetMarkedObjectCount(); + if (nMarkCount<=static_cast<size_t>(mnFrameHandlesLimit)) { + for (size_t nMarkNum=0; nMarkNum<nMarkCount && !bRet; ++nMarkNum) { + const SdrMark* pM=GetSdrMarkByIndex(nMarkNum); + const SdrUShortCont& rPts = pM->GetMarkedPoints(); + bRet = !rPts.empty(); + } + } + } + return bRet; +} + +bool SdrMarkView::IsPointMarkable(const SdrHdl& rHdl) const +{ + return !ImpIsFrameHandles() && !rHdl.IsPlusHdl() && rHdl.GetKind()!=SdrHdlKind::Glue && rHdl.GetKind()!=SdrHdlKind::SmartTag && rHdl.GetObj()!=nullptr && rHdl.GetObj()->IsPolyObj(); +} + +bool SdrMarkView::MarkPointHelper(SdrHdl* pHdl, SdrMark* pMark, bool bUnmark) +{ + return ImpMarkPoint( pHdl, pMark, bUnmark ); +} + +bool SdrMarkView::ImpMarkPoint(SdrHdl* pHdl, SdrMark* pMark, bool bUnmark) +{ + if (pHdl==nullptr || pHdl->IsPlusHdl() || pHdl->GetKind()==SdrHdlKind::Glue) + return false; + + if (pHdl->IsSelected() != bUnmark) + return false; + + SdrObject* pObj=pHdl->GetObj(); + if (pObj==nullptr || !pObj->IsPolyObj()) + return false; + + if (pMark==nullptr) + { + const size_t nMarkNum=TryToFindMarkedObject(pObj); + if (nMarkNum==SAL_MAX_SIZE) + return false; + pMark=GetSdrMarkByIndex(nMarkNum); + } + const sal_uInt32 nHdlNum(pHdl->GetObjHdlNum()); + SdrUShortCont& rPts=pMark->GetMarkedPoints(); + if (!bUnmark) + { + rPts.insert(static_cast<sal_uInt16>(nHdlNum)); + } + else + { + SdrUShortCont::const_iterator it = rPts.find( static_cast<sal_uInt16>(nHdlNum) ); + if (it != rPts.end()) + { + rPts.erase(it); + } + else + { + return false; // error case! + } + } + + pHdl->SetSelected(!bUnmark); + if (!mbPlusHdlAlways) + { + if (!bUnmark) + { + SdrHdlList plusList(nullptr); + pObj->AddToPlusHdlList(plusList, *pHdl); + sal_uInt32 nCount(plusList.GetHdlCount()); + for (sal_uInt32 i=0; i<nCount; i++) + { + SdrHdl* pPlusHdl=plusList.GetHdl(i); + pPlusHdl->SetObj(pObj); + pPlusHdl->SetPageView(pMark->GetPageView()); + pPlusHdl->SetPlusHdl(true); + } + plusList.MoveTo(maHdlList); + } + else + { + for (size_t i = maHdlList.GetHdlCount(); i>0;) + { + --i; + SdrHdl* pPlusHdl=maHdlList.GetHdl(i); + if (pPlusHdl->IsPlusHdl() && pPlusHdl->GetSourceHdlNum()==nHdlNum) + { + maHdlList.RemoveHdl(i); + } + } + } + } + + maHdlList.Sort(); + + return true; +} + + +bool SdrMarkView::MarkPoint(SdrHdl& rHdl, bool bUnmark) +{ + ForceUndirtyMrkPnt(); + bool bRet=false; + const SdrObject* pObj=rHdl.GetObj(); + if (IsPointMarkable(rHdl) && rHdl.IsSelected()==bUnmark) { + const size_t nMarkNum=TryToFindMarkedObject(pObj); + if (nMarkNum!=SAL_MAX_SIZE) { + SdrMark* pM=GetSdrMarkByIndex(nMarkNum); + if (ImpMarkPoint(&rHdl,pM,bUnmark)) { + MarkListHasChanged(); + bRet=true; + } + } + } + + return bRet; +} + +bool SdrMarkView::MarkPoints(const tools::Rectangle* pRect, bool bUnmark) +{ + ForceUndirtyMrkPnt(); + bool bChgd=false; + SortMarkedObjects(); + const SdrObject* pObj0=nullptr; + const SdrPageView* pPV0=nullptr; + SdrMark* pM=nullptr; + maHdlList.Sort(); + const size_t nHdlCnt=maHdlList.GetHdlCount(); + for (size_t nHdlNum=nHdlCnt; nHdlNum>0;) { + --nHdlNum; + SdrHdl* pHdl=maHdlList.GetHdl(nHdlNum); + if (IsPointMarkable(*pHdl) && pHdl->IsSelected()==bUnmark) { + const SdrObject* pObj=pHdl->GetObj(); + const SdrPageView* pPV=pHdl->GetPageView(); + if (pObj!=pObj0 || pPV!=pPV0 || pM==nullptr) { // This section is for optimization, + const size_t nMarkNum=TryToFindMarkedObject(pObj); // so ImpMarkPoint() doesn't always + if (nMarkNum!=SAL_MAX_SIZE) { // have to search the object in the MarkList. + pM=GetSdrMarkByIndex(nMarkNum); + pObj0=pObj; + pPV0=pPV; + } else { +#ifdef DBG_UTIL + if (pObj->IsInserted()) { + OSL_FAIL("SdrMarkView::MarkPoints(const Rectangle* pRect): Selected object not found."); + } +#endif + pM=nullptr; + } + } + Point aPos(pHdl->GetPos()); + if (pM!=nullptr && (pRect==nullptr || pRect->Contains(aPos))) { + if (ImpMarkPoint(pHdl,pM,bUnmark)) bChgd=true; + } + } + } + if (bChgd) { + MarkListHasChanged(); + } + + return bChgd; +} + +void SdrMarkView::MarkNextPoint() +{ + ForceUndirtyMrkPnt(); + SortMarkedObjects(); +} + +const tools::Rectangle& SdrMarkView::GetMarkedPointsRect() const +{ + ForceUndirtyMrkPnt(); + if (mbMarkedPointsRectsDirty) ImpSetPointsRects(); + return maMarkedPointsRect; +} + +void SdrMarkView::SetPlusHandlesAlwaysVisible(bool bOn) +{ // TODO: Optimize HandlePaint! + ForceUndirtyMrkPnt(); + if (bOn!=mbPlusHdlAlways) { + mbPlusHdlAlways=bOn; + SetMarkHandles(nullptr); + MarkListHasChanged(); + } +} + + +// ImpSetPointsRects() is for PolyPoints and GluePoints! + + +void SdrMarkView::ImpSetPointsRects() const +{ + tools::Rectangle aPnts; + tools::Rectangle aGlue; + const size_t nHdlCnt=maHdlList.GetHdlCount(); + for (size_t nHdlNum=0; nHdlNum<nHdlCnt; ++nHdlNum) { + const SdrHdl* pHdl=maHdlList.GetHdl(nHdlNum); + SdrHdlKind eKind=pHdl->GetKind(); + if ((eKind==SdrHdlKind::Poly && pHdl->IsSelected()) || eKind==SdrHdlKind::Glue) { + Point aPt(pHdl->GetPos()); + tools::Rectangle& rR=eKind==SdrHdlKind::Glue ? aGlue : aPnts; + if (rR.IsEmpty()) { + rR=tools::Rectangle(aPt,aPt); + } else { + if (aPt.X()<rR.Left ()) rR.SetLeft(aPt.X() ); + if (aPt.X()>rR.Right ()) rR.SetRight(aPt.X() ); + if (aPt.Y()<rR.Top ()) rR.SetTop(aPt.Y() ); + if (aPt.Y()>rR.Bottom()) rR.SetBottom(aPt.Y() ); + } + } + } + const_cast<SdrMarkView*>(this)->maMarkedPointsRect=aPnts; + const_cast<SdrMarkView*>(this)->maMarkedGluePointsRect=aGlue; + const_cast<SdrMarkView*>(this)->mbMarkedPointsRectsDirty=false; +} + + +// UndirtyMrkPnt() is for PolyPoints and GluePoints! + + +void SdrMarkView::UndirtyMrkPnt() const +{ + bool bChg=false; + const size_t nMarkCount=GetMarkedObjectCount(); + for (size_t nMarkNum=0; nMarkNum<nMarkCount; ++nMarkNum) { + SdrMark* pM=GetSdrMarkByIndex(nMarkNum); + const SdrObject* pObj=pM->GetMarkedSdrObj(); + // PolyPoints + { + SdrUShortCont& rPts = pM->GetMarkedPoints(); + if (pObj->IsPolyObj()) { + // Remove invalid selected points, that is, all + // entries above the number of points in the object. + sal_uInt32 nMax(pObj->GetPointCount()); + + SdrUShortCont::const_iterator it = rPts.lower_bound(nMax); + if( it != rPts.end() ) + { + rPts.erase(it, rPts.end()); + bChg = true; + } + } + else + { + if (!rPts.empty()) + { + // only fail *if* there are marked points + OSL_FAIL("SdrMarkView::UndirtyMrkPnt(): Selected points on an object that is not a PolyObj!"); + rPts.clear(); + bChg = true; + } + } + } + + // GluePoints + { + SdrUShortCont& rPts = pM->GetMarkedGluePoints(); + const SdrGluePointList* pGPL=pObj->GetGluePointList(); + if (pGPL!=nullptr) { + // Remove invalid selected gluepoints, that is, all entries + // (IDs) that aren't contained in the GluePointList of the + // object + for(SdrUShortCont::const_iterator it = rPts.begin(); it != rPts.end(); ) + { + sal_uInt16 nId=*it; + if (pGPL->FindGluePoint(nId)==SDRGLUEPOINT_NOTFOUND) { + it = rPts.erase(it); + bChg=true; + } + else + ++it; + } + } else { + if (!rPts.empty()) { + rPts.clear(); // object doesn't have any gluepoints (any more) + bChg=true; + } + } + } + } + if (bChg) const_cast<SdrMarkView*>(this)->mbMarkedPointsRectsDirty=true; + const_cast<SdrMarkView*>(this)->mbMrkPntDirty=false; +} + + +bool SdrMarkView::HasMarkableGluePoints() const +{ + bool bRet=false; + if (IsGluePointEditMode()) { + ForceUndirtyMrkPnt(); + const size_t nMarkCount=GetMarkedObjectCount(); + for (size_t nMarkNum=0; nMarkNum<nMarkCount && !bRet; ++nMarkNum) { + const SdrMark* pM=GetSdrMarkByIndex(nMarkNum); + const SdrObject* pObj=pM->GetMarkedSdrObj(); + const SdrGluePointList* pGPL=pObj->GetGluePointList(); + + // #i38892# + if(pGPL && pGPL->GetCount()) + { + for(sal_uInt16 a(0); !bRet && a < pGPL->GetCount(); a++) + { + if((*pGPL)[a].IsUserDefined()) + { + bRet = true; + } + } + } + } + } + return bRet; +} + +bool SdrMarkView::HasMarkedGluePoints() const +{ + ForceUndirtyMrkPnt(); + bool bRet=false; + const size_t nMarkCount=GetMarkedObjectCount(); + for (size_t nMarkNum=0; nMarkNum<nMarkCount && !bRet; ++nMarkNum) { + const SdrMark* pM=GetSdrMarkByIndex(nMarkNum); + const SdrUShortCont& rPts = pM->GetMarkedGluePoints(); + bRet = !rPts.empty(); + } + return bRet; +} + +bool SdrMarkView::MarkGluePoints(const tools::Rectangle* pRect, bool bUnmark) +{ + if (!IsGluePointEditMode() && !bUnmark) return false; + ForceUndirtyMrkPnt(); + bool bChgd=false; + SortMarkedObjects(); + const size_t nMarkCount=GetMarkedObjectCount(); + for (size_t nMarkNum=0; nMarkNum<nMarkCount; ++nMarkNum) { + SdrMark* pM=GetSdrMarkByIndex(nMarkNum); + const SdrObject* pObj=pM->GetMarkedSdrObj(); + const SdrGluePointList* pGPL=pObj->GetGluePointList(); + SdrUShortCont& rPts = pM->GetMarkedGluePoints(); + if (bUnmark && pRect==nullptr) { // UnmarkAll + if (!rPts.empty()) { + rPts.clear(); + bChgd=true; + } + } else { + if (pGPL!=nullptr) { + sal_uInt16 nGluePointCnt=pGPL->GetCount(); + for (sal_uInt16 nGPNum=0; nGPNum<nGluePointCnt; nGPNum++) { + const SdrGluePoint& rGP=(*pGPL)[nGPNum]; + + // #i38892# + if(rGP.IsUserDefined()) + { + Point aPos(rGP.GetAbsolutePos(*pObj)); + if (pRect==nullptr || pRect->Contains(aPos)) { + bool bContains = rPts.find( rGP.GetId() ) != rPts.end(); + if (!bUnmark && !bContains) { + bChgd=true; + rPts.insert(rGP.GetId()); + } + if (bUnmark && bContains) { + bChgd=true; + rPts.erase(rGP.GetId()); + } + } + } + } + } + } + } + if (bChgd) { + AdjustMarkHdl(); + MarkListHasChanged(); + } + return bChgd; +} + +bool SdrMarkView::PickGluePoint(const Point& rPnt, SdrObject*& rpObj, sal_uInt16& rnId, SdrPageView*& rpPV) const +{ + rpObj=nullptr; rpPV=nullptr; rnId=0; + if (!IsGluePointEditMode()) return false; + OutputDevice* pOut=mpActualOutDev.get(); + if (pOut==nullptr) pOut=GetFirstOutputDevice(); + if (pOut==nullptr) return false; + SortMarkedObjects(); + const size_t nMarkCount=GetMarkedObjectCount(); + size_t nMarkNum=nMarkCount; + while (nMarkNum>0) { + nMarkNum--; + const SdrMark* pM=GetSdrMarkByIndex(nMarkNum); + SdrObject* pObj=pM->GetMarkedSdrObj(); + SdrPageView* pPV=pM->GetPageView(); + const SdrGluePointList* pGPL=pObj->GetGluePointList(); + if (pGPL!=nullptr) { + sal_uInt16 nNum=pGPL->HitTest(rPnt,*pOut,pObj); + if (nNum!=SDRGLUEPOINT_NOTFOUND) + { + // #i38892# + const SdrGluePoint& rCandidate = (*pGPL)[nNum]; + + if(rCandidate.IsUserDefined()) + { + rpObj=pObj; + rnId=(*pGPL)[nNum].GetId(); + rpPV=pPV; + return true; + } + } + } + } + return false; +} + +bool SdrMarkView::MarkGluePoint(const SdrObject* pObj, sal_uInt16 nId, bool bUnmark) +{ + if (!IsGluePointEditMode()) return false; + ForceUndirtyMrkPnt(); + bool bChgd=false; + if (pObj!=nullptr) { + const size_t nMarkPos=TryToFindMarkedObject(pObj); + if (nMarkPos!=SAL_MAX_SIZE) { + SdrMark* pM=GetSdrMarkByIndex(nMarkPos); + SdrUShortCont& rPts = pM->GetMarkedGluePoints(); + bool bContains = rPts.find( nId ) != rPts.end(); + if (!bUnmark && !bContains) { + bChgd=true; + rPts.insert(nId); + } + if (bUnmark && bContains) { + bChgd=true; + rPts.erase(nId); + } + } else { + // TODO: implement implicit selection of objects + } + } + if (bChgd) { + AdjustMarkHdl(); + MarkListHasChanged(); + } + return bChgd; +} + +bool SdrMarkView::IsGluePointMarked(const SdrObject* pObj, sal_uInt16 nId) const +{ + ForceUndirtyMrkPnt(); + bool bRet=false; + const size_t nPos=TryToFindMarkedObject(pObj); // casting to NonConst + if (nPos!=SAL_MAX_SIZE) { + const SdrMark* pM=GetSdrMarkByIndex(nPos); + const SdrUShortCont& rPts = pM->GetMarkedGluePoints(); + bRet = rPts.find( nId ) != rPts.end(); + } + return bRet; +} + +SdrHdl* SdrMarkView::GetGluePointHdl(const SdrObject* pObj, sal_uInt16 nId) const +{ + ForceUndirtyMrkPnt(); + const size_t nHdlCnt=maHdlList.GetHdlCount(); + for (size_t nHdlNum=0; nHdlNum<nHdlCnt; ++nHdlNum) { + SdrHdl* pHdl=maHdlList.GetHdl(nHdlNum); + if (pHdl->GetObj()==pObj && + pHdl->GetKind()==SdrHdlKind::Glue && + pHdl->GetObjHdlNum()==nId ) return pHdl; + } + return nullptr; +} + +void SdrMarkView::MarkNextGluePoint() +{ + ForceUndirtyMrkPnt(); + SortMarkedObjects(); +} + +const tools::Rectangle& SdrMarkView::GetMarkedGluePointsRect() const +{ + ForceUndirtyMrkPnt(); + if (mbMarkedPointsRectsDirty) ImpSetPointsRects(); + return maMarkedGluePointsRect; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |