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