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: 52 ImpSdrUShortContSorter(Container& rNewCont) 53 : ContainerSorter(rNewCont) 54 {} 55 56 virtual int Compare(const void* pElem1, const void* pElem2) const; 57 }; 58 59 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 67 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 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 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 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 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 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 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 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 210 SdrObject* SdrMark::GetMarkedSdrObj() const 211 { 212 return mpSelectedSdrObject; 213 } 214 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 286 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 311 SdrPage* SdrMark::GetPage() const 312 { 313 return (mpSelectedSdrObject ? mpSelectedSdrObject->GetPage() : 0); 314 } 315 316 SdrObjList* SdrMark::GetObjList() const 317 { 318 return (mpSelectedSdrObject ? mpSelectedSdrObject->GetObjList() : 0); 319 } 320 321 //////////////////////////////////////////////////////////////////////////////////////////////////// 322 323 class ImpSdrMarkListSorter: public ContainerSorter 324 { 325 public: 326 ImpSdrMarkListSorter(Container& rNewCont) 327 : ContainerSorter(rNewCont) 328 {} 329 330 virtual int Compare(const void* pElem1, const void* pElem2) const; 331 }; 332 333 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 358 void SdrMarkList::ForceSort() const 359 { 360 if(!mbSorted) 361 { 362 ((SdrMarkList*)this)->ImpForceSort(); 363 } 364 } 365 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 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 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 460 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 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 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 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 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 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 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 649 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 713 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 826 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 857 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 { 891 ViewSelection::ViewSelection() 892 : mbEdgesOfMarkedNodesDirty(sal_False) 893 { 894 } 895 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 907 const SdrMarkList& ViewSelection::GetEdgesOfMarkedNodes() const 908 { 909 if(mbEdgesOfMarkedNodesDirty) 910 { 911 ((ViewSelection*)this)->ImpForceEdgesOfMarkedNodes(); 912 } 913 914 return maEdgesOfMarkedNodes; 915 } 916 917 const SdrMarkList& ViewSelection::GetMarkedEdgesOfMarkedNodes() const 918 { 919 if(mbEdgesOfMarkedNodesDirty) 920 { 921 ((ViewSelection*)this)->ImpForceEdgesOfMarkedNodes(); 922 } 923 924 return maMarkedEdgesOfMarkedNodes; 925 } 926 927 const List& ViewSelection::GetAllMarkedObjects() const 928 { 929 if(mbEdgesOfMarkedNodesDirty) 930 { 931 ((ViewSelection*)this)->ImpForceEdgesOfMarkedNodes(); 932 } 933 934 return maAllMarkedObjects; 935 } 936 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 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