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/svdetc.hxx>
23 #include <svx/svdoedge.hxx>
24 #include "svx/svdglob.hxx"
25 #include <svx/svdpagv.hxx>
26 #include <svx/svdpage.hxx>
27 #include "svddrgm1.hxx"
29 ////////////////////////////////////////////////////////////////////////////////////////////////////
31 ////////////////////////////////////////////////////////////////////////////////////////////////////
33 sal_Bool
SdrMarkView::HasMarkablePoints() const
37 if (!ImpIsFrameHandles()) {
38 sal_uIntPtr nMarkAnz
=GetMarkedObjectCount();
39 if (nMarkAnz
<=nFrameHandlesLimit
) {
40 for (sal_uIntPtr nMarkNum
=0; nMarkNum
<nMarkAnz
&& !bRet
; nMarkNum
++) {
41 const SdrMark
* pM
=GetSdrMarkByIndex(nMarkNum
);
42 const SdrObject
* pObj
=pM
->GetMarkedSdrObj();
43 bRet
=pObj
->IsPolyObj();
50 sal_uIntPtr
SdrMarkView::GetMarkablePointCount() const
54 if (!ImpIsFrameHandles()) {
55 sal_uIntPtr nMarkAnz
=GetMarkedObjectCount();
56 if (nMarkAnz
<=nFrameHandlesLimit
) {
57 for (sal_uIntPtr nMarkNum
=0; nMarkNum
<nMarkAnz
; nMarkNum
++) {
58 const SdrMark
* pM
=GetSdrMarkByIndex(nMarkNum
);
59 const SdrObject
* pObj
=pM
->GetMarkedSdrObj();
60 if (pObj
->IsPolyObj()) {
61 nAnz
+=pObj
->GetPointCount();
69 sal_Bool
SdrMarkView::HasMarkedPoints() const
72 sal_Bool bRet
=sal_False
;
73 if (!ImpIsFrameHandles()) {
74 sal_uIntPtr nMarkAnz
=GetMarkedObjectCount();
75 if (nMarkAnz
<=nFrameHandlesLimit
) {
76 for (sal_uIntPtr nMarkNum
=0; nMarkNum
<nMarkAnz
&& !bRet
; nMarkNum
++) {
77 const SdrMark
* pM
=GetSdrMarkByIndex(nMarkNum
);
78 const SdrUShortCont
* pPts
=pM
->GetMarkedPoints();
79 bRet
=pPts
!=NULL
&& !pPts
->empty();
86 sal_uIntPtr
SdrMarkView::GetMarkedPointCount() const
90 if (!ImpIsFrameHandles()) {
91 sal_uIntPtr nMarkAnz
=GetMarkedObjectCount();
92 if (nMarkAnz
<=nFrameHandlesLimit
) {
93 for (sal_uIntPtr nMarkNum
=0; nMarkNum
<nMarkAnz
; nMarkNum
++) {
94 const SdrMark
* pM
=GetSdrMarkByIndex(nMarkNum
);
95 const SdrUShortCont
* pPts
=pM
->GetMarkedPoints();
96 if (pPts
!=NULL
) nAnz
+=pPts
->size();
103 sal_Bool
SdrMarkView::IsPointMarkable(const SdrHdl
& rHdl
) const
105 return !ImpIsFrameHandles() && &rHdl
!=NULL
&& !rHdl
.IsPlusHdl() && rHdl
.GetKind()!=HDL_GLUE
&& rHdl
.GetKind()!=HDL_SMARTTAG
&& rHdl
.GetObj()!=NULL
&& rHdl
.GetObj()->IsPolyObj();
108 sal_Bool
SdrMarkView::MarkPointHelper(SdrHdl
* pHdl
, SdrMark
* pMark
, sal_Bool bUnmark
)
110 return ImpMarkPoint( pHdl
, pMark
, bUnmark
);
113 sal_Bool
SdrMarkView::ImpMarkPoint(SdrHdl
* pHdl
, SdrMark
* pMark
, sal_Bool bUnmark
)
115 if (pHdl
==NULL
|| pHdl
->IsPlusHdl() || pHdl
->GetKind()==HDL_GLUE
)
118 if (pHdl
->IsSelected() != bUnmark
)
121 SdrObject
* pObj
=pHdl
->GetObj();
122 if (pObj
==NULL
|| !pObj
->IsPolyObj())
127 sal_uIntPtr nMarkNum
=TryToFindMarkedObject(pObj
);
128 if (nMarkNum
==CONTAINER_ENTRY_NOTFOUND
)
130 pMark
=GetSdrMarkByIndex(nMarkNum
);
132 const sal_uInt32
nHdlNum(pHdl
->GetObjHdlNum());
133 SdrUShortCont
* pPts
=pMark
->ForceMarkedPoints();
136 pPts
->insert((sal_uInt16
)nHdlNum
);
140 SdrUShortCont::const_iterator it
= pPts
->find( (sal_uInt16
)nHdlNum
);
141 if (it
!= pPts
->end())
147 return sal_False
; // error case!
151 pHdl
->SetSelected(!bUnmark
);
156 sal_uInt32
nAnz(pObj
->GetPlusHdlCount(*pHdl
));
157 for (sal_uInt32 i
=0; i
<nAnz
; i
++)
159 SdrHdl
* pPlusHdl
=pObj
->GetPlusHdl(*pHdl
,i
);
162 pPlusHdl
->SetObj(pObj
);
163 pPlusHdl
->SetPageView(pMark
->GetPageView());
164 pPlusHdl
->SetPlusHdl(sal_True
);
165 aHdl
.AddHdl(pPlusHdl
);
171 for (sal_uIntPtr i
= aHdl
.GetHdlCount(); i
>0;)
174 SdrHdl
* pPlusHdl
=aHdl
.GetHdl(i
);
175 if (pPlusHdl
->IsPlusHdl() && pPlusHdl
->GetSourceHdlNum()==nHdlNum
)
190 sal_Bool
SdrMarkView::MarkPoint(SdrHdl
& rHdl
, sal_Bool bUnmark
)
192 if (&rHdl
==NULL
) return sal_False
;
193 ForceUndirtyMrkPnt();
194 sal_Bool bRet
=sal_False
;
195 const SdrObject
* pObj
=rHdl
.GetObj();
196 if (IsPointMarkable(rHdl
) && rHdl
.IsSelected()==bUnmark
) {
197 sal_uIntPtr nMarkNum
=TryToFindMarkedObject(pObj
);
198 if (nMarkNum
!=CONTAINER_ENTRY_NOTFOUND
) {
199 SdrMark
* pM
=GetSdrMarkByIndex(nMarkNum
);
200 pM
->ForceMarkedPoints();
201 if (ImpMarkPoint(&rHdl
,pM
,bUnmark
)) {
202 MarkListHasChanged();
211 sal_Bool
SdrMarkView::MarkPoints(const Rectangle
* pRect
, sal_Bool bUnmark
)
213 ForceUndirtyMrkPnt();
214 sal_Bool bChgd
=sal_False
;
216 const SdrObject
* pObj0
=NULL
;
217 const SdrPageView
* pPV0
=NULL
;
220 sal_uIntPtr nHdlAnz
=aHdl
.GetHdlCount();
221 for (sal_uIntPtr nHdlNum
=nHdlAnz
; nHdlNum
>0;) {
223 SdrHdl
* pHdl
=aHdl
.GetHdl(nHdlNum
);
224 if (IsPointMarkable(*pHdl
) && pHdl
->IsSelected()==bUnmark
) {
225 const SdrObject
* pObj
=pHdl
->GetObj();
226 const SdrPageView
* pPV
=pHdl
->GetPageView();
227 if (pObj
!=pObj0
|| pPV
!=pPV0
|| pM
==NULL
) { // This section is for optimization,
228 sal_uIntPtr nMarkNum
=TryToFindMarkedObject(pObj
); // so ImpMarkPoint() doesn't always
229 if (nMarkNum
!=CONTAINER_ENTRY_NOTFOUND
) { // have to search the object in the MarkList.
230 pM
=GetSdrMarkByIndex(nMarkNum
);
233 pM
->ForceMarkedPoints();
236 if (pObj
->IsInserted()) {
237 OSL_FAIL("SdrMarkView::MarkPoints(const Rectangle* pRect): Selected object not found.");
243 Point
aPos(pHdl
->GetPos());
244 if (pM
!=NULL
&& (pRect
==NULL
|| pRect
->IsInside(aPos
))) {
245 if (ImpMarkPoint(pHdl
,pM
,bUnmark
)) bChgd
=sal_True
;
250 MarkListHasChanged();
256 sal_Bool
SdrMarkView::MarkNextPoint(const Point
& /*rPnt*/, sal_Bool
/*bPrev*/)
258 ForceUndirtyMrkPnt();
259 sal_Bool bChgd
=sal_False
;
263 MarkListHasChanged();
268 const Rectangle
& SdrMarkView::GetMarkedPointsRect() const
270 ForceUndirtyMrkPnt();
271 if (bMarkedPointsRectsDirty
) ImpSetPointsRects();
272 return aMarkedPointsRect
;
275 void SdrMarkView::SetPlusHandlesAlwaysVisible(sal_Bool bOn
)
276 { // TODO: Optimize HandlePaint!
277 ForceUndirtyMrkPnt();
278 if (bOn
!=bPlusHdlAlways
) {
281 MarkListHasChanged();
285 ////////////////////////////////////////////////////////////////////////////////////////////////////
286 // ImpSetPointsRects() is for PolyPoints and GluePoints!
287 ////////////////////////////////////////////////////////////////////////////////////////////////////
289 void SdrMarkView::ImpSetPointsRects() const
293 sal_uIntPtr nHdlAnz
=aHdl
.GetHdlCount();
294 for (sal_uIntPtr nHdlNum
=0; nHdlNum
<nHdlAnz
; nHdlNum
++) {
295 const SdrHdl
* pHdl
=aHdl
.GetHdl(nHdlNum
);
296 SdrHdlKind eKind
=pHdl
->GetKind();
297 if ((eKind
==HDL_POLY
&& pHdl
->IsSelected()) || eKind
==HDL_GLUE
) {
298 Point
aPt(pHdl
->GetPos());
299 Rectangle
& rR
=eKind
==HDL_GLUE
? aGlue
: aPnts
;
301 rR
=Rectangle(aPt
,aPt
);
303 if (aPt
.X()<rR
.Left ()) rR
.Left ()=aPt
.X();
304 if (aPt
.X()>rR
.Right ()) rR
.Right ()=aPt
.X();
305 if (aPt
.Y()<rR
.Top ()) rR
.Top ()=aPt
.Y();
306 if (aPt
.Y()>rR
.Bottom()) rR
.Bottom()=aPt
.Y();
310 ((SdrMarkView
*)this)->aMarkedPointsRect
=aPnts
;
311 ((SdrMarkView
*)this)->aMarkedGluePointsRect
=aGlue
;
312 ((SdrMarkView
*)this)->bMarkedPointsRectsDirty
=sal_False
;
315 ////////////////////////////////////////////////////////////////////////////////////////////////////
316 // UndirtyMrkPnt() is for PolyPoints and GluePoints!
317 ////////////////////////////////////////////////////////////////////////////////////////////////////
319 void SdrMarkView::UndirtyMrkPnt() const
321 sal_Bool bChg
=sal_False
;
322 sal_uIntPtr nMarkAnz
=GetMarkedObjectCount();
323 for (sal_uIntPtr nMarkNum
=0; nMarkNum
<nMarkAnz
; nMarkNum
++) {
324 SdrMark
* pM
=GetSdrMarkByIndex(nMarkNum
);
325 const SdrObject
* pObj
=pM
->GetMarkedSdrObj();
327 SdrUShortCont
* pPts
=pM
->GetMarkedPoints();
329 if (pObj
->IsPolyObj()) {
330 // Remove invalid selected points, that is, all
331 // entries above the number of points in the object.
332 sal_uInt32
nMax(pObj
->GetPointCount());
334 SdrUShortCont::const_iterator it
= pPts
->lower_bound(nMax
);
335 if( it
!= pPts
->end() )
337 pPts
->erase(it
, pPts
->end() );
343 OSL_FAIL("SdrMarkView::UndirtyMrkPnt(): Selected points on an object that is not a PolyObj!");
344 if(pPts
&& !pPts
->empty())
353 pPts
=pM
->GetMarkedGluePoints();
354 const SdrGluePointList
* pGPL
=pObj
->GetGluePointList();
357 // Remove invalid selected glue points, that is, all entries
358 // (IDs) that aren't contained in the GluePointList of the
360 for(SdrUShortCont::const_iterator it
= pPts
->begin(); it
!= pPts
->end(); )
363 if (pGPL
->FindGluePoint(nId
)==SDRGLUEPOINT_NOTFOUND
) {
371 if (pPts
!=NULL
&& !pPts
->empty()) {
372 pPts
->clear(); // object doesn't have any glue points (any more)
378 if (bChg
) ((SdrMarkView
*)this)->bMarkedPointsRectsDirty
=sal_True
;
379 ((SdrMarkView
*)this)->bMrkPntDirty
=sal_False
;
382 ////////////////////////////////////////////////////////////////////////////////////////////////////
384 sal_Bool
SdrMarkView::HasMarkableGluePoints() const
386 sal_Bool bRet
=sal_False
;
387 if (IsGluePointEditMode()) {
388 ForceUndirtyMrkPnt();
389 sal_uIntPtr nMarkAnz
=GetMarkedObjectCount();
390 for (sal_uIntPtr nMarkNum
=0; nMarkNum
<nMarkAnz
&& !bRet
; nMarkNum
++) {
391 const SdrMark
* pM
=GetSdrMarkByIndex(nMarkNum
);
392 const SdrObject
* pObj
=pM
->GetMarkedSdrObj();
393 const SdrGluePointList
* pGPL
=pObj
->GetGluePointList();
396 if(pGPL
&& pGPL
->GetCount())
398 for(sal_uInt16
a(0); !bRet
&& a
< pGPL
->GetCount(); a
++)
400 if((*pGPL
)[a
].IsUserDefined())
411 sal_Bool
SdrMarkView::HasMarkedGluePoints() const
413 ForceUndirtyMrkPnt();
414 sal_Bool bRet
=sal_False
;
415 sal_uIntPtr nMarkAnz
=GetMarkedObjectCount();
416 for (sal_uIntPtr nMarkNum
=0; nMarkNum
<nMarkAnz
&& !bRet
; nMarkNum
++) {
417 const SdrMark
* pM
=GetSdrMarkByIndex(nMarkNum
);
418 const SdrUShortCont
* pPts
=pM
->GetMarkedGluePoints();
419 bRet
=pPts
!=NULL
&& !pPts
->empty();
424 sal_Bool
SdrMarkView::MarkGluePoints(const Rectangle
* pRect
, sal_Bool bUnmark
)
426 if (!IsGluePointEditMode() && !bUnmark
) return sal_False
;
427 ForceUndirtyMrkPnt();
428 sal_Bool bChgd
=sal_False
;
430 sal_uIntPtr nMarkAnz
=GetMarkedObjectCount();
431 for (sal_uIntPtr nMarkNum
=0; nMarkNum
<nMarkAnz
; nMarkNum
++) {
432 SdrMark
* pM
=GetSdrMarkByIndex(nMarkNum
);
433 const SdrObject
* pObj
=pM
->GetMarkedSdrObj();
434 const SdrGluePointList
* pGPL
=pObj
->GetGluePointList();
435 SdrUShortCont
* pPts
=pM
->GetMarkedGluePoints();
436 if (bUnmark
&& pRect
==NULL
) { // UnmarkAll
437 if (pPts
!=NULL
&& !pPts
->empty()) {
442 if (pGPL
!=NULL
&& (pPts
!=NULL
|| !bUnmark
)) {
443 sal_uInt16 nGPAnz
=pGPL
->GetCount();
444 for (sal_uInt16 nGPNum
=0; nGPNum
<nGPAnz
; nGPNum
++) {
445 const SdrGluePoint
& rGP
=(*pGPL
)[nGPNum
];
448 if(rGP
.IsUserDefined())
450 Point
aPos(rGP
.GetAbsolutePos(*pObj
));
451 if (pRect
==NULL
|| pRect
->IsInside(aPos
)) {
453 pPts
=pM
->ForceMarkedGluePoints();
454 bool bContains
= pPts
->find( rGP
.GetId() ) != pPts
->end();
455 if (!bUnmark
&& !bContains
) {
457 pPts
->insert(rGP
.GetId());
459 if (bUnmark
&& bContains
) {
461 pPts
->erase(rGP
.GetId());
471 MarkListHasChanged();
476 sal_Bool
SdrMarkView::PickGluePoint(const Point
& rPnt
, SdrObject
*& rpObj
, sal_uInt16
& rnId
, SdrPageView
*& rpPV
, sal_uIntPtr nOptions
) const
478 SdrObject
* pObj0
=rpObj
;
479 sal_uInt16 nId0
=rnId
;
480 rpObj
=NULL
; rpPV
=NULL
; rnId
=0;
481 if (!IsGluePointEditMode()) return sal_False
;
482 sal_Bool bBack
=(nOptions
& SDRSEARCH_BACKWARD
) !=0;
483 sal_Bool bNext
=(nOptions
& SDRSEARCH_NEXT
) !=0;
484 OutputDevice
* pOut
=(OutputDevice
*)pActualOutDev
;
485 if (pOut
==NULL
) pOut
=GetFirstOutputDevice();
486 if (pOut
==NULL
) return sal_False
;
488 sal_uIntPtr nMarkAnz
=GetMarkedObjectCount();
489 sal_uIntPtr nMarkNum
=bBack
? 0 : nMarkAnz
;
491 nMarkNum
=((SdrMarkView
*)this)->TryToFindMarkedObject(pObj0
);
492 if (nMarkNum
==CONTAINER_ENTRY_NOTFOUND
) return sal_False
;
493 if (!bBack
) nMarkNum
++;
495 while (bBack
? nMarkNum
<nMarkAnz
: nMarkNum
>0) {
496 if (!bBack
) nMarkNum
--;
497 const SdrMark
* pM
=GetSdrMarkByIndex(nMarkNum
);
498 SdrObject
* pObj
=pM
->GetMarkedSdrObj();
499 SdrPageView
* pPV
=pM
->GetPageView();
500 const SdrGluePointList
* pGPL
=pObj
->GetGluePointList();
502 sal_uInt16 nNum
=pGPL
->HitTest(rPnt
,*pOut
,pObj
,bBack
,bNext
,nId0
);
503 if (nNum
!=SDRGLUEPOINT_NOTFOUND
)
506 const SdrGluePoint
& rCandidate
= (*pGPL
)[nNum
];
508 if(rCandidate
.IsUserDefined())
511 rnId
=(*pGPL
)[nNum
].GetId();
517 bNext
=sal_False
; // HitNextGluePoint only for the first Obj
518 if (bBack
) nMarkNum
++;
523 sal_Bool
SdrMarkView::MarkGluePoint(const SdrObject
* pObj
, sal_uInt16 nId
, const SdrPageView
* /*pPV*/, sal_Bool bUnmark
)
525 if (!IsGluePointEditMode()) return sal_False
;
526 ForceUndirtyMrkPnt();
527 sal_Bool bChgd
=sal_False
;
529 sal_uIntPtr nMarkPos
=TryToFindMarkedObject(pObj
);
530 if (nMarkPos
!=CONTAINER_ENTRY_NOTFOUND
) {
531 SdrMark
* pM
=GetSdrMarkByIndex(nMarkPos
);
532 SdrUShortCont
* pPts
=bUnmark
? pM
->GetMarkedGluePoints() : pM
->ForceMarkedGluePoints();
534 bool bContains
= pPts
->find( nId
) != pPts
->end();
535 if (!bUnmark
&& !bContains
) {
539 if (bUnmark
&& bContains
) {
545 // TODO: implement implicit selection of objects
550 MarkListHasChanged();
555 sal_Bool
SdrMarkView::IsGluePointMarked(const SdrObject
* pObj
, sal_uInt16 nId
) const
557 ForceUndirtyMrkPnt();
558 sal_Bool bRet
=sal_False
;
559 sal_uIntPtr nPos
=((SdrMarkView
*)this)->TryToFindMarkedObject(pObj
); // casting to NonConst
560 if (nPos
!=CONTAINER_ENTRY_NOTFOUND
) {
561 const SdrMark
* pM
=GetSdrMarkByIndex(nPos
);
562 const SdrUShortCont
* pPts
=pM
->GetMarkedGluePoints();
564 bRet
= pPts
->find( nId
) != pPts
->end();
570 SdrHdl
* SdrMarkView::GetGluePointHdl(const SdrObject
* pObj
, sal_uInt16 nId
) const
572 ForceUndirtyMrkPnt();
573 sal_uIntPtr nHdlAnz
=aHdl
.GetHdlCount();
574 for (sal_uIntPtr nHdlNum
=0; nHdlNum
<nHdlAnz
; nHdlNum
++) {
575 SdrHdl
* pHdl
=aHdl
.GetHdl(nHdlNum
);
576 if (pHdl
->GetObj()==pObj
&&
577 pHdl
->GetKind()==HDL_GLUE
&&
578 pHdl
->GetObjHdlNum()==nId
) return pHdl
;
583 sal_Bool
SdrMarkView::MarkNextGluePoint(const Point
& /*rPnt*/, sal_Bool
/*bPrev*/)
585 ForceUndirtyMrkPnt();
586 sal_Bool bChgd
=sal_False
;
590 MarkListHasChanged();
595 const Rectangle
& SdrMarkView::GetMarkedGluePointsRect() const
597 ForceUndirtyMrkPnt();
598 if (bMarkedPointsRectsDirty
) ImpSetPointsRects();
599 return aMarkedGluePointsRect
;
602 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */