bump product version to 4.1.6.2
[LibreOffice.git] / svx / source / svdraw / svdmrkv1.cxx
blob00a2da73e55d66b43f8253b84e2c43d5c358284e
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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 ////////////////////////////////////////////////////////////////////////////////////////////////////
30 // Point Selection
31 ////////////////////////////////////////////////////////////////////////////////////////////////////
33 sal_Bool SdrMarkView::HasMarkablePoints() const
35 ForceUndirtyMrkPnt();
36 bool bRet=false;
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();
47 return bRet;
50 sal_uIntPtr SdrMarkView::GetMarkablePointCount() const
52 ForceUndirtyMrkPnt();
53 sal_uIntPtr nAnz=0;
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();
66 return nAnz;
69 sal_Bool SdrMarkView::HasMarkedPoints() const
71 ForceUndirtyMrkPnt();
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();
83 return bRet;
86 sal_uIntPtr SdrMarkView::GetMarkedPointCount() const
88 ForceUndirtyMrkPnt();
89 sal_uIntPtr nAnz=0;
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();
100 return nAnz;
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)
116 return sal_False;
118 if (pHdl->IsSelected() != bUnmark)
119 return sal_False;
121 SdrObject* pObj=pHdl->GetObj();
122 if (pObj==NULL || !pObj->IsPolyObj())
123 return sal_False;
125 if (pMark==NULL)
127 sal_uIntPtr nMarkNum=TryToFindMarkedObject(pObj);
128 if (nMarkNum==CONTAINER_ENTRY_NOTFOUND)
129 return sal_False;
130 pMark=GetSdrMarkByIndex(nMarkNum);
132 const sal_uInt32 nHdlNum(pHdl->GetObjHdlNum());
133 SdrUShortCont* pPts=pMark->ForceMarkedPoints();
134 if (!bUnmark)
136 pPts->insert((sal_uInt16)nHdlNum);
138 else
140 SdrUShortCont::const_iterator it = pPts->find( (sal_uInt16)nHdlNum );
141 if (it != pPts->end())
143 pPts->erase(it);
145 else
147 return sal_False; // error case!
151 pHdl->SetSelected(!bUnmark);
152 if (!bPlusHdlAlways)
154 if (!bUnmark)
156 sal_uInt32 nAnz(pObj->GetPlusHdlCount(*pHdl));
157 for (sal_uInt32 i=0; i<nAnz; i++)
159 SdrHdl* pPlusHdl=pObj->GetPlusHdl(*pHdl,i);
160 if (pPlusHdl!=NULL)
162 pPlusHdl->SetObj(pObj);
163 pPlusHdl->SetPageView(pMark->GetPageView());
164 pPlusHdl->SetPlusHdl(sal_True);
165 aHdl.AddHdl(pPlusHdl);
169 else
171 for (sal_uIntPtr i = aHdl.GetHdlCount(); i>0;)
173 i--;
174 SdrHdl* pPlusHdl=aHdl.GetHdl(i);
175 if (pPlusHdl->IsPlusHdl() && pPlusHdl->GetSourceHdlNum()==nHdlNum)
177 aHdl.RemoveHdl(i);
178 delete pPlusHdl;
184 aHdl.Sort();
186 return sal_True;
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();
203 bRet=sal_True;
208 return bRet;
211 sal_Bool SdrMarkView::MarkPoints(const Rectangle* pRect, sal_Bool bUnmark)
213 ForceUndirtyMrkPnt();
214 sal_Bool bChgd=sal_False;
215 SortMarkedObjects();
216 const SdrObject* pObj0=NULL;
217 const SdrPageView* pPV0=NULL;
218 SdrMark* pM=NULL;
219 aHdl.Sort();
220 sal_uIntPtr nHdlAnz=aHdl.GetHdlCount();
221 for (sal_uIntPtr nHdlNum=nHdlAnz; nHdlNum>0;) {
222 nHdlNum--;
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);
231 pObj0=pObj;
232 pPV0=pPV;
233 pM->ForceMarkedPoints();
234 } else {
235 #ifdef DBG_UTIL
236 if (pObj->IsInserted()) {
237 OSL_FAIL("SdrMarkView::MarkPoints(const Rectangle* pRect): Selected object not found.");
239 #endif
240 pM=NULL;
243 Point aPos(pHdl->GetPos());
244 if (pM!=NULL && (pRect==NULL || pRect->IsInside(aPos))) {
245 if (ImpMarkPoint(pHdl,pM,bUnmark)) bChgd=sal_True;
249 if (bChgd) {
250 MarkListHasChanged();
253 return bChgd;
256 sal_Bool SdrMarkView::MarkNextPoint(const Point& /*rPnt*/, sal_Bool /*bPrev*/)
258 ForceUndirtyMrkPnt();
259 sal_Bool bChgd=sal_False;
260 SortMarkedObjects();
261 // ...
262 if (bChgd) {
263 MarkListHasChanged();
265 return bChgd;
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) {
279 bPlusHdlAlways=bOn;
280 SetMarkHandles();
281 MarkListHasChanged();
285 ////////////////////////////////////////////////////////////////////////////////////////////////////
286 // ImpSetPointsRects() is for PolyPoints and GluePoints!
287 ////////////////////////////////////////////////////////////////////////////////////////////////////
289 void SdrMarkView::ImpSetPointsRects() const
291 Rectangle aPnts;
292 Rectangle aGlue;
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;
300 if (rR.IsEmpty()) {
301 rR=Rectangle(aPt,aPt);
302 } else {
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();
326 // PolyPoints
327 SdrUShortCont* pPts=pM->GetMarkedPoints();
328 if (pPts!=NULL) {
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() );
338 bChg = sal_True;
341 else
343 OSL_FAIL("SdrMarkView::UndirtyMrkPnt(): Selected points on an object that is not a PolyObj!");
344 if(pPts && !pPts->empty())
346 pPts->clear();
347 bChg = sal_True;
352 // GluePoints
353 pPts=pM->GetMarkedGluePoints();
354 const SdrGluePointList* pGPL=pObj->GetGluePointList();
355 if (pPts!=NULL) {
356 if (pGPL!=NULL) {
357 // Remove invalid selected glue points, that is, all entries
358 // (IDs) that aren't contained in the GluePointList of the
359 // object
360 for(SdrUShortCont::const_iterator it = pPts->begin(); it != pPts->end(); )
362 sal_uInt16 nId=*it;
363 if (pGPL->FindGluePoint(nId)==SDRGLUEPOINT_NOTFOUND) {
364 pPts->erase(it++);
365 bChg=sal_True;
367 else
368 ++it;
370 } else {
371 if (pPts!=NULL && !pPts->empty()) {
372 pPts->clear(); // object doesn't have any glue points (any more)
373 bChg=sal_True;
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();
395 // #i38892#
396 if(pGPL && pGPL->GetCount())
398 for(sal_uInt16 a(0); !bRet && a < pGPL->GetCount(); a++)
400 if((*pGPL)[a].IsUserDefined())
402 bRet = sal_True;
408 return bRet;
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();
421 return bRet;
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;
429 SortMarkedObjects();
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()) {
438 pPts->clear();
439 bChgd=sal_True;
441 } else {
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];
447 // #i38892#
448 if(rGP.IsUserDefined())
450 Point aPos(rGP.GetAbsolutePos(*pObj));
451 if (pRect==NULL || pRect->IsInside(aPos)) {
452 if (pPts==NULL)
453 pPts=pM->ForceMarkedGluePoints();
454 bool bContains = pPts->find( rGP.GetId() ) != pPts->end();
455 if (!bUnmark && !bContains) {
456 bChgd=sal_True;
457 pPts->insert(rGP.GetId());
459 if (bUnmark && bContains) {
460 bChgd=sal_True;
461 pPts->erase(rGP.GetId());
469 if (bChgd) {
470 AdjustMarkHdl();
471 MarkListHasChanged();
473 return bChgd;
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;
487 SortMarkedObjects();
488 sal_uIntPtr nMarkAnz=GetMarkedObjectCount();
489 sal_uIntPtr nMarkNum=bBack ? 0 : nMarkAnz;
490 if (bNext) {
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();
501 if (pGPL!=NULL) {
502 sal_uInt16 nNum=pGPL->HitTest(rPnt,*pOut,pObj,bBack,bNext,nId0);
503 if (nNum!=SDRGLUEPOINT_NOTFOUND)
505 // #i38892#
506 const SdrGluePoint& rCandidate = (*pGPL)[nNum];
508 if(rCandidate.IsUserDefined())
510 rpObj=pObj;
511 rnId=(*pGPL)[nNum].GetId();
512 rpPV=pPV;
513 return sal_True;
517 bNext=sal_False; // HitNextGluePoint only for the first Obj
518 if (bBack) nMarkNum++;
520 return sal_False;
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;
528 if (pObj!=NULL) {
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();
533 if (pPts!=NULL) {
534 bool bContains = pPts->find( nId ) != pPts->end();
535 if (!bUnmark && !bContains) {
536 bChgd=sal_True;
537 pPts->insert(nId);
539 if (bUnmark && bContains) {
540 bChgd=sal_True;
541 pPts->erase(nId);
544 } else {
545 // TODO: implement implicit selection of objects
548 if (bChgd) {
549 AdjustMarkHdl();
550 MarkListHasChanged();
552 return bChgd;
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();
563 if (pPts!=NULL) {
564 bRet = pPts->find( nId ) != pPts->end();
567 return bRet;
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;
580 return NULL;
583 sal_Bool SdrMarkView::MarkNextGluePoint(const Point& /*rPnt*/, sal_Bool /*bPrev*/)
585 ForceUndirtyMrkPnt();
586 sal_Bool bChgd=sal_False;
587 SortMarkedObjects();
588 // ...
589 if (bChgd) {
590 MarkListHasChanged();
592 return bChgd;
595 const Rectangle& SdrMarkView::GetMarkedGluePointsRect() const
597 ForceUndirtyMrkPnt();
598 if (bMarkedPointsRectsDirty) ImpSetPointsRects();
599 return aMarkedGluePointsRect;
602 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */