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