xref: /trunk/main/svx/source/svdraw/svdmark.cxx (revision f6e50924)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_svx.hxx"
26 
27 ////////////////////////////////////////////////////////////////////////////////////////////////////
28 
29 #include <svx/svdmark.hxx>
30 #include <svx/svdetc.hxx>
31 #include <svx/svdobj.hxx>
32 #include <svx/svdpage.hxx>
33 #include "svx/svditer.hxx"
34 #include <svx/svdpagv.hxx>
35 #include <svx/svdopath.hxx> // zur Abschaltung
36 #include <svx/svdogrp.hxx>  // des Cache bei
37 #include <svx/svdorect.hxx> // GetMarkDescription
38 #include "svx/svdstr.hrc"   // Namen aus der Resource
39 #include "svx/svdglob.hxx"  // StringCache
40 
41 ////////////////////////////////////////////////////////////////////////////////////////////////////
42 #include <svx/obj3d.hxx>
43 #include <svx/scene3d.hxx>
44 #include <svl/brdcst.hxx>
45 #include <svx/svdoedge.hxx>
46 
47 ////////////////////////////////////////////////////////////////////////////////////////////////////
48 
49 class ImpSdrUShortContSorter: public ContainerSorter
50 {
51 public:
ImpSdrUShortContSorter(Container & rNewCont)52 	ImpSdrUShortContSorter(Container& rNewCont)
53 	:	ContainerSorter(rNewCont)
54 	{}
55 
56 	virtual int Compare(const void* pElem1, const void* pElem2) const;
57 };
58 
Compare(const void * pElem1,const void * pElem2) const59 int ImpSdrUShortContSorter::Compare(const void* pElem1, const void* pElem2) const
60 {
61 	sal_uInt16 n1((sal_uInt16)((sal_uIntPtr)pElem1));
62 	sal_uInt16 n2((sal_uInt16)((sal_uIntPtr)pElem2));
63 
64 	return ((n1 < n2) ? (-1) : (n1 > n2) ? (1) : (0));
65 }
66 
Sort() const67 void SdrUShortCont::Sort() const
68 {
69 	ImpSdrUShortContSorter aSort(*((Container*)(&maArray)));
70 	aSort.DoSort();
71 	((SdrUShortCont*)this)->mbSorted = sal_True;
72 
73 	sal_uLong nNum(GetCount());
74 
75 	if(nNum > 1)
76 	{
77 		nNum--;
78 		sal_uInt16 nVal0 = GetObject(nNum);
79 
80 		while(nNum > 0)
81 		{
82 			nNum--;
83 			sal_uInt16 nVal1 = GetObject(nNum);
84 
85 			if(nVal1 == nVal0)
86 			{
87 				((SdrUShortCont*)this)->Remove(nNum);
88 			}
89 
90 			nVal0 = nVal1;
91 		}
92 	}
93 }
94 
CheckSort(sal_uLong nPos)95 void SdrUShortCont::CheckSort(sal_uLong nPos)
96 {
97 	sal_uLong nAnz(maArray.Count());
98 
99 	if(nPos > nAnz)
100 		nPos = nAnz;
101 
102 	sal_uInt16 nAktVal = GetObject(nPos);
103 
104 	if(nPos > 0)
105 	{
106 		sal_uInt16 nPrevVal = GetObject(nPos - 1);
107 
108 		if(nPrevVal >= nAktVal)
109 			mbSorted = sal_False;
110 	}
111 
112 	if(nPos < nAnz - 1)
113 	{
114 		sal_uInt16 nNextVal = GetObject(nPos + 1);
115 
116 		if(nNextVal <= nAktVal)
117 			mbSorted = sal_False;
118 	}
119 }
120 
getContainer()121 std::set< sal_uInt16 > SdrUShortCont::getContainer()
122 {
123 	std::set< sal_uInt16 > aSet;
124 
125 	sal_uInt32 nAnz = maArray.Count();
126 	while(nAnz)
127 		aSet.insert( GetObject(--nAnz) );
128 
129 	return aSet;
130 }
131 
132 ////////////////////////////////////////////////////////////////////////////////////////////////////
133 
SdrMark(SdrObject * pNewObj,SdrPageView * pNewPageView)134 SdrMark::SdrMark(SdrObject* pNewObj, SdrPageView* pNewPageView)
135 :	mpSelectedSdrObject(pNewObj),
136 	mpPageView(pNewPageView),
137 	mpPoints(0L),
138 	mpLines(0L),
139 	mpGluePoints(0L),
140 	mbCon1(sal_False),
141 	mbCon2(sal_False),
142 	mnUser(0)
143 {
144 	if(mpSelectedSdrObject)
145 	{
146 		mpSelectedSdrObject->AddObjectUser( *this );
147 	}
148 }
149 
SdrMark(const SdrMark & rMark)150 SdrMark::SdrMark(const SdrMark& rMark)
151 :	ObjectUser(),
152     mpSelectedSdrObject(0L),
153 	mpPageView(0L),
154 	mpPoints(0L),
155 	mpLines(0L),
156 	mpGluePoints(0L),
157 	mbCon1(sal_False),
158 	mbCon2(sal_False),
159 	mnUser(0)
160 {
161 	*this = rMark;
162 }
163 
~SdrMark()164 SdrMark::~SdrMark()
165 {
166 	if(mpSelectedSdrObject)
167 	{
168 		mpSelectedSdrObject->RemoveObjectUser( *this );
169 	}
170 
171 	if(mpPoints)
172 	{
173 		delete mpPoints;
174 	}
175 
176 	if(mpLines)
177 	{
178 		delete mpLines;
179 	}
180 
181 	if(mpGluePoints)
182 	{
183 		delete mpGluePoints;
184 	}
185 }
186 
ObjectInDestruction(const SdrObject & rObject)187 void SdrMark::ObjectInDestruction(const SdrObject& rObject)
188 {
189     (void) rObject; // avoid warnings
190 	OSL_ENSURE(mpSelectedSdrObject && mpSelectedSdrObject == &rObject, "SdrMark::ObjectInDestruction: called form object different from hosted one (!)");
191 	OSL_ENSURE(mpSelectedSdrObject, "SdrMark::ObjectInDestruction: still seleceted SdrObject is deleted, deselect first (!)");
192 	mpSelectedSdrObject = 0L;
193 }
194 
SetMarkedSdrObj(SdrObject * pNewObj)195 void SdrMark::SetMarkedSdrObj(SdrObject* pNewObj)
196 {
197 	if(mpSelectedSdrObject)
198 	{
199 		mpSelectedSdrObject->RemoveObjectUser( *this );
200 	}
201 
202 	mpSelectedSdrObject = pNewObj;
203 
204 	if(mpSelectedSdrObject)
205 	{
206 		mpSelectedSdrObject->AddObjectUser( *this );
207 	}
208 }
209 
GetMarkedSdrObj() const210 SdrObject* SdrMark::GetMarkedSdrObj() const
211 {
212 	return mpSelectedSdrObject;
213 }
214 
operator =(const SdrMark & rMark)215 SdrMark& SdrMark::operator=(const SdrMark& rMark)
216 {
217 	SetMarkedSdrObj(rMark.mpSelectedSdrObject);
218 	mpPageView = rMark.mpPageView;
219 	mbCon1 = rMark.mbCon1;
220 	mbCon2 = rMark.mbCon2;
221 	mnUser = rMark.mnUser;
222 
223 	if(!rMark.mpPoints)
224 	{
225 		if(mpPoints)
226 		{
227 			delete mpPoints;
228 			mpPoints = 0L;
229 		}
230 	}
231 	else
232 	{
233 		if(!mpPoints)
234 		{
235 			mpPoints = new SdrUShortCont(*rMark.mpPoints);
236 		}
237 		else
238 		{
239 			*mpPoints = *rMark.mpPoints;
240 		}
241 	}
242 
243 	if(!rMark.mpLines)
244 	{
245 		if(mpLines)
246 		{
247 			delete mpLines;
248 			mpLines = 0L;
249 		}
250 	}
251 	else
252 	{
253 		if(!mpLines)
254 		{
255 			mpLines = new SdrUShortCont(*rMark.mpLines);
256 		}
257 		else
258 		{
259 			*mpLines = *rMark.mpLines;
260 		}
261 	}
262 
263 	if(!rMark.mpGluePoints)
264 	{
265 		if(mpGluePoints)
266 		{
267 			delete mpGluePoints;
268 			mpGluePoints = 0L;
269 		}
270 	}
271 	else
272 	{
273 		if(!mpGluePoints)
274 		{
275 			mpGluePoints = new SdrUShortCont(*rMark.mpGluePoints);
276 		}
277 		else
278 		{
279 			*mpGluePoints = *rMark.mpGluePoints;
280 		}
281 	}
282 
283 	return *this;
284 }
285 
operator ==(const SdrMark & rMark) const286 sal_Bool SdrMark::operator==(const SdrMark& rMark) const
287 {
288 	sal_Bool bRet(mpSelectedSdrObject == rMark.mpSelectedSdrObject && mpPageView == rMark.mpPageView && mbCon1 == rMark.mbCon1 && mbCon2 == rMark.mbCon2 && mnUser == rMark.mnUser);
289 
290 	if((mpPoints != 0L) != (rMark.mpPoints != 0L))
291 		bRet = sal_False;
292 
293 	if((mpLines != 0L) != (rMark.mpLines != 0L))
294 		bRet = sal_False;
295 
296 	if((mpGluePoints != 0L) != (rMark.mpGluePoints != 0L))
297 		bRet = sal_False;
298 
299 	if(bRet && mpPoints && *mpPoints != *rMark.mpPoints)
300 		bRet = sal_False;
301 
302 	if(bRet && mpLines && *mpLines != *rMark.mpLines)
303 		bRet = sal_False;
304 
305 	if(bRet && mpGluePoints && *mpGluePoints != *rMark.mpGluePoints)
306 		bRet = sal_False;
307 
308 	return bRet;
309 }
310 
GetPage() const311 SdrPage* SdrMark::GetPage() const
312 {
313 	return (mpSelectedSdrObject ? mpSelectedSdrObject->GetPage() : 0);
314 }
315 
GetObjList() const316 SdrObjList* SdrMark::GetObjList() const
317 {
318 	return (mpSelectedSdrObject ? mpSelectedSdrObject->GetObjList() : 0);
319 }
320 
321 ////////////////////////////////////////////////////////////////////////////////////////////////////
322 
323 class ImpSdrMarkListSorter: public ContainerSorter
324 {
325 public:
ImpSdrMarkListSorter(Container & rNewCont)326 	ImpSdrMarkListSorter(Container& rNewCont)
327         :	ContainerSorter(rNewCont)
328 	{}
329 
330 	virtual int Compare(const void* pElem1, const void* pElem2) const;
331 };
332 
Compare(const void * pElem1,const void * pElem2) const333 int ImpSdrMarkListSorter::Compare(const void* pElem1, const void* pElem2) const
334 {
335 	SdrObject* pObj1 = ((SdrMark*)pElem1)->GetMarkedSdrObj();
336 	SdrObject* pObj2 = ((SdrMark*)pElem2)->GetMarkedSdrObj();
337 	SdrObjList* pOL1 = (pObj1) ? pObj1->GetObjList() : 0L;
338 	SdrObjList* pOL2 = (pObj2) ? pObj2->GetObjList() : 0L;
339 
340 	if (pOL1 == pOL2)
341     {
342         // AF: Note that I reverted a change from sal_uInt32 to sal_uLong (made
343         // for 64bit compliance, #i78198#) because internally in SdrObject
344         // both nOrdNum and mnNavigationPosition are stored as sal_uInt32.
345         sal_uInt32 nObjOrd1((pObj1) ? pObj1->GetNavigationPosition() : 0);
346         sal_uInt32 nObjOrd2((pObj2) ? pObj2->GetNavigationPosition() : 0);
347 
348         return (nObjOrd1 < nObjOrd2 ? -1 : 1);
349     }
350 	else
351 	{
352 		return ((long)pOL1 < (long)pOL2) ? -1 : 1;
353 	}
354 }
355 
356 ////////////////////////////////////////////////////////////////////////////////////////////////////
357 
ForceSort() const358 void SdrMarkList::ForceSort() const
359 {
360 	if(!mbSorted)
361 	{
362 		((SdrMarkList*)this)->ImpForceSort();
363 	}
364 }
365 
ImpForceSort()366 void SdrMarkList::ImpForceSort()
367 {
368 	if(!mbSorted)
369 	{
370 		mbSorted = sal_True;
371 		sal_uLong nAnz = maList.Count();
372 
373 		// remove invalid
374 		if(nAnz > 0 )
375 		{
376 			SdrMark* pAkt = (SdrMark*)maList.First();
377 			while( pAkt )
378 			{
379 				if(pAkt->GetMarkedSdrObj() == 0)
380 				{
381 					maList.Remove();
382 					delete pAkt;
383 				}
384 				pAkt= (SdrMark*)maList.Next();
385 			}
386 			nAnz = maList.Count();
387 		}
388 
389 		if(nAnz > 1)
390 		{
391 			ImpSdrMarkListSorter aSort(maList);
392 			aSort.DoSort();
393 
394 			// remove duplicates
395 			if(maList.Count() > 1)
396 			{
397 				SdrMark* pAkt = (SdrMark*)maList.Last();
398 				SdrMark* pCmp = (SdrMark*)maList.Prev();
399 
400 				while(pCmp)
401 				{
402 					if(pAkt->GetMarkedSdrObj() == pCmp->GetMarkedSdrObj() && pAkt->GetMarkedSdrObj())
403 					{
404 						// Con1/Con2 Merging
405 						if(pCmp->IsCon1())
406 							pAkt->SetCon1(sal_True);
407 
408 						if(pCmp->IsCon2())
409 							pAkt->SetCon2(sal_True);
410 
411 						// pCmp loeschen.
412 						maList.Remove();
413 
414 						delete pCmp;
415 					}
416 					else
417 					{
418 						pAkt = pCmp;
419 					}
420 
421 					pCmp = (SdrMark*)maList.Prev();
422 				}
423 			}
424 		}
425 	}
426 }
427 
Clear()428 void SdrMarkList::Clear()
429 {
430 	for(sal_uLong i(0L); i < GetMarkCount(); i++)
431 	{
432 		SdrMark* pMark = GetMark(i);
433 		delete pMark;
434 	}
435 
436 	maList.Clear();
437 	SetNameDirty();
438 }
439 
operator =(const SdrMarkList & rLst)440 void SdrMarkList::operator=(const SdrMarkList& rLst)
441 {
442 	Clear();
443 
444 	for(sal_uLong i(0L); i < rLst.GetMarkCount(); i++)
445 	{
446 		SdrMark* pMark = rLst.GetMark(i);
447 		SdrMark* pNeuMark = new SdrMark(*pMark);
448 		maList.Insert(pNeuMark, CONTAINER_APPEND);
449 	}
450 
451 	maMarkName = rLst.maMarkName;
452 	mbNameOk = rLst.mbNameOk;
453 	maPointName = rLst.maPointName;
454 	mbPointNameOk = rLst.mbPointNameOk;
455 	maGluePointName = rLst.maGluePointName;
456 	mbGluePointNameOk = rLst.mbGluePointNameOk;
457 	mbSorted = rLst.mbSorted;
458 }
459 
FindObject(const SdrObject * pObj) const460 sal_uLong SdrMarkList::FindObject(const SdrObject* pObj) const
461 {
462 	// #109658#
463 	//
464 	// Since relying on OrdNums is not allowed for the selection because objects in the
465 	// selection may not be inserted in a list if they are e.g. modified ATM, i changed
466 	// this loop to just look if the object pointer is in the selection.
467 	//
468 	// Problem is that GetOrdNum() which is const, internally casts to non-const and
469 	// hardly sets the OrdNum member of the object (nOrdNum) to 0 (ZERO) if the object
470 	// is not inserted in a object list.
471 	// Since this may be by purpose and necessary somewhere else i decided that it is
472 	// less dangerous to change this method then changing SdrObject::GetOrdNum().
473 	if(pObj && maList.Count())
474 	{
475 		for(sal_uLong a(0L); a < maList.Count(); a++)
476 		{
477 			if(((SdrMark*)(maList.GetObject(a)))->GetMarkedSdrObj() == pObj)
478 			{
479 				return a;
480 			}
481 		}
482 	}
483 
484 	return CONTAINER_ENTRY_NOTFOUND;
485 }
486 
InsertEntry(const SdrMark & rMark,sal_Bool bChkSort)487 void SdrMarkList::InsertEntry(const SdrMark& rMark, sal_Bool bChkSort)
488 {
489 	SetNameDirty();
490 	sal_uLong nAnz(maList.Count());
491 
492 	if(!bChkSort || !mbSorted || nAnz == 0)
493 	{
494 		if(!bChkSort)
495 			mbSorted = sal_False;
496 
497 		maList.Insert(new SdrMark(rMark), CONTAINER_APPEND);
498 	}
499 	else
500 	{
501 		SdrMark* pLast = GetMark(sal_uLong(nAnz - 1));
502 		const SdrObject* pLastObj = pLast->GetMarkedSdrObj();
503 		const SdrObject* pNeuObj = rMark.GetMarkedSdrObj();
504 
505 		if(pLastObj == pNeuObj)
506 		{
507 			// Aha, den gibt's schon
508 			// Con1/Con2 Merging
509 			if(rMark.IsCon1())
510 				pLast->SetCon1(sal_True);
511 
512 			if(rMark.IsCon2())
513 				pLast->SetCon2(sal_True);
514 		}
515 		else
516 		{
517 			SdrMark* pKopie = new SdrMark(rMark);
518 			maList.Insert(pKopie, CONTAINER_APPEND);
519 
520 			// und nun checken, ob die Sortierung noch ok ist
521 			const SdrObjList* pLastOL = pLastObj!=0L ? pLastObj->GetObjList() : 0L;
522 			const SdrObjList* pNeuOL = pNeuObj !=0L ? pNeuObj ->GetObjList() : 0L;
523 
524 			if(pLastOL == pNeuOL)
525 			{
526 				const sal_uLong nLastNum(pLastObj!=0L ? pLastObj->GetOrdNum() : 0);
527 				const sal_uLong nNeuNum(pNeuObj !=0L ? pNeuObj ->GetOrdNum() : 0);
528 
529 				if(nNeuNum < nLastNum)
530 				{
531 					// irgendwann muss mal sortiert werden
532 					mbSorted = sal_False;
533 				}
534 			}
535 			else
536 			{
537 				// irgendwann muss mal sortiert werden
538 				mbSorted = sal_False;
539 			}
540 		}
541 	}
542 
543 	return;
544 }
545 
DeleteMark(sal_uLong nNum)546 void SdrMarkList::DeleteMark(sal_uLong nNum)
547 {
548 	SdrMark* pMark = GetMark(nNum);
549 	DBG_ASSERT(pMark!=0L,"DeleteMark: MarkEntry nicht gefunden");
550 
551 	if(pMark)
552 	{
553 		maList.Remove(nNum);
554 		delete pMark;
555 		SetNameDirty();
556 	}
557 }
558 
ReplaceMark(const SdrMark & rNewMark,sal_uLong nNum)559 void SdrMarkList::ReplaceMark(const SdrMark& rNewMark, sal_uLong nNum)
560 {
561 	SdrMark* pMark = GetMark(nNum);
562 	DBG_ASSERT(pMark!=0L,"ReplaceMark: MarkEntry nicht gefunden");
563 
564 	if(pMark)
565 	{
566 		delete pMark;
567 		SetNameDirty();
568 		SdrMark* pKopie = new SdrMark(rNewMark);
569 		maList.Replace(pKopie, nNum);
570 		mbSorted = sal_False;
571 	}
572 }
573 
Merge(const SdrMarkList & rSrcList,sal_Bool bReverse)574 void SdrMarkList::Merge(const SdrMarkList& rSrcList, sal_Bool bReverse)
575 {
576 	sal_uLong nAnz(rSrcList.maList.Count());
577 
578 	if(rSrcList.mbSorted)
579 	{
580 		// Merging ohne ein Sort bei rSrcList zu erzwingen
581 		bReverse = sal_False;
582 	}
583 
584 	if(!bReverse)
585 	{
586 		for(sal_uLong i(0L); i < nAnz; i++)
587 		{
588 			SdrMark* pM = (SdrMark*)(rSrcList.maList.GetObject(i));
589 			InsertEntry(*pM);
590 		}
591 	}
592 	else
593 	{
594 		for(sal_uLong i(nAnz); i > 0;)
595 		{
596 			i--;
597 			SdrMark* pM = (SdrMark*)(rSrcList.maList.GetObject(i));
598 			InsertEntry(*pM);
599 		}
600 	}
601 }
602 
DeletePageView(const SdrPageView & rPV)603 sal_Bool SdrMarkList::DeletePageView(const SdrPageView& rPV)
604 {
605 	sal_Bool bChgd(sal_False);
606 
607 	for(sal_uLong i(GetMarkCount()); i > 0; )
608 	{
609 		i--;
610 		SdrMark* pMark = GetMark(i);
611 
612 		if(pMark->GetPageView()==&rPV)
613 		{
614 			maList.Remove(i);
615 			delete pMark;
616 			SetNameDirty();
617 			bChgd = sal_True;
618 		}
619 	}
620 
621 	return bChgd;
622 }
623 
InsertPageView(const SdrPageView & rPV)624 sal_Bool SdrMarkList::InsertPageView(const SdrPageView& rPV)
625 {
626 	sal_Bool bChgd(sal_False);
627 	DeletePageView(rPV); // erstmal alle raus, dann die ganze Seite hinten dran
628 	SdrObject* pObj;
629 	const SdrObjList* pOL = rPV.GetObjList();
630 	sal_uLong nObjAnz(pOL->GetObjCount());
631 
632 	for(sal_uLong nO(0L); nO < nObjAnz; nO++)
633 	{
634 		pObj = pOL->GetObj(nO);
635 		sal_Bool bDoIt(rPV.IsObjMarkable(pObj));
636 
637 		if(bDoIt)
638 		{
639 			SdrMark* pM = new SdrMark(pObj, (SdrPageView*)&rPV);
640 			maList.Insert(pM, CONTAINER_APPEND);
641 			SetNameDirty();
642 			bChgd = sal_True;
643 		}
644 	}
645 
646 	return bChgd;
647 }
648 
GetMarkDescription() const649 const XubString& SdrMarkList::GetMarkDescription() const
650 {
651 	sal_uLong nAnz(GetMarkCount());
652 
653 	if(mbNameOk && 1L == nAnz)
654 	{
655 		// Bei Einfachselektion nur Textrahmen cachen
656 		const SdrObject* pObj = GetMark(0)->GetMarkedSdrObj();
657 		const SdrTextObj* pTextObj = PTR_CAST(SdrTextObj, pObj);
658 
659 		if(!pTextObj || !pTextObj->IsTextFrame())
660 		{
661 			((SdrMarkList*)(this))->mbNameOk = sal_False;
662 		}
663 	}
664 
665 	if(!mbNameOk)
666 	{
667 		SdrMark* pMark = GetMark(0);
668 		XubString aNam;
669 
670 		if(!nAnz)
671 		{
672 			((SdrMarkList*)(this))->maMarkName = ImpGetResStr(STR_ObjNameNoObj);
673 		}
674 		else if(1L == nAnz)
675 		{
676 			if(pMark->GetMarkedSdrObj())
677 			{
678 				pMark->GetMarkedSdrObj()->TakeObjNameSingul(aNam);
679 			}
680 		}
681 		else
682 		{
683 			if(pMark->GetMarkedSdrObj())
684 			{
685 				pMark->GetMarkedSdrObj()->TakeObjNamePlural(aNam);
686 				XubString aStr1;
687 				sal_Bool bEq(sal_True);
688 
689 				for(sal_uLong i = 1; i < GetMarkCount() && bEq; i++)
690 				{
691 					SdrMark* pMark2 = GetMark(i);
692 					pMark2->GetMarkedSdrObj()->TakeObjNamePlural(aStr1);
693 					bEq = aNam.Equals(aStr1);
694 				}
695 
696 				if(!bEq)
697 				{
698 					aNam = ImpGetResStr(STR_ObjNamePlural);
699 				}
700 			}
701 
702 			aNam.Insert(sal_Unicode(' '), 0);
703 			aNam.Insert(UniString::CreateFromInt32(nAnz), 0);
704 		}
705 
706 		((SdrMarkList*)(this))->maMarkName = aNam;
707 		((SdrMarkList*)(this))->mbNameOk = sal_True;
708 	}
709 
710 	return maMarkName;
711 }
712 
GetPointMarkDescription(sal_Bool bGlue) const713 const XubString& SdrMarkList::GetPointMarkDescription(sal_Bool bGlue) const
714 {
715 	sal_Bool& rNameOk = (sal_Bool&)(bGlue ? mbGluePointNameOk : mbPointNameOk);
716 	XubString& rName = (XubString&)(bGlue ? maGluePointName : maPointName);
717 	sal_uLong nMarkAnz(GetMarkCount());
718 	sal_uLong nMarkPtAnz(0L);
719 	sal_uLong nMarkPtObjAnz(0L);
720 	sal_uLong n1stMarkNum(ULONG_MAX);
721 
722 	for(sal_uLong nMarkNum(0L); nMarkNum < nMarkAnz; nMarkNum++)
723 	{
724 		const SdrMark* pMark = GetMark(nMarkNum);
725 		const SdrUShortCont* pPts = bGlue ? pMark->GetMarkedGluePoints() : pMark->GetMarkedPoints();
726 		sal_uLong nAnz(pPts ? pPts->GetCount() : 0);
727 
728 		if(nAnz)
729 		{
730 			if(n1stMarkNum == ULONG_MAX)
731 			{
732 				n1stMarkNum = nMarkNum;
733 			}
734 
735 			nMarkPtAnz += nAnz;
736 			nMarkPtObjAnz++;
737 		}
738 
739 		if(nMarkPtObjAnz > 1 && rNameOk)
740 		{
741 			// vorzeitige Entscheidung
742 			return rName;
743 		}
744 	}
745 
746 	if(rNameOk && 1L == nMarkPtObjAnz)
747 	{
748 		// Bei Einfachselektion nur Textrahmen cachen
749 		const SdrObject* pObj = GetMark(0)->GetMarkedSdrObj();
750 		const SdrTextObj* pTextObj = PTR_CAST(SdrTextObj,pObj);
751 
752 		if(!pTextObj || !pTextObj->IsTextFrame())
753 		{
754 			rNameOk = sal_False;
755 		}
756 	}
757 
758 	if(!nMarkPtObjAnz)
759 	{
760 		rName.Erase();
761 		rNameOk = sal_True;
762 	}
763 	else if(!rNameOk)
764 	{
765 		const SdrMark* pMark = GetMark(n1stMarkNum);
766 		XubString aNam;
767 
768 		if(1L == nMarkPtObjAnz)
769 		{
770 			if(pMark->GetMarkedSdrObj())
771 			{
772 				pMark->GetMarkedSdrObj()->TakeObjNameSingul(aNam);
773 			}
774 		}
775 		else
776 		{
777 			if(pMark->GetMarkedSdrObj())
778 			{
779 				pMark->GetMarkedSdrObj()->TakeObjNamePlural(aNam);
780 			}
781 
782 			XubString aStr1;
783 			sal_Bool bEq(sal_True);
784 
785 			for(sal_uLong i(n1stMarkNum + 1L); i < GetMarkCount() && bEq; i++)
786 			{
787 				const SdrMark* pMark2 = GetMark(i);
788 				const SdrUShortCont* pPts = bGlue ? pMark2->GetMarkedGluePoints() : pMark2->GetMarkedPoints();
789 
790 				if(pPts && pPts->GetCount() && pMark2->GetMarkedSdrObj())
791 				{
792 					pMark2->GetMarkedSdrObj()->TakeObjNamePlural(aStr1);
793 					bEq = aNam.Equals(aStr1);
794 				}
795 			}
796 
797 			if(!bEq)
798 			{
799 				aNam = ImpGetResStr(STR_ObjNamePlural);
800 			}
801 
802 			aNam.Insert(sal_Unicode(' '), 0);
803 			aNam.Insert(UniString::CreateFromInt32(nMarkPtObjAnz), 0);
804 		}
805 
806 		XubString aStr1;
807 
808 		if(1L == nMarkPtAnz)
809 		{
810 			aStr1 = (ImpGetResStr(bGlue ? STR_ViewMarkedGluePoint : STR_ViewMarkedPoint));
811 		}
812 		else
813 		{
814 			aStr1 = (ImpGetResStr(bGlue ? STR_ViewMarkedGluePoints : STR_ViewMarkedPoints));
815 			aStr1.SearchAndReplaceAscii("%2", UniString::CreateFromInt32(nMarkPtAnz));
816 		}
817 
818 		aStr1.SearchAndReplaceAscii("%1", aNam);
819 		rName = aStr1;
820 		rNameOk = sal_True;
821 	}
822 
823 	return rName;
824 }
825 
TakeBoundRect(SdrPageView * pPV,Rectangle & rRect) const826 sal_Bool SdrMarkList::TakeBoundRect(SdrPageView* pPV, Rectangle& rRect) const
827 {
828 	sal_Bool bFnd(sal_False);
829 	Rectangle aR;
830 
831 	for(sal_uLong i(0L); i < GetMarkCount(); i++)
832 	{
833 		SdrMark* pMark = GetMark(i);
834 
835 		if(!pPV || pMark->GetPageView() == pPV)
836 		{
837 			if(pMark->GetMarkedSdrObj())
838 			{
839 				aR = pMark->GetMarkedSdrObj()->GetCurrentBoundRect();
840 
841 				if(bFnd)
842 				{
843 					rRect.Union(aR);
844 				}
845 				else
846 				{
847 					rRect = aR;
848 					bFnd = sal_True;
849 				}
850 			}
851 		}
852 	}
853 
854 	return bFnd;
855 }
856 
TakeSnapRect(SdrPageView * pPV,Rectangle & rRect) const857 sal_Bool SdrMarkList::TakeSnapRect(SdrPageView* pPV, Rectangle& rRect) const
858 {
859 	sal_Bool bFnd(sal_False);
860 
861 	for(sal_uLong i(0L); i < GetMarkCount(); i++)
862 	{
863 		SdrMark* pMark = GetMark(i);
864 
865 		if(!pPV || pMark->GetPageView() == pPV)
866 		{
867 			if(pMark->GetMarkedSdrObj())
868 			{
869 				Rectangle aR(pMark->GetMarkedSdrObj()->GetSnapRect());
870 
871 				if(bFnd)
872 				{
873 					rRect.Union(aR);
874 				}
875 				else
876 				{
877 					rRect = aR;
878 					bFnd = sal_True;
879 				}
880 			}
881 		}
882 	}
883 
884 	return bFnd;
885 }
886 
887 ////////////////////////////////////////////////////////////////////////////////////////////////////
888 
889 namespace sdr
890 {
ViewSelection()891 	ViewSelection::ViewSelection()
892 	:	mbEdgesOfMarkedNodesDirty(sal_False)
893 	{
894 	}
895 
SetEdgesOfMarkedNodesDirty()896 	void ViewSelection::SetEdgesOfMarkedNodesDirty()
897 	{
898 		if(!mbEdgesOfMarkedNodesDirty)
899 		{
900 			mbEdgesOfMarkedNodesDirty = sal_True;
901 			maEdgesOfMarkedNodes.Clear();
902 			maMarkedEdgesOfMarkedNodes.Clear();
903 			maAllMarkedObjects.Clear();
904 		}
905 	}
906 
GetEdgesOfMarkedNodes() const907 	const SdrMarkList& ViewSelection::GetEdgesOfMarkedNodes() const
908 	{
909 		if(mbEdgesOfMarkedNodesDirty)
910 		{
911 			((ViewSelection*)this)->ImpForceEdgesOfMarkedNodes();
912 		}
913 
914 		return maEdgesOfMarkedNodes;
915 	}
916 
GetMarkedEdgesOfMarkedNodes() const917 	const SdrMarkList& ViewSelection::GetMarkedEdgesOfMarkedNodes() const
918 	{
919 		if(mbEdgesOfMarkedNodesDirty)
920 		{
921 			((ViewSelection*)this)->ImpForceEdgesOfMarkedNodes();
922 		}
923 
924 		return maMarkedEdgesOfMarkedNodes;
925 	}
926 
GetAllMarkedObjects() const927 	const List& ViewSelection::GetAllMarkedObjects() const
928 	{
929 		if(mbEdgesOfMarkedNodesDirty)
930 		{
931 			((ViewSelection*)this)->ImpForceEdgesOfMarkedNodes();
932 		}
933 
934 		return maAllMarkedObjects;
935 	}
936 
ImplCollectCompleteSelection(SdrObject * pObj)937 	void ViewSelection::ImplCollectCompleteSelection(SdrObject* pObj)
938 	{
939 		if(pObj)
940 		{
941 			sal_Bool bIsGroup(pObj->IsGroupObject());
942 
943 			if(bIsGroup && pObj->ISA(E3dObject) && !pObj->ISA(E3dScene))
944 			{
945 				bIsGroup = sal_False;
946 			}
947 
948 			if(bIsGroup)
949 			{
950 				SdrObjList* pList = pObj->GetSubList();
951 
952 				for(sal_uLong a(0L); a < pList->GetObjCount(); a++)
953 				{
954 					SdrObject* pObj2 = pList->GetObj(a);
955 					ImplCollectCompleteSelection(pObj2);
956 				}
957 			}
958 
959 			maAllMarkedObjects.Insert(pObj, LIST_APPEND);
960 		}
961 	}
962 
ImpForceEdgesOfMarkedNodes()963 	void ViewSelection::ImpForceEdgesOfMarkedNodes()
964 	{
965 		if(mbEdgesOfMarkedNodesDirty)
966 		{
967 			mbEdgesOfMarkedNodesDirty = sal_False;
968 			maMarkedObjectList.ForceSort();
969 			maEdgesOfMarkedNodes.Clear();
970 			maMarkedEdgesOfMarkedNodes.Clear();
971 			maAllMarkedObjects.Clear();
972 
973 			// #126320# GetMarkCount after ForceSort
974 			const sal_uLong nMarkAnz(maMarkedObjectList.GetMarkCount());
975 
976 			for(sal_uLong a(0L); a < nMarkAnz; a++)
977 			{
978 				SdrObject* pCandidate = maMarkedObjectList.GetMark(a)->GetMarkedSdrObj();
979 
980 				if(pCandidate)
981 				{
982 					// build transitive hull
983 					ImplCollectCompleteSelection(pCandidate);
984 
985 					if(pCandidate->IsNode())
986 					{
987 						// travel over broadcaster/listener to access edges connected to the selected object
988 						const SfxBroadcaster* pBC = pCandidate->GetBroadcaster();
989 
990 						if(pBC)
991 						{
992 							sal_uInt16 nLstAnz(pBC->GetListenerCount());
993 
994 							for(sal_uInt16 nl(0); nl < nLstAnz; nl++)
995 							{
996 								SfxListener* pLst = pBC->GetListener(nl);
997 								SdrEdgeObj* pEdge = PTR_CAST(SdrEdgeObj, pLst);
998 
999 								if(pEdge && pEdge->IsInserted() && pEdge->GetPage() == pCandidate->GetPage())
1000 								{
1001 									SdrMark aM(pEdge, maMarkedObjectList.GetMark(a)->GetPageView());
1002 
1003 									if(pEdge->GetConnectedNode(sal_True) == pCandidate)
1004 									{
1005 										aM.SetCon1(sal_True);
1006 									}
1007 
1008 									if(pEdge->GetConnectedNode(sal_False) == pCandidate)
1009 									{
1010 										aM.SetCon2(sal_True);
1011 									}
1012 
1013 									if(CONTAINER_ENTRY_NOTFOUND == maMarkedObjectList.FindObject(pEdge))
1014 									{
1015 										// nachsehen, ob er selbst markiert ist
1016 										maEdgesOfMarkedNodes.InsertEntry(aM);
1017 									}
1018 									else
1019 									{
1020 										maMarkedEdgesOfMarkedNodes.InsertEntry(aM);
1021 									}
1022 								}
1023 							}
1024 						}
1025 					}
1026 				}
1027 			}
1028 
1029 			maEdgesOfMarkedNodes.ForceSort();
1030 			maMarkedEdgesOfMarkedNodes.ForceSort();
1031 		}
1032 	}
1033 } // end of namespace sdr
1034 
1035 ////////////////////////////////////////////////////////////////////////////////////////////////////
1036 // eof
1037