xref: /AOO41X/main/svx/source/svdraw/svdmark.cxx (revision f6e50924346d0b8c0b07c91832a97665dd718b0c)
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