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