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 "svdglob.hxx"
25 #include <svx/svdpagv.hxx>
26 #include <svx/svdpage.hxx>
27 #include "svddrgm1.hxx"
33 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 bool SdrMarkView::HasMarkedPoints() const
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 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 bool SdrMarkView::MarkPointHelper(SdrHdl
* pHdl
, SdrMark
* pMark
, bool bUnmark
)
110 return ImpMarkPoint( pHdl
, pMark
, bUnmark
);
113 bool SdrMarkView::ImpMarkPoint(SdrHdl
* pHdl
, SdrMark
* pMark
, 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 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(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 bool SdrMarkView::MarkPoint(SdrHdl
& rHdl
, bool bUnmark
)
192 if (&rHdl
==NULL
) return false;
193 ForceUndirtyMrkPnt();
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 bool SdrMarkView::MarkPoints(const Rectangle
* pRect
, bool bUnmark
)
213 ForceUndirtyMrkPnt();
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
=true;
250 MarkListHasChanged();
256 bool SdrMarkView::MarkNextPoint(const Point
& /*rPnt*/, bool /*bPrev*/)
258 ForceUndirtyMrkPnt();
263 const Rectangle
& SdrMarkView::GetMarkedPointsRect() const
265 ForceUndirtyMrkPnt();
266 if (bMarkedPointsRectsDirty
) ImpSetPointsRects();
267 return aMarkedPointsRect
;
270 void SdrMarkView::SetPlusHandlesAlwaysVisible(bool bOn
)
271 { // TODO: Optimize HandlePaint!
272 ForceUndirtyMrkPnt();
273 if (bOn
!=bPlusHdlAlways
) {
276 MarkListHasChanged();
281 // ImpSetPointsRects() is for PolyPoints and GluePoints!
284 void SdrMarkView::ImpSetPointsRects() const
288 sal_uIntPtr nHdlAnz
=aHdl
.GetHdlCount();
289 for (sal_uIntPtr nHdlNum
=0; nHdlNum
<nHdlAnz
; nHdlNum
++) {
290 const SdrHdl
* pHdl
=aHdl
.GetHdl(nHdlNum
);
291 SdrHdlKind eKind
=pHdl
->GetKind();
292 if ((eKind
==HDL_POLY
&& pHdl
->IsSelected()) || eKind
==HDL_GLUE
) {
293 Point
aPt(pHdl
->GetPos());
294 Rectangle
& rR
=eKind
==HDL_GLUE
? aGlue
: aPnts
;
296 rR
=Rectangle(aPt
,aPt
);
298 if (aPt
.X()<rR
.Left ()) rR
.Left ()=aPt
.X();
299 if (aPt
.X()>rR
.Right ()) rR
.Right ()=aPt
.X();
300 if (aPt
.Y()<rR
.Top ()) rR
.Top ()=aPt
.Y();
301 if (aPt
.Y()>rR
.Bottom()) rR
.Bottom()=aPt
.Y();
305 ((SdrMarkView
*)this)->aMarkedPointsRect
=aPnts
;
306 ((SdrMarkView
*)this)->aMarkedGluePointsRect
=aGlue
;
307 ((SdrMarkView
*)this)->bMarkedPointsRectsDirty
=false;
311 // UndirtyMrkPnt() is for PolyPoints and GluePoints!
314 void SdrMarkView::UndirtyMrkPnt() const
317 sal_uIntPtr nMarkAnz
=GetMarkedObjectCount();
318 for (sal_uIntPtr nMarkNum
=0; nMarkNum
<nMarkAnz
; nMarkNum
++) {
319 SdrMark
* pM
=GetSdrMarkByIndex(nMarkNum
);
320 const SdrObject
* pObj
=pM
->GetMarkedSdrObj();
322 SdrUShortCont
* pPts
=pM
->GetMarkedPoints();
324 if (pObj
->IsPolyObj()) {
325 // Remove invalid selected points, that is, all
326 // entries above the number of points in the object.
327 sal_uInt32
nMax(pObj
->GetPointCount());
329 SdrUShortCont::const_iterator it
= pPts
->lower_bound(nMax
);
330 if( it
!= pPts
->end() )
332 pPts
->erase(it
, pPts
->end() );
338 OSL_FAIL("SdrMarkView::UndirtyMrkPnt(): Selected points on an object that is not a PolyObj!");
339 if(pPts
&& !pPts
->empty())
348 pPts
=pM
->GetMarkedGluePoints();
349 const SdrGluePointList
* pGPL
=pObj
->GetGluePointList();
352 // Remove invalid selected glue points, that is, all entries
353 // (IDs) that aren't contained in the GluePointList of the
355 for(SdrUShortCont::const_iterator it
= pPts
->begin(); it
!= pPts
->end(); )
358 if (pGPL
->FindGluePoint(nId
)==SDRGLUEPOINT_NOTFOUND
) {
366 if (pPts
!=NULL
&& !pPts
->empty()) {
367 pPts
->clear(); // object doesn't have any glue points (any more)
373 if (bChg
) ((SdrMarkView
*)this)->bMarkedPointsRectsDirty
=true;
374 ((SdrMarkView
*)this)->bMrkPntDirty
=false;
379 bool SdrMarkView::HasMarkableGluePoints() const
382 if (IsGluePointEditMode()) {
383 ForceUndirtyMrkPnt();
384 sal_uIntPtr nMarkAnz
=GetMarkedObjectCount();
385 for (sal_uIntPtr nMarkNum
=0; nMarkNum
<nMarkAnz
&& !bRet
; nMarkNum
++) {
386 const SdrMark
* pM
=GetSdrMarkByIndex(nMarkNum
);
387 const SdrObject
* pObj
=pM
->GetMarkedSdrObj();
388 const SdrGluePointList
* pGPL
=pObj
->GetGluePointList();
391 if(pGPL
&& pGPL
->GetCount())
393 for(sal_uInt16
a(0); !bRet
&& a
< pGPL
->GetCount(); a
++)
395 if((*pGPL
)[a
].IsUserDefined())
406 bool SdrMarkView::HasMarkedGluePoints() const
408 ForceUndirtyMrkPnt();
410 sal_uIntPtr nMarkAnz
=GetMarkedObjectCount();
411 for (sal_uIntPtr nMarkNum
=0; nMarkNum
<nMarkAnz
&& !bRet
; nMarkNum
++) {
412 const SdrMark
* pM
=GetSdrMarkByIndex(nMarkNum
);
413 const SdrUShortCont
* pPts
=pM
->GetMarkedGluePoints();
414 bRet
=pPts
!=NULL
&& !pPts
->empty();
419 bool SdrMarkView::MarkGluePoints(const Rectangle
* pRect
, bool bUnmark
)
421 if (!IsGluePointEditMode() && !bUnmark
) return false;
422 ForceUndirtyMrkPnt();
425 sal_uIntPtr nMarkAnz
=GetMarkedObjectCount();
426 for (sal_uIntPtr nMarkNum
=0; nMarkNum
<nMarkAnz
; nMarkNum
++) {
427 SdrMark
* pM
=GetSdrMarkByIndex(nMarkNum
);
428 const SdrObject
* pObj
=pM
->GetMarkedSdrObj();
429 const SdrGluePointList
* pGPL
=pObj
->GetGluePointList();
430 SdrUShortCont
* pPts
=pM
->GetMarkedGluePoints();
431 if (bUnmark
&& pRect
==NULL
) { // UnmarkAll
432 if (pPts
!=NULL
&& !pPts
->empty()) {
437 if (pGPL
!=NULL
&& (pPts
!=NULL
|| !bUnmark
)) {
438 sal_uInt16 nGPAnz
=pGPL
->GetCount();
439 for (sal_uInt16 nGPNum
=0; nGPNum
<nGPAnz
; nGPNum
++) {
440 const SdrGluePoint
& rGP
=(*pGPL
)[nGPNum
];
443 if(rGP
.IsUserDefined())
445 Point
aPos(rGP
.GetAbsolutePos(*pObj
));
446 if (pRect
==NULL
|| pRect
->IsInside(aPos
)) {
448 pPts
=pM
->ForceMarkedGluePoints();
449 bool bContains
= pPts
->find( rGP
.GetId() ) != pPts
->end();
450 if (!bUnmark
&& !bContains
) {
452 pPts
->insert(rGP
.GetId());
454 if (bUnmark
&& bContains
) {
456 pPts
->erase(rGP
.GetId());
466 MarkListHasChanged();
471 bool SdrMarkView::PickGluePoint(const Point
& rPnt
, SdrObject
*& rpObj
, sal_uInt16
& rnId
, SdrPageView
*& rpPV
, sal_uIntPtr nOptions
) const
473 SdrObject
* pObj0
=rpObj
;
474 sal_uInt16 nId0
=rnId
;
475 rpObj
=NULL
; rpPV
=NULL
; rnId
=0;
476 if (!IsGluePointEditMode()) return false;
477 bool bBack
=(nOptions
& SDRSEARCH_BACKWARD
) !=0;
478 bool bNext
=(nOptions
& SDRSEARCH_NEXT
) !=0;
479 OutputDevice
* pOut
=(OutputDevice
*)pActualOutDev
;
480 if (pOut
==NULL
) pOut
=GetFirstOutputDevice();
481 if (pOut
==NULL
) return false;
483 sal_uIntPtr nMarkAnz
=GetMarkedObjectCount();
484 sal_uIntPtr nMarkNum
=bBack
? 0 : nMarkAnz
;
486 nMarkNum
=((SdrMarkView
*)this)->TryToFindMarkedObject(pObj0
);
487 if (nMarkNum
==CONTAINER_ENTRY_NOTFOUND
) return false;
488 if (!bBack
) nMarkNum
++;
490 while (bBack
? nMarkNum
<nMarkAnz
: nMarkNum
>0) {
491 if (!bBack
) nMarkNum
--;
492 const SdrMark
* pM
=GetSdrMarkByIndex(nMarkNum
);
493 SdrObject
* pObj
=pM
->GetMarkedSdrObj();
494 SdrPageView
* pPV
=pM
->GetPageView();
495 const SdrGluePointList
* pGPL
=pObj
->GetGluePointList();
497 sal_uInt16 nNum
=pGPL
->HitTest(rPnt
,*pOut
,pObj
,bBack
,bNext
,nId0
);
498 if (nNum
!=SDRGLUEPOINT_NOTFOUND
)
501 const SdrGluePoint
& rCandidate
= (*pGPL
)[nNum
];
503 if(rCandidate
.IsUserDefined())
506 rnId
=(*pGPL
)[nNum
].GetId();
512 bNext
=false; // HitNextGluePoint only for the first Obj
513 if (bBack
) nMarkNum
++;
518 bool SdrMarkView::MarkGluePoint(const SdrObject
* pObj
, sal_uInt16 nId
, const SdrPageView
* /*pPV*/, bool bUnmark
)
520 if (!IsGluePointEditMode()) return false;
521 ForceUndirtyMrkPnt();
524 sal_uIntPtr nMarkPos
=TryToFindMarkedObject(pObj
);
525 if (nMarkPos
!=CONTAINER_ENTRY_NOTFOUND
) {
526 SdrMark
* pM
=GetSdrMarkByIndex(nMarkPos
);
527 SdrUShortCont
* pPts
=bUnmark
? pM
->GetMarkedGluePoints() : pM
->ForceMarkedGluePoints();
529 bool bContains
= pPts
->find( nId
) != pPts
->end();
530 if (!bUnmark
&& !bContains
) {
534 if (bUnmark
&& bContains
) {
540 // TODO: implement implicit selection of objects
545 MarkListHasChanged();
550 bool SdrMarkView::IsGluePointMarked(const SdrObject
* pObj
, sal_uInt16 nId
) const
552 ForceUndirtyMrkPnt();
554 sal_uIntPtr nPos
=((SdrMarkView
*)this)->TryToFindMarkedObject(pObj
); // casting to NonConst
555 if (nPos
!=CONTAINER_ENTRY_NOTFOUND
) {
556 const SdrMark
* pM
=GetSdrMarkByIndex(nPos
);
557 const SdrUShortCont
* pPts
=pM
->GetMarkedGluePoints();
559 bRet
= pPts
->find( nId
) != pPts
->end();
565 SdrHdl
* SdrMarkView::GetGluePointHdl(const SdrObject
* pObj
, sal_uInt16 nId
) const
567 ForceUndirtyMrkPnt();
568 sal_uIntPtr nHdlAnz
=aHdl
.GetHdlCount();
569 for (sal_uIntPtr nHdlNum
=0; nHdlNum
<nHdlAnz
; nHdlNum
++) {
570 SdrHdl
* pHdl
=aHdl
.GetHdl(nHdlNum
);
571 if (pHdl
->GetObj()==pObj
&&
572 pHdl
->GetKind()==HDL_GLUE
&&
573 pHdl
->GetObjHdlNum()==nId
) return pHdl
;
578 bool SdrMarkView::MarkNextGluePoint(const Point
& /*rPnt*/, bool /*bPrev*/)
580 ForceUndirtyMrkPnt();
585 const Rectangle
& SdrMarkView::GetMarkedGluePointsRect() const
587 ForceUndirtyMrkPnt();
588 if (bMarkedPointsRectsDirty
) ImpSetPointsRects();
589 return aMarkedGluePointsRect
;
592 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */