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