1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*************************************************************************
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6 * Copyright 2000, 2010 Oracle and/or its affiliates.
8 * OpenOffice.org - a multi-platform office productivity suite
10 * This file is part of OpenOffice.org.
12 * OpenOffice.org is free software: you can redistribute it and/or modify
13 * it under the terms of the GNU Lesser General Public License version 3
14 * only, as published by the Free Software Foundation.
16 * OpenOffice.org is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU Lesser General Public License version 3 for more details
20 * (a copy is included in the LICENSE file that accompanied this code).
22 * You should have received a copy of the GNU Lesser General Public License
23 * version 3 along with OpenOffice.org. If not, see
24 * <http://www.openoffice.org/license.html>
25 * for a copy of the LGPLv3 License.
27 ************************************************************************/
30 #include <svx/svdmrkv.hxx>
31 #include <svx/svdetc.hxx>
32 #include <svx/svdoedge.hxx>
33 #include "svx/svdglob.hxx"
34 #include <svx/svdpagv.hxx>
35 #include <svx/svdpage.hxx>
36 #include "svddrgm1.hxx"
38 ////////////////////////////////////////////////////////////////////////////////////////////////////
40 ////////////////////////////////////////////////////////////////////////////////////////////////////
42 sal_Bool
SdrMarkView::HasMarkablePoints() const
46 if (!ImpIsFrameHandles()) {
47 sal_uIntPtr nMarkAnz
=GetMarkedObjectCount();
48 if (nMarkAnz
<=nFrameHandlesLimit
) {
49 for (sal_uIntPtr nMarkNum
=0; nMarkNum
<nMarkAnz
&& !bRet
; nMarkNum
++) {
50 const SdrMark
* pM
=GetSdrMarkByIndex(nMarkNum
);
51 const SdrObject
* pObj
=pM
->GetMarkedSdrObj();
52 bRet
=pObj
->IsPolyObj();
59 sal_uIntPtr
SdrMarkView::GetMarkablePointCount() const
63 if (!ImpIsFrameHandles()) {
64 sal_uIntPtr nMarkAnz
=GetMarkedObjectCount();
65 if (nMarkAnz
<=nFrameHandlesLimit
) {
66 for (sal_uIntPtr nMarkNum
=0; nMarkNum
<nMarkAnz
; nMarkNum
++) {
67 const SdrMark
* pM
=GetSdrMarkByIndex(nMarkNum
);
68 const SdrObject
* pObj
=pM
->GetMarkedSdrObj();
69 if (pObj
->IsPolyObj()) {
70 nAnz
+=pObj
->GetPointCount();
78 sal_Bool
SdrMarkView::HasMarkedPoints() const
81 sal_Bool bRet
=sal_False
;
82 if (!ImpIsFrameHandles()) {
83 sal_uIntPtr nMarkAnz
=GetMarkedObjectCount();
84 if (nMarkAnz
<=nFrameHandlesLimit
) {
85 for (sal_uIntPtr nMarkNum
=0; nMarkNum
<nMarkAnz
&& !bRet
; nMarkNum
++) {
86 const SdrMark
* pM
=GetSdrMarkByIndex(nMarkNum
);
87 const SdrUShortCont
* pPts
=pM
->GetMarkedPoints();
88 bRet
=pPts
!=NULL
&& pPts
->GetCount()!=0;
95 sal_uIntPtr
SdrMarkView::GetMarkedPointCount() const
99 if (!ImpIsFrameHandles()) {
100 sal_uIntPtr nMarkAnz
=GetMarkedObjectCount();
101 if (nMarkAnz
<=nFrameHandlesLimit
) {
102 for (sal_uIntPtr nMarkNum
=0; nMarkNum
<nMarkAnz
; nMarkNum
++) {
103 const SdrMark
* pM
=GetSdrMarkByIndex(nMarkNum
);
104 const SdrUShortCont
* pPts
=pM
->GetMarkedPoints();
105 if (pPts
!=NULL
) nAnz
+=pPts
->GetCount();
112 sal_Bool
SdrMarkView::IsPointMarkable(const SdrHdl
& rHdl
) const
114 return !ImpIsFrameHandles() && &rHdl
!=NULL
&& !rHdl
.IsPlusHdl() && rHdl
.GetKind()!=HDL_GLUE
&& rHdl
.GetKind()!=HDL_SMARTTAG
&& rHdl
.GetObj()!=NULL
&& rHdl
.GetObj()->IsPolyObj();
117 sal_Bool
SdrMarkView::MarkPointHelper(SdrHdl
* pHdl
, SdrMark
* pMark
, sal_Bool bUnmark
)
119 return ImpMarkPoint( pHdl
, pMark
, bUnmark
);
122 sal_Bool
SdrMarkView::ImpMarkPoint(SdrHdl
* pHdl
, SdrMark
* pMark
, sal_Bool bUnmark
)
124 if (pHdl
==NULL
|| pHdl
->IsPlusHdl() || pHdl
->GetKind()==HDL_GLUE
)
127 if (pHdl
->IsSelected() != bUnmark
)
130 SdrObject
* pObj
=pHdl
->GetObj();
131 if (pObj
==NULL
|| !pObj
->IsPolyObj())
136 sal_uIntPtr nMarkNum
=TryToFindMarkedObject(pObj
);
137 if (nMarkNum
==CONTAINER_ENTRY_NOTFOUND
)
139 pMark
=GetSdrMarkByIndex(nMarkNum
);
141 const sal_uInt32
nHdlNum(pHdl
->GetObjHdlNum());
142 SdrUShortCont
* pPts
=pMark
->ForceMarkedPoints();
145 pPts
->Insert((sal_uInt16
)nHdlNum
);
149 sal_uIntPtr nBla
=pPts
->GetPos((sal_uInt16
)nHdlNum
);
150 if (nBla
!=CONTAINER_ENTRY_NOTFOUND
)
156 return sal_False
; // error case!
160 pHdl
->SetSelected(!bUnmark
);
165 sal_uInt32
nAnz(pObj
->GetPlusHdlCount(*pHdl
));
166 for (sal_uInt32 i
=0; i
<nAnz
; i
++)
168 SdrHdl
* pPlusHdl
=pObj
->GetPlusHdl(*pHdl
,i
);
171 pPlusHdl
->SetObj(pObj
);
172 pPlusHdl
->SetPageView(pMark
->GetPageView());
173 pPlusHdl
->SetPlusHdl(sal_True
);
174 aHdl
.AddHdl(pPlusHdl
);
180 for (sal_uIntPtr i
= aHdl
.GetHdlCount(); i
>0;)
183 SdrHdl
* pPlusHdl
=aHdl
.GetHdl(i
);
184 if (pPlusHdl
->IsPlusHdl() && pPlusHdl
->GetSourceHdlNum()==nHdlNum
)
199 sal_Bool
SdrMarkView::MarkPoint(SdrHdl
& rHdl
, sal_Bool bUnmark
)
201 if (&rHdl
==NULL
) return sal_False
;
202 ForceUndirtyMrkPnt();
203 sal_Bool bRet
=sal_False
;
204 const SdrObject
* pObj
=rHdl
.GetObj();
205 if (IsPointMarkable(rHdl
) && rHdl
.IsSelected()==bUnmark
) {
206 sal_uIntPtr nMarkNum
=TryToFindMarkedObject(pObj
);
207 if (nMarkNum
!=CONTAINER_ENTRY_NOTFOUND
) {
208 SdrMark
* pM
=GetSdrMarkByIndex(nMarkNum
);
209 SdrUShortCont
* pPts
=pM
->ForceMarkedPoints();
211 if (ImpMarkPoint(&rHdl
,pM
,bUnmark
)) {
213 MarkListHasChanged();
222 sal_Bool
SdrMarkView::MarkPoints(const Rectangle
* pRect
, sal_Bool bUnmark
)
224 ForceUndirtyMrkPnt();
225 sal_Bool bChgd
=sal_False
;
227 const SdrObject
* pObj0
=NULL
;
228 const SdrPageView
* pPV0
=NULL
;
231 sal_uIntPtr nHdlAnz
=aHdl
.GetHdlCount();
232 for (sal_uIntPtr nHdlNum
=nHdlAnz
; nHdlNum
>0;) {
234 SdrHdl
* pHdl
=aHdl
.GetHdl(nHdlNum
);
235 if (IsPointMarkable(*pHdl
) && pHdl
->IsSelected()==bUnmark
) {
236 const SdrObject
* pObj
=pHdl
->GetObj();
237 const SdrPageView
* pPV
=pHdl
->GetPageView();
238 if (pObj
!=pObj0
|| pPV
!=pPV0
|| pM
==NULL
) { // This section is for optimization,
240 SdrUShortCont
* pPts
=pM
->GetMarkedPoints();
241 if (pPts
!=NULL
) pPts
->ForceSort();
243 sal_uIntPtr nMarkNum
=TryToFindMarkedObject(pObj
); // so ImpMarkPoint() doesn't always
244 if (nMarkNum
!=CONTAINER_ENTRY_NOTFOUND
) { // have to search the object in the MarkList.
245 pM
=GetSdrMarkByIndex(nMarkNum
);
248 SdrUShortCont
* pPts
=pM
->ForceMarkedPoints();
252 if (pObj
->IsInserted()) {
253 OSL_FAIL("SdrMarkView::MarkPoints(const Rectangle* pRect): Selected object not found.");
259 Point
aPos(pHdl
->GetPos());
260 if (pM
!=NULL
&& (pRect
==NULL
|| pRect
->IsInside(aPos
))) {
261 if (ImpMarkPoint(pHdl
,pM
,bUnmark
)) bChgd
=sal_True
;
265 if (pM
!=NULL
) { // Clean up the last selected MarkEntry, if necessary
266 SdrUShortCont
* pPts
=pM
->GetMarkedPoints();
267 if (pPts
!=NULL
) pPts
->ForceSort();
270 MarkListHasChanged();
276 sal_Bool
SdrMarkView::MarkNextPoint(const Point
& /*rPnt*/, sal_Bool
/*bPrev*/)
278 ForceUndirtyMrkPnt();
279 sal_Bool bChgd
=sal_False
;
283 MarkListHasChanged();
288 const Rectangle
& SdrMarkView::GetMarkedPointsRect() const
290 ForceUndirtyMrkPnt();
291 if (bMarkedPointsRectsDirty
) ImpSetPointsRects();
292 return aMarkedPointsRect
;
295 void SdrMarkView::SetPlusHandlesAlwaysVisible(sal_Bool bOn
)
296 { // TODO: Optimize HandlePaint!
297 ForceUndirtyMrkPnt();
298 if (bOn
!=bPlusHdlAlways
) {
301 MarkListHasChanged();
305 ////////////////////////////////////////////////////////////////////////////////////////////////////
306 // ImpSetPointsRects() is for PolyPoints and GluePoints!
307 ////////////////////////////////////////////////////////////////////////////////////////////////////
309 void SdrMarkView::ImpSetPointsRects() const
313 sal_uIntPtr nHdlAnz
=aHdl
.GetHdlCount();
314 for (sal_uIntPtr nHdlNum
=0; nHdlNum
<nHdlAnz
; nHdlNum
++) {
315 const SdrHdl
* pHdl
=aHdl
.GetHdl(nHdlNum
);
316 SdrHdlKind eKind
=pHdl
->GetKind();
317 if ((eKind
==HDL_POLY
&& pHdl
->IsSelected()) || eKind
==HDL_GLUE
) {
318 Point
aPt(pHdl
->GetPos());
319 Rectangle
& rR
=eKind
==HDL_GLUE
? aGlue
: aPnts
;
321 rR
=Rectangle(aPt
,aPt
);
323 if (aPt
.X()<rR
.Left ()) rR
.Left ()=aPt
.X();
324 if (aPt
.X()>rR
.Right ()) rR
.Right ()=aPt
.X();
325 if (aPt
.Y()<rR
.Top ()) rR
.Top ()=aPt
.Y();
326 if (aPt
.Y()>rR
.Bottom()) rR
.Bottom()=aPt
.Y();
330 ((SdrMarkView
*)this)->aMarkedPointsRect
=aPnts
;
331 ((SdrMarkView
*)this)->aMarkedGluePointsRect
=aGlue
;
332 ((SdrMarkView
*)this)->bMarkedPointsRectsDirty
=sal_False
;
335 ////////////////////////////////////////////////////////////////////////////////////////////////////
336 // UndirtyMrkPnt() is for PolyPoints and GluePoints!
337 ////////////////////////////////////////////////////////////////////////////////////////////////////
339 void SdrMarkView::UndirtyMrkPnt() const
341 sal_Bool bChg
=sal_False
;
342 sal_uIntPtr nMarkAnz
=GetMarkedObjectCount();
343 for (sal_uIntPtr nMarkNum
=0; nMarkNum
<nMarkAnz
; nMarkNum
++) {
344 SdrMark
* pM
=GetSdrMarkByIndex(nMarkNum
);
345 const SdrObject
* pObj
=pM
->GetMarkedSdrObj();
347 SdrUShortCont
* pPts
=pM
->GetMarkedPoints();
349 if (pObj
->IsPolyObj()) {
350 // Remove invalid selected points, that is, all
351 // entries above the number of points in the object.
352 sal_uInt32
nMax(pObj
->GetPointCount());
353 sal_uInt32
nPtNum(0xffffffff);
357 for (sal_uInt32
nIndex(pPts
->GetCount()); nIndex
> 0L && nPtNum
>= nMax
;)
360 nPtNum
= pPts
->GetObject(nIndex
);
364 pPts
->Remove(nIndex
);
371 OSL_FAIL("SdrMarkView::UndirtyMrkPnt(): Selected points on an object that is not a PolyObj!");
372 if(pPts
&& pPts
->GetCount())
381 pPts
=pM
->GetMarkedGluePoints();
382 const SdrGluePointList
* pGPL
=pObj
->GetGluePointList();
385 // Remove invalid selected glue points, that is, all entries
386 // (IDs) that aren't contained in the GluePointList of the
389 for (sal_uIntPtr nIndex
=pPts
->GetCount(); nIndex
>0;) {
391 sal_uInt16 nId
=pPts
->GetObject(nIndex
);
392 if (pGPL
->FindGluePoint(nId
)==SDRGLUEPOINT_NOTFOUND
) {
393 pPts
->Remove(nIndex
);
398 if (pPts
!=NULL
&& pPts
->GetCount()!=0) {
399 pPts
->Clear(); // object doesn't have any glue points (any more)
405 if (bChg
) ((SdrMarkView
*)this)->bMarkedPointsRectsDirty
=sal_True
;
406 ((SdrMarkView
*)this)->bMrkPntDirty
=sal_False
;
409 ////////////////////////////////////////////////////////////////////////////////////////////////////
411 sal_Bool
SdrMarkView::HasMarkableGluePoints() const
413 sal_Bool bRet
=sal_False
;
414 if (IsGluePointEditMode()) {
415 ForceUndirtyMrkPnt();
416 sal_uIntPtr nMarkAnz
=GetMarkedObjectCount();
417 for (sal_uIntPtr nMarkNum
=0; nMarkNum
<nMarkAnz
&& !bRet
; nMarkNum
++) {
418 const SdrMark
* pM
=GetSdrMarkByIndex(nMarkNum
);
419 const SdrObject
* pObj
=pM
->GetMarkedSdrObj();
420 const SdrGluePointList
* pGPL
=pObj
->GetGluePointList();
423 if(pGPL
&& pGPL
->GetCount())
425 for(sal_uInt16
a(0); !bRet
&& a
< pGPL
->GetCount(); a
++)
427 if((*pGPL
)[a
].IsUserDefined())
438 sal_Bool
SdrMarkView::HasMarkedGluePoints() const
440 ForceUndirtyMrkPnt();
441 sal_Bool bRet
=sal_False
;
442 sal_uIntPtr nMarkAnz
=GetMarkedObjectCount();
443 for (sal_uIntPtr nMarkNum
=0; nMarkNum
<nMarkAnz
&& !bRet
; nMarkNum
++) {
444 const SdrMark
* pM
=GetSdrMarkByIndex(nMarkNum
);
445 const SdrUShortCont
* pPts
=pM
->GetMarkedGluePoints();
446 bRet
=pPts
!=NULL
&& pPts
->GetCount()!=0;
451 sal_Bool
SdrMarkView::MarkGluePoints(const Rectangle
* pRect
, sal_Bool bUnmark
)
453 if (!IsGluePointEditMode() && !bUnmark
) return sal_False
;
454 ForceUndirtyMrkPnt();
455 sal_Bool bChgd
=sal_False
;
457 sal_uIntPtr nMarkAnz
=GetMarkedObjectCount();
458 for (sal_uIntPtr nMarkNum
=0; nMarkNum
<nMarkAnz
; nMarkNum
++) {
459 SdrMark
* pM
=GetSdrMarkByIndex(nMarkNum
);
460 const SdrObject
* pObj
=pM
->GetMarkedSdrObj();
461 const SdrGluePointList
* pGPL
=pObj
->GetGluePointList();
462 SdrUShortCont
* pPts
=pM
->GetMarkedGluePoints();
463 if (bUnmark
&& pRect
==NULL
) { // UnmarkAll
464 if (pPts
!=NULL
&& pPts
->GetCount()!=0) {
469 if (pGPL
!=NULL
&& (pPts
!=NULL
|| !bUnmark
)) {
470 sal_uInt16 nGPAnz
=pGPL
->GetCount();
471 for (sal_uInt16 nGPNum
=0; nGPNum
<nGPAnz
; nGPNum
++) {
472 const SdrGluePoint
& rGP
=(*pGPL
)[nGPNum
];
475 if(rGP
.IsUserDefined())
477 Point
aPos(rGP
.GetAbsolutePos(*pObj
));
478 if (pRect
==NULL
|| pRect
->IsInside(aPos
)) {
479 if (pPts
==NULL
) pPts
=pM
->ForceMarkedGluePoints();
480 else pPts
->ForceSort();
481 sal_uIntPtr nPos
=pPts
->GetPos(rGP
.GetId());
482 if (!bUnmark
&& nPos
==CONTAINER_ENTRY_NOTFOUND
) {
484 pPts
->Insert(rGP
.GetId());
486 if (bUnmark
&& nPos
!=CONTAINER_ENTRY_NOTFOUND
) {
498 MarkListHasChanged();
503 sal_Bool
SdrMarkView::PickGluePoint(const Point
& rPnt
, SdrObject
*& rpObj
, sal_uInt16
& rnId
, SdrPageView
*& rpPV
, sal_uIntPtr nOptions
) const
505 SdrObject
* pObj0
=rpObj
;
506 sal_uInt16 nId0
=rnId
;
507 rpObj
=NULL
; rpPV
=NULL
; rnId
=0;
508 if (!IsGluePointEditMode()) return sal_False
;
509 sal_Bool bBack
=(nOptions
& SDRSEARCH_BACKWARD
) !=0;
510 sal_Bool bNext
=(nOptions
& SDRSEARCH_NEXT
) !=0;
511 OutputDevice
* pOut
=(OutputDevice
*)pActualOutDev
;
512 if (pOut
==NULL
) pOut
=GetFirstOutputDevice();
513 if (pOut
==NULL
) return sal_False
;
515 sal_uIntPtr nMarkAnz
=GetMarkedObjectCount();
516 sal_uIntPtr nMarkNum
=bBack
? 0 : nMarkAnz
;
518 nMarkNum
=((SdrMarkView
*)this)->TryToFindMarkedObject(pObj0
);
519 if (nMarkNum
==CONTAINER_ENTRY_NOTFOUND
) return sal_False
;
520 if (!bBack
) nMarkNum
++;
522 while (bBack
? nMarkNum
<nMarkAnz
: nMarkNum
>0) {
523 if (!bBack
) nMarkNum
--;
524 const SdrMark
* pM
=GetSdrMarkByIndex(nMarkNum
);
525 SdrObject
* pObj
=pM
->GetMarkedSdrObj();
526 SdrPageView
* pPV
=pM
->GetPageView();
527 const SdrGluePointList
* pGPL
=pObj
->GetGluePointList();
529 sal_uInt16 nNum
=pGPL
->HitTest(rPnt
,*pOut
,pObj
,bBack
,bNext
,nId0
);
530 if (nNum
!=SDRGLUEPOINT_NOTFOUND
)
533 const SdrGluePoint
& rCandidate
= (*pGPL
)[nNum
];
535 if(rCandidate
.IsUserDefined())
538 rnId
=(*pGPL
)[nNum
].GetId();
544 bNext
=sal_False
; // HitNextGluePoint only for the first Obj
545 if (bBack
) nMarkNum
++;
550 sal_Bool
SdrMarkView::MarkGluePoint(const SdrObject
* pObj
, sal_uInt16 nId
, const SdrPageView
* /*pPV*/, sal_Bool bUnmark
)
552 if (!IsGluePointEditMode()) return sal_False
;
553 ForceUndirtyMrkPnt();
554 sal_Bool bChgd
=sal_False
;
556 sal_uIntPtr nMarkPos
=TryToFindMarkedObject(pObj
);
557 if (nMarkPos
!=CONTAINER_ENTRY_NOTFOUND
) {
558 SdrMark
* pM
=GetSdrMarkByIndex(nMarkPos
);
559 SdrUShortCont
* pPts
=bUnmark
? pM
->GetMarkedGluePoints() : pM
->ForceMarkedGluePoints();
561 sal_uIntPtr nPointPos
=pPts
->GetPos(nId
);
562 if (!bUnmark
&& nPointPos
==CONTAINER_ENTRY_NOTFOUND
) {
566 if (bUnmark
&& nPointPos
!=CONTAINER_ENTRY_NOTFOUND
) {
568 pPts
->Remove(nPointPos
);
572 // TODO: implement implicit selection of objects
577 MarkListHasChanged();
582 sal_Bool
SdrMarkView::IsGluePointMarked(const SdrObject
* pObj
, sal_uInt16 nId
) const
584 ForceUndirtyMrkPnt();
585 sal_Bool bRet
=sal_False
;
586 sal_uIntPtr nPos
=((SdrMarkView
*)this)->TryToFindMarkedObject(pObj
); // casting to NonConst
587 if (nPos
!=CONTAINER_ENTRY_NOTFOUND
) {
588 const SdrMark
* pM
=GetSdrMarkByIndex(nPos
);
589 const SdrUShortCont
* pPts
=pM
->GetMarkedGluePoints();
591 bRet
=pPts
->Exist(nId
);
597 SdrHdl
* SdrMarkView::GetGluePointHdl(const SdrObject
* pObj
, sal_uInt16 nId
) const
599 ForceUndirtyMrkPnt();
600 sal_uIntPtr nHdlAnz
=aHdl
.GetHdlCount();
601 for (sal_uIntPtr nHdlNum
=0; nHdlNum
<nHdlAnz
; nHdlNum
++) {
602 SdrHdl
* pHdl
=aHdl
.GetHdl(nHdlNum
);
603 if (pHdl
->GetObj()==pObj
&&
604 pHdl
->GetKind()==HDL_GLUE
&&
605 pHdl
->GetObjHdlNum()==nId
) return pHdl
;
610 sal_Bool
SdrMarkView::MarkNextGluePoint(const Point
& /*rPnt*/, sal_Bool
/*bPrev*/)
612 ForceUndirtyMrkPnt();
613 sal_Bool bChgd
=sal_False
;
617 MarkListHasChanged();
622 const Rectangle
& SdrMarkView::GetMarkedGluePointsRect() const
624 ForceUndirtyMrkPnt();
625 if (bMarkedPointsRectsDirty
) ImpSetPointsRects();
626 return aMarkedGluePointsRect
;
629 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */