1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 #include <svx/svdmrkv.hxx>
22 #include <svx/svdpagv.hxx>
23 #include <osl/diagnose.h>
29 bool SdrMarkView::HasMarkablePoints() const
33 if (!ImpIsFrameHandles()) {
34 const size_t nMarkCount
=GetMarkedObjectCount();
35 if (nMarkCount
<=static_cast<size_t>(mnFrameHandlesLimit
)) {
36 for (size_t nMarkNum
=0; nMarkNum
<nMarkCount
&& !bRet
; ++nMarkNum
) {
37 const SdrMark
* pM
=GetSdrMarkByIndex(nMarkNum
);
38 const SdrObject
* pObj
=pM
->GetMarkedSdrObj();
39 bRet
=pObj
->IsPolyObj();
46 sal_Int32
SdrMarkView::GetMarkablePointCount() const
50 if (!ImpIsFrameHandles()) {
51 const size_t nMarkCount
=GetMarkedObjectCount();
52 if (nMarkCount
<=static_cast<size_t>(mnFrameHandlesLimit
)) {
53 for (size_t nMarkNum
=0; nMarkNum
<nMarkCount
; ++nMarkNum
) {
54 const SdrMark
* pM
=GetSdrMarkByIndex(nMarkNum
);
55 const SdrObject
* pObj
=pM
->GetMarkedSdrObj();
56 if (pObj
->IsPolyObj()) {
57 nCount
+=pObj
->GetPointCount();
65 bool SdrMarkView::HasMarkedPoints() const
69 if (!ImpIsFrameHandles()) {
70 const size_t nMarkCount
=GetMarkedObjectCount();
71 if (nMarkCount
<=static_cast<size_t>(mnFrameHandlesLimit
)) {
72 for (size_t nMarkNum
=0; nMarkNum
<nMarkCount
&& !bRet
; ++nMarkNum
) {
73 const SdrMark
* pM
=GetSdrMarkByIndex(nMarkNum
);
74 const SdrUShortCont
& rPts
= pM
->GetMarkedPoints();
82 bool SdrMarkView::IsPointMarkable(const SdrHdl
& rHdl
) const
84 return !ImpIsFrameHandles() && !rHdl
.IsPlusHdl() && rHdl
.GetKind()!=SdrHdlKind::Glue
&& rHdl
.GetKind()!=SdrHdlKind::SmartTag
&& rHdl
.GetObj()!=nullptr && rHdl
.GetObj()->IsPolyObj();
87 bool SdrMarkView::MarkPointHelper(SdrHdl
* pHdl
, SdrMark
* pMark
, bool bUnmark
)
89 return ImpMarkPoint( pHdl
, pMark
, bUnmark
);
92 bool SdrMarkView::ImpMarkPoint(SdrHdl
* pHdl
, SdrMark
* pMark
, bool bUnmark
)
94 if (pHdl
==nullptr || pHdl
->IsPlusHdl() || pHdl
->GetKind()==SdrHdlKind::Glue
)
97 if (pHdl
->IsSelected() != bUnmark
)
100 SdrObject
* pObj
=pHdl
->GetObj();
101 if (pObj
==nullptr || !pObj
->IsPolyObj())
106 const size_t nMarkNum
=TryToFindMarkedObject(pObj
);
107 if (nMarkNum
==SAL_MAX_SIZE
)
109 pMark
=GetSdrMarkByIndex(nMarkNum
);
111 const sal_uInt32
nHdlNum(pHdl
->GetObjHdlNum());
112 SdrUShortCont
& rPts
=pMark
->GetMarkedPoints();
115 rPts
.insert(static_cast<sal_uInt16
>(nHdlNum
));
119 SdrUShortCont::const_iterator it
= rPts
.find( static_cast<sal_uInt16
>(nHdlNum
) );
120 if (it
!= rPts
.end())
126 return false; // error case!
130 pHdl
->SetSelected(!bUnmark
);
131 if (!mbPlusHdlAlways
)
135 SdrHdlList
plusList(nullptr);
136 pObj
->AddToPlusHdlList(plusList
, *pHdl
);
137 sal_uInt32
nCount(plusList
.GetHdlCount());
138 for (sal_uInt32 i
=0; i
<nCount
; i
++)
140 SdrHdl
* pPlusHdl
=plusList
.GetHdl(i
);
141 pPlusHdl
->SetObj(pObj
);
142 pPlusHdl
->SetPageView(pMark
->GetPageView());
143 pPlusHdl
->SetPlusHdl(true);
145 plusList
.MoveTo(maHdlList
);
149 for (size_t i
= maHdlList
.GetHdlCount(); i
>0;)
152 SdrHdl
* pPlusHdl
=maHdlList
.GetHdl(i
);
153 if (pPlusHdl
->IsPlusHdl() && pPlusHdl
->GetSourceHdlNum()==nHdlNum
)
155 maHdlList
.RemoveHdl(i
);
167 bool SdrMarkView::MarkPoint(SdrHdl
& rHdl
, bool bUnmark
)
169 ForceUndirtyMrkPnt();
171 const SdrObject
* pObj
=rHdl
.GetObj();
172 if (IsPointMarkable(rHdl
) && rHdl
.IsSelected()==bUnmark
) {
173 const size_t nMarkNum
=TryToFindMarkedObject(pObj
);
174 if (nMarkNum
!=SAL_MAX_SIZE
) {
175 SdrMark
* pM
=GetSdrMarkByIndex(nMarkNum
);
176 if (ImpMarkPoint(&rHdl
,pM
,bUnmark
)) {
177 MarkListHasChanged();
186 bool SdrMarkView::MarkPoints(const tools::Rectangle
* pRect
, bool bUnmark
)
188 ForceUndirtyMrkPnt();
191 const SdrObject
* pObj0
=nullptr;
192 const SdrPageView
* pPV0
=nullptr;
195 const size_t nHdlCnt
=maHdlList
.GetHdlCount();
196 for (size_t nHdlNum
=nHdlCnt
; nHdlNum
>0;) {
198 SdrHdl
* pHdl
=maHdlList
.GetHdl(nHdlNum
);
199 if (IsPointMarkable(*pHdl
) && pHdl
->IsSelected()==bUnmark
) {
200 const SdrObject
* pObj
=pHdl
->GetObj();
201 const SdrPageView
* pPV
=pHdl
->GetPageView();
202 if (pObj
!=pObj0
|| pPV
!=pPV0
|| pM
==nullptr) { // This section is for optimization,
203 const size_t nMarkNum
=TryToFindMarkedObject(pObj
); // so ImpMarkPoint() doesn't always
204 if (nMarkNum
!=SAL_MAX_SIZE
) { // have to search the object in the MarkList.
205 pM
=GetSdrMarkByIndex(nMarkNum
);
210 if (pObj
->IsInserted()) {
211 OSL_FAIL("SdrMarkView::MarkPoints(const Rectangle* pRect): Selected object not found.");
217 Point
aPos(pHdl
->GetPos());
218 if (pM
!=nullptr && (pRect
==nullptr || pRect
->Contains(aPos
))) {
219 if (ImpMarkPoint(pHdl
,pM
,bUnmark
)) bChgd
=true;
224 MarkListHasChanged();
230 void SdrMarkView::MarkNextPoint()
232 ForceUndirtyMrkPnt();
236 const tools::Rectangle
& SdrMarkView::GetMarkedPointsRect() const
238 ForceUndirtyMrkPnt();
239 if (mbMarkedPointsRectsDirty
) ImpSetPointsRects();
240 return maMarkedPointsRect
;
243 void SdrMarkView::SetPlusHandlesAlwaysVisible(bool bOn
)
244 { // TODO: Optimize HandlePaint!
245 ForceUndirtyMrkPnt();
246 if (bOn
!=mbPlusHdlAlways
) {
248 SetMarkHandles(nullptr);
249 MarkListHasChanged();
254 // ImpSetPointsRects() is for PolyPoints and GluePoints!
257 void SdrMarkView::ImpSetPointsRects() const
259 tools::Rectangle aPnts
;
260 tools::Rectangle aGlue
;
261 const size_t nHdlCnt
=maHdlList
.GetHdlCount();
262 for (size_t nHdlNum
=0; nHdlNum
<nHdlCnt
; ++nHdlNum
) {
263 const SdrHdl
* pHdl
=maHdlList
.GetHdl(nHdlNum
);
264 SdrHdlKind eKind
=pHdl
->GetKind();
265 if ((eKind
==SdrHdlKind::Poly
&& pHdl
->IsSelected()) || eKind
==SdrHdlKind::Glue
) {
266 Point
aPt(pHdl
->GetPos());
267 tools::Rectangle
& rR
=eKind
==SdrHdlKind::Glue
? aGlue
: aPnts
;
269 rR
=tools::Rectangle(aPt
,aPt
);
271 if (aPt
.X()<rR
.Left ()) rR
.SetLeft(aPt
.X() );
272 if (aPt
.X()>rR
.Right ()) rR
.SetRight(aPt
.X() );
273 if (aPt
.Y()<rR
.Top ()) rR
.SetTop(aPt
.Y() );
274 if (aPt
.Y()>rR
.Bottom()) rR
.SetBottom(aPt
.Y() );
278 const_cast<SdrMarkView
*>(this)->maMarkedPointsRect
=aPnts
;
279 const_cast<SdrMarkView
*>(this)->maMarkedGluePointsRect
=aGlue
;
280 const_cast<SdrMarkView
*>(this)->mbMarkedPointsRectsDirty
=false;
284 // UndirtyMrkPnt() is for PolyPoints and GluePoints!
287 void SdrMarkView::UndirtyMrkPnt() const
290 const size_t nMarkCount
=GetMarkedObjectCount();
291 for (size_t nMarkNum
=0; nMarkNum
<nMarkCount
; ++nMarkNum
) {
292 SdrMark
* pM
=GetSdrMarkByIndex(nMarkNum
);
293 const SdrObject
* pObj
=pM
->GetMarkedSdrObj();
296 SdrUShortCont
& rPts
= pM
->GetMarkedPoints();
297 if (pObj
->IsPolyObj()) {
298 // Remove invalid selected points, that is, all
299 // entries above the number of points in the object.
300 sal_uInt32
nMax(pObj
->GetPointCount());
302 SdrUShortCont::const_iterator it
= rPts
.lower_bound(nMax
);
303 if( it
!= rPts
.end() )
305 rPts
.erase(it
, rPts
.end());
313 // only fail *if* there are marked points
314 OSL_FAIL("SdrMarkView::UndirtyMrkPnt(): Selected points on an object that is not a PolyObj!");
323 SdrUShortCont
& rPts
= pM
->GetMarkedGluePoints();
324 const SdrGluePointList
* pGPL
=pObj
->GetGluePointList();
326 // Remove invalid selected gluepoints, that is, all entries
327 // (IDs) that aren't contained in the GluePointList of the
329 for(SdrUShortCont::const_iterator it
= rPts
.begin(); it
!= rPts
.end(); )
332 if (pGPL
->FindGluePoint(nId
)==SDRGLUEPOINT_NOTFOUND
) {
341 rPts
.clear(); // object doesn't have any gluepoints (any more)
347 if (bChg
) const_cast<SdrMarkView
*>(this)->mbMarkedPointsRectsDirty
=true;
348 const_cast<SdrMarkView
*>(this)->mbMrkPntDirty
=false;
352 bool SdrMarkView::HasMarkableGluePoints() const
355 if (IsGluePointEditMode()) {
356 ForceUndirtyMrkPnt();
357 const size_t nMarkCount
=GetMarkedObjectCount();
358 for (size_t nMarkNum
=0; nMarkNum
<nMarkCount
&& !bRet
; ++nMarkNum
) {
359 const SdrMark
* pM
=GetSdrMarkByIndex(nMarkNum
);
360 const SdrObject
* pObj
=pM
->GetMarkedSdrObj();
361 const SdrGluePointList
* pGPL
=pObj
->GetGluePointList();
364 if(pGPL
&& pGPL
->GetCount())
366 for(sal_uInt16
a(0); !bRet
&& a
< pGPL
->GetCount(); a
++)
368 if((*pGPL
)[a
].IsUserDefined())
379 bool SdrMarkView::HasMarkedGluePoints() const
381 ForceUndirtyMrkPnt();
383 const size_t nMarkCount
=GetMarkedObjectCount();
384 for (size_t nMarkNum
=0; nMarkNum
<nMarkCount
&& !bRet
; ++nMarkNum
) {
385 const SdrMark
* pM
=GetSdrMarkByIndex(nMarkNum
);
386 const SdrUShortCont
& rPts
= pM
->GetMarkedGluePoints();
387 bRet
= !rPts
.empty();
392 bool SdrMarkView::MarkGluePoints(const tools::Rectangle
* pRect
, bool bUnmark
)
394 if (!IsGluePointEditMode() && !bUnmark
) return false;
395 ForceUndirtyMrkPnt();
398 const size_t nMarkCount
=GetMarkedObjectCount();
399 for (size_t nMarkNum
=0; nMarkNum
<nMarkCount
; ++nMarkNum
) {
400 SdrMark
* pM
=GetSdrMarkByIndex(nMarkNum
);
401 const SdrObject
* pObj
=pM
->GetMarkedSdrObj();
402 const SdrGluePointList
* pGPL
=pObj
->GetGluePointList();
403 SdrUShortCont
& rPts
= pM
->GetMarkedGluePoints();
404 if (bUnmark
&& pRect
==nullptr) { // UnmarkAll
411 sal_uInt16 nGluePointCnt
=pGPL
->GetCount();
412 for (sal_uInt16 nGPNum
=0; nGPNum
<nGluePointCnt
; nGPNum
++) {
413 const SdrGluePoint
& rGP
=(*pGPL
)[nGPNum
];
416 if(rGP
.IsUserDefined())
418 Point
aPos(rGP
.GetAbsolutePos(*pObj
));
419 if (pRect
==nullptr || pRect
->Contains(aPos
)) {
420 bool bContains
= rPts
.find( rGP
.GetId() ) != rPts
.end();
421 if (!bUnmark
&& !bContains
) {
423 rPts
.insert(rGP
.GetId());
425 if (bUnmark
&& bContains
) {
427 rPts
.erase(rGP
.GetId());
437 MarkListHasChanged();
442 bool SdrMarkView::PickGluePoint(const Point
& rPnt
, SdrObject
*& rpObj
, sal_uInt16
& rnId
, SdrPageView
*& rpPV
) const
444 rpObj
=nullptr; rpPV
=nullptr; rnId
=0;
445 if (!IsGluePointEditMode()) return false;
446 OutputDevice
* pOut
=mpActualOutDev
.get();
447 if (pOut
==nullptr) pOut
=GetFirstOutputDevice();
448 if (pOut
==nullptr) return false;
450 const size_t nMarkCount
=GetMarkedObjectCount();
451 size_t nMarkNum
=nMarkCount
;
454 const SdrMark
* pM
=GetSdrMarkByIndex(nMarkNum
);
455 SdrObject
* pObj
=pM
->GetMarkedSdrObj();
456 SdrPageView
* pPV
=pM
->GetPageView();
457 const SdrGluePointList
* pGPL
=pObj
->GetGluePointList();
459 sal_uInt16 nNum
=pGPL
->HitTest(rPnt
,*pOut
,pObj
);
460 if (nNum
!=SDRGLUEPOINT_NOTFOUND
)
463 const SdrGluePoint
& rCandidate
= (*pGPL
)[nNum
];
465 if(rCandidate
.IsUserDefined())
468 rnId
=(*pGPL
)[nNum
].GetId();
478 bool SdrMarkView::MarkGluePoint(const SdrObject
* pObj
, sal_uInt16 nId
, bool bUnmark
)
480 if (!IsGluePointEditMode()) return false;
481 ForceUndirtyMrkPnt();
484 const size_t nMarkPos
=TryToFindMarkedObject(pObj
);
485 if (nMarkPos
!=SAL_MAX_SIZE
) {
486 SdrMark
* pM
=GetSdrMarkByIndex(nMarkPos
);
487 SdrUShortCont
& rPts
= pM
->GetMarkedGluePoints();
488 bool bContains
= rPts
.find( nId
) != rPts
.end();
489 if (!bUnmark
&& !bContains
) {
493 if (bUnmark
&& bContains
) {
498 // TODO: implement implicit selection of objects
503 MarkListHasChanged();
508 bool SdrMarkView::IsGluePointMarked(const SdrObject
* pObj
, sal_uInt16 nId
) const
510 ForceUndirtyMrkPnt();
512 const size_t nPos
=TryToFindMarkedObject(pObj
); // casting to NonConst
513 if (nPos
!=SAL_MAX_SIZE
) {
514 const SdrMark
* pM
=GetSdrMarkByIndex(nPos
);
515 const SdrUShortCont
& rPts
= pM
->GetMarkedGluePoints();
516 bRet
= rPts
.find( nId
) != rPts
.end();
521 SdrHdl
* SdrMarkView::GetGluePointHdl(const SdrObject
* pObj
, sal_uInt16 nId
) const
523 ForceUndirtyMrkPnt();
524 const size_t nHdlCnt
=maHdlList
.GetHdlCount();
525 for (size_t nHdlNum
=0; nHdlNum
<nHdlCnt
; ++nHdlNum
) {
526 SdrHdl
* pHdl
=maHdlList
.GetHdl(nHdlNum
);
527 if (pHdl
->GetObj()==pObj
&&
528 pHdl
->GetKind()==SdrHdlKind::Glue
&&
529 pHdl
->GetObjHdlNum()==nId
) return pHdl
;
534 void SdrMarkView::MarkNextGluePoint()
536 ForceUndirtyMrkPnt();
540 const tools::Rectangle
& SdrMarkView::GetMarkedGluePointsRect() const
542 ForceUndirtyMrkPnt();
543 if (mbMarkedPointsRectsDirty
) ImpSetPointsRects();
544 return maMarkedGluePointsRect
;
547 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */