Version 4.3.0.0.beta1, tag libreoffice-4.3.0.0.beta1
[LibreOffice.git] / svx / source / svdraw / svdmrkv1.cxx
blob4cf1d3cee59ffbf6c41c9196e3506193f3a2443b
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 "svdglob.hxx"
25 #include <svx/svdpagv.hxx>
26 #include <svx/svdpage.hxx>
27 #include "svddrgm1.hxx"
30 // Point Selection
33 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 bool SdrMarkView::HasMarkedPoints() const
71 ForceUndirtyMrkPnt();
72 bool bRet=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 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)
116 return false;
118 if (pHdl->IsSelected() != bUnmark)
119 return false;
121 SdrObject* pObj=pHdl->GetObj();
122 if (pObj==NULL || !pObj->IsPolyObj())
123 return false;
125 if (pMark==NULL)
127 sal_uIntPtr nMarkNum=TryToFindMarkedObject(pObj);
128 if (nMarkNum==CONTAINER_ENTRY_NOTFOUND)
129 return 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 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(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 true;
190 bool SdrMarkView::MarkPoint(SdrHdl& rHdl, bool bUnmark)
192 if (&rHdl==NULL) return false;
193 ForceUndirtyMrkPnt();
194 bool bRet=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=true;
208 return bRet;
211 bool SdrMarkView::MarkPoints(const Rectangle* pRect, bool bUnmark)
213 ForceUndirtyMrkPnt();
214 bool bChgd=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=true;
249 if (bChgd) {
250 MarkListHasChanged();
253 return bChgd;
256 bool SdrMarkView::MarkNextPoint(const Point& /*rPnt*/, bool /*bPrev*/)
258 ForceUndirtyMrkPnt();
259 SortMarkedObjects();
260 return false;
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) {
274 bPlusHdlAlways=bOn;
275 SetMarkHandles();
276 MarkListHasChanged();
281 // ImpSetPointsRects() is for PolyPoints and GluePoints!
284 void SdrMarkView::ImpSetPointsRects() const
286 Rectangle aPnts;
287 Rectangle aGlue;
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;
295 if (rR.IsEmpty()) {
296 rR=Rectangle(aPt,aPt);
297 } else {
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
316 bool bChg=false;
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();
321 // PolyPoints
322 SdrUShortCont* pPts=pM->GetMarkedPoints();
323 if (pPts!=NULL) {
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() );
333 bChg = true;
336 else
338 OSL_FAIL("SdrMarkView::UndirtyMrkPnt(): Selected points on an object that is not a PolyObj!");
339 if(pPts && !pPts->empty())
341 pPts->clear();
342 bChg = true;
347 // GluePoints
348 pPts=pM->GetMarkedGluePoints();
349 const SdrGluePointList* pGPL=pObj->GetGluePointList();
350 if (pPts!=NULL) {
351 if (pGPL!=NULL) {
352 // Remove invalid selected glue points, that is, all entries
353 // (IDs) that aren't contained in the GluePointList of the
354 // object
355 for(SdrUShortCont::const_iterator it = pPts->begin(); it != pPts->end(); )
357 sal_uInt16 nId=*it;
358 if (pGPL->FindGluePoint(nId)==SDRGLUEPOINT_NOTFOUND) {
359 pPts->erase(it++);
360 bChg=true;
362 else
363 ++it;
365 } else {
366 if (pPts!=NULL && !pPts->empty()) {
367 pPts->clear(); // object doesn't have any glue points (any more)
368 bChg=true;
373 if (bChg) ((SdrMarkView*)this)->bMarkedPointsRectsDirty=true;
374 ((SdrMarkView*)this)->bMrkPntDirty=false;
379 bool SdrMarkView::HasMarkableGluePoints() const
381 bool bRet=false;
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();
390 // #i38892#
391 if(pGPL && pGPL->GetCount())
393 for(sal_uInt16 a(0); !bRet && a < pGPL->GetCount(); a++)
395 if((*pGPL)[a].IsUserDefined())
397 bRet = true;
403 return bRet;
406 bool SdrMarkView::HasMarkedGluePoints() const
408 ForceUndirtyMrkPnt();
409 bool bRet=false;
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();
416 return bRet;
419 bool SdrMarkView::MarkGluePoints(const Rectangle* pRect, bool bUnmark)
421 if (!IsGluePointEditMode() && !bUnmark) return false;
422 ForceUndirtyMrkPnt();
423 bool bChgd=false;
424 SortMarkedObjects();
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()) {
433 pPts->clear();
434 bChgd=true;
436 } else {
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];
442 // #i38892#
443 if(rGP.IsUserDefined())
445 Point aPos(rGP.GetAbsolutePos(*pObj));
446 if (pRect==NULL || pRect->IsInside(aPos)) {
447 if (pPts==NULL)
448 pPts=pM->ForceMarkedGluePoints();
449 bool bContains = pPts->find( rGP.GetId() ) != pPts->end();
450 if (!bUnmark && !bContains) {
451 bChgd=true;
452 pPts->insert(rGP.GetId());
454 if (bUnmark && bContains) {
455 bChgd=true;
456 pPts->erase(rGP.GetId());
464 if (bChgd) {
465 AdjustMarkHdl();
466 MarkListHasChanged();
468 return bChgd;
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;
482 SortMarkedObjects();
483 sal_uIntPtr nMarkAnz=GetMarkedObjectCount();
484 sal_uIntPtr nMarkNum=bBack ? 0 : nMarkAnz;
485 if (bNext) {
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();
496 if (pGPL!=NULL) {
497 sal_uInt16 nNum=pGPL->HitTest(rPnt,*pOut,pObj,bBack,bNext,nId0);
498 if (nNum!=SDRGLUEPOINT_NOTFOUND)
500 // #i38892#
501 const SdrGluePoint& rCandidate = (*pGPL)[nNum];
503 if(rCandidate.IsUserDefined())
505 rpObj=pObj;
506 rnId=(*pGPL)[nNum].GetId();
507 rpPV=pPV;
508 return true;
512 bNext=false; // HitNextGluePoint only for the first Obj
513 if (bBack) nMarkNum++;
515 return false;
518 bool SdrMarkView::MarkGluePoint(const SdrObject* pObj, sal_uInt16 nId, const SdrPageView* /*pPV*/, bool bUnmark)
520 if (!IsGluePointEditMode()) return false;
521 ForceUndirtyMrkPnt();
522 bool bChgd=false;
523 if (pObj!=NULL) {
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();
528 if (pPts!=NULL) {
529 bool bContains = pPts->find( nId ) != pPts->end();
530 if (!bUnmark && !bContains) {
531 bChgd=true;
532 pPts->insert(nId);
534 if (bUnmark && bContains) {
535 bChgd=true;
536 pPts->erase(nId);
539 } else {
540 // TODO: implement implicit selection of objects
543 if (bChgd) {
544 AdjustMarkHdl();
545 MarkListHasChanged();
547 return bChgd;
550 bool SdrMarkView::IsGluePointMarked(const SdrObject* pObj, sal_uInt16 nId) const
552 ForceUndirtyMrkPnt();
553 bool bRet=false;
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();
558 if (pPts!=NULL) {
559 bRet = pPts->find( nId ) != pPts->end();
562 return bRet;
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;
575 return NULL;
578 bool SdrMarkView::MarkNextGluePoint(const Point& /*rPnt*/, bool /*bPrev*/)
580 ForceUndirtyMrkPnt();
581 SortMarkedObjects();
582 return false;
585 const Rectangle& SdrMarkView::GetMarkedGluePointsRect() const
587 ForceUndirtyMrkPnt();
588 if (bMarkedPointsRectsDirty) ImpSetPointsRects();
589 return aMarkedGluePointsRect;
592 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */