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