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 #include <svx/svdedtv.hxx> 32 #include <editeng/outliner.hxx> 33 #include <svx/svdundo.hxx> 34 #include <svx/svdogrp.hxx> // fuer's Gruppieren 35 #include <svx/svdovirt.hxx> // fuer VirtualObject-Bundling (Writer) 36 #include <svx/svdopath.hxx> // fuer CombineObjects 37 #include <svx/svdpage.hxx> 38 #include <svx/svdpagv.hxx> 39 #include "svx/svditer.hxx" 40 #include <svx/svdograf.hxx> // fuer Possibilities 41 #include <svx/svdoole2.hxx> // und Mtf-Import 42 #include "svx/svdstr.hrc" // Namen aus der Resource 43 #include "svx/svdglob.hxx" // StringCache 44 #include "svdfmtf.hxx" 45 #include <svx/svdetc.hxx> 46 #include <sfx2/basedlgs.hxx> 47 #include <vcl/msgbox.hxx> 48 #include <editeng/outlobj.hxx> 49 #include <editeng/eeitem.hxx> 50 #include <basegfx/polygon/b2dpolypolygon.hxx> 51 #include <basegfx/polygon/b2dpolypolygontools.hxx> 52 53 #include <svx/svxdlg.hxx> //CHINA001 54 #include <svx/dialogs.hrc> //CHINA001 55 56 // #i37011# 57 #include <svx/svdoashp.hxx> 58 #include <basegfx/polygon/b2dpolypolygoncutter.hxx> 59 60 //////////////////////////////////////////////////////////////////////////////////////////////////// 61 //////////////////////////////////////////////////////////////////////////////////////////////////// 62 //////////////////////////////////////////////////////////////////////////////////////////////////// 63 //////////////////////////////////////////////////////////////////////////////////////////////////// 64 // 65 // @@@@@ @@@@@ @@ @@@@@@ @@ @@ @@ @@@@@ @@ @@ 66 // @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ 67 // @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @ @@ 68 // @@@@ @@ @@ @@ @@ @@@@@ @@ @@@@ @@@@@@@ 69 // @@ @@ @@ @@ @@ @@@ @@ @@ @@@@@@@ 70 // @@ @@ @@ @@ @@ @@@ @@ @@ @@@ @@@ 71 // @@@@@ @@@@@ @@ @@ @ @@ @@@@@ @@ @@ 72 // 73 //////////////////////////////////////////////////////////////////////////////////////////////////// 74 //////////////////////////////////////////////////////////////////////////////////////////////////// 75 76 void SdrEditView::ImpBundleVirtObjOfMarkList() 77 { 78 // ... fehlende Implementation 79 } 80 81 SdrObject* SdrEditView::GetMaxToTopObj(SdrObject* /*pObj*/) const 82 { 83 return NULL; 84 } 85 86 SdrObject* SdrEditView::GetMaxToBtmObj(SdrObject* /*pObj*/) const 87 { 88 return NULL; 89 } 90 91 void SdrEditView::ObjOrderChanged(SdrObject* /*pObj*/, sal_uIntPtr /*nOldPos*/, sal_uIntPtr /*nNewPos*/) 92 { 93 } 94 95 void SdrEditView::MovMarkedToTop() 96 { 97 sal_uIntPtr nAnz=GetMarkedObjectCount(); 98 if (nAnz!=0) 99 { 100 const bool bUndo = IsUndoEnabled(); 101 102 if( bUndo ) 103 BegUndo(ImpGetResStr(STR_EditMovToTop),GetDescriptionOfMarkedObjects(),SDRREPFUNC_OBJ_MOVTOTOP); 104 105 SortMarkedObjects(); 106 sal_uIntPtr nm; 107 for (nm=0; nm<nAnz; nm++) 108 { // Ordnums muessen alle stimmen! 109 GetMarkedObjectByIndex(nm)->GetOrdNum(); 110 } 111 sal_Bool bChg=sal_False; 112 SdrObjList* pOL0=NULL; 113 sal_uIntPtr nNewPos=0; 114 for (nm=nAnz; nm>0;) 115 { 116 nm--; 117 SdrMark* pM=GetSdrMarkByIndex(nm); 118 SdrObject* pObj=pM->GetMarkedSdrObj(); 119 SdrObjList* pOL=pObj->GetObjList(); 120 if (pOL!=pOL0) 121 { 122 nNewPos=sal_uIntPtr(pOL->GetObjCount()-1); 123 pOL0=pOL; 124 } 125 sal_uIntPtr nNowPos=pObj->GetOrdNumDirect(); 126 const Rectangle& rBR=pObj->GetCurrentBoundRect(); 127 sal_uIntPtr nCmpPos=nNowPos+1; 128 SdrObject* pMaxObj=GetMaxToTopObj(pObj); 129 if (pMaxObj!=NULL) 130 { 131 sal_uIntPtr nMaxPos=pMaxObj->GetOrdNum(); 132 if (nMaxPos!=0) 133 nMaxPos--; 134 if (nNewPos>nMaxPos) 135 nNewPos=nMaxPos; // diesen nicht ueberholen. 136 if (nNewPos<nNowPos) 137 nNewPos=nNowPos; // aber dabei auch nicht in die falsche Richtung schieben 138 } 139 sal_Bool bEnd=sal_False; 140 while (nCmpPos<nNewPos && !bEnd) 141 { 142 SdrObject* pCmpObj=pOL->GetObj(nCmpPos); 143 if (pCmpObj==NULL) 144 { 145 DBG_ERROR("MovMarkedToTop(): Vergleichsobjekt nicht gefunden"); 146 bEnd=sal_True; 147 } 148 else if (pCmpObj==pMaxObj) 149 { 150 nNewPos=nCmpPos; 151 nNewPos--; 152 bEnd=sal_True; 153 } 154 else if (rBR.IsOver(pCmpObj->GetCurrentBoundRect())) 155 { 156 nNewPos=nCmpPos; 157 bEnd=sal_True; 158 } 159 else 160 { 161 nCmpPos++; 162 } 163 } 164 if (nNowPos!=nNewPos) 165 { 166 bChg=sal_True; 167 pOL->SetObjectOrdNum(nNowPos,nNewPos); 168 if( bUndo ) 169 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoObjectOrdNum(*pObj,nNowPos,nNewPos)); 170 ObjOrderChanged(pObj,nNowPos,nNewPos); 171 } 172 nNewPos--; 173 } 174 175 if( bUndo ) 176 EndUndo(); 177 178 if (bChg) 179 MarkListHasChanged(); 180 } 181 } 182 183 void SdrEditView::MovMarkedToBtm() 184 { 185 sal_uIntPtr nAnz=GetMarkedObjectCount(); 186 if (nAnz!=0) 187 { 188 const bool bUndo = IsUndoEnabled(); 189 190 if( bUndo ) 191 BegUndo(ImpGetResStr(STR_EditMovToBtm),GetDescriptionOfMarkedObjects(),SDRREPFUNC_OBJ_MOVTOBTM); 192 193 SortMarkedObjects(); 194 sal_uIntPtr nm; 195 for (nm=0; nm<nAnz; nm++) 196 { // Ordnums muessen alle stimmen! 197 GetMarkedObjectByIndex(nm)->GetOrdNum(); 198 } 199 200 sal_Bool bChg=sal_False; 201 SdrObjList* pOL0=NULL; 202 sal_uIntPtr nNewPos=0; 203 for (nm=0; nm<nAnz; nm++) 204 { 205 SdrMark* pM=GetSdrMarkByIndex(nm); 206 SdrObject* pObj=pM->GetMarkedSdrObj(); 207 SdrObjList* pOL=pObj->GetObjList(); 208 if (pOL!=pOL0) 209 { 210 nNewPos=0; 211 pOL0=pOL; 212 } 213 sal_uIntPtr nNowPos=pObj->GetOrdNumDirect(); 214 const Rectangle& rBR=pObj->GetCurrentBoundRect(); 215 sal_uIntPtr nCmpPos=nNowPos; if (nCmpPos>0) nCmpPos--; 216 SdrObject* pMaxObj=GetMaxToBtmObj(pObj); 217 if (pMaxObj!=NULL) 218 { 219 sal_uIntPtr nMinPos=pMaxObj->GetOrdNum()+1; 220 if (nNewPos<nMinPos) 221 nNewPos=nMinPos; // diesen nicht ueberholen. 222 if (nNewPos>nNowPos) 223 nNewPos=nNowPos; // aber dabei auch nicht in die falsche Richtung schieben 224 } 225 sal_Bool bEnd=sal_False; 226 // nNewPos ist an dieser Stelle noch die maximale Position, 227 // an der das Obj hinruecken darf, ohne seinen Vorgaenger 228 // (Mehrfachselektion) zu ueberholen. 229 while (nCmpPos>nNewPos && !bEnd) 230 { 231 SdrObject* pCmpObj=pOL->GetObj(nCmpPos); 232 if (pCmpObj==NULL) 233 { 234 DBG_ERROR("MovMarkedToBtm(): Vergleichsobjekt nicht gefunden"); 235 bEnd=sal_True; 236 } 237 else if (pCmpObj==pMaxObj) 238 { 239 nNewPos=nCmpPos; 240 nNewPos++; 241 bEnd=sal_True; 242 } 243 else if (rBR.IsOver(pCmpObj->GetCurrentBoundRect())) 244 { 245 nNewPos=nCmpPos; 246 bEnd=sal_True; 247 } 248 else 249 { 250 nCmpPos--; 251 } 252 } 253 if (nNowPos!=nNewPos) 254 { 255 bChg=sal_True; 256 pOL->SetObjectOrdNum(nNowPos,nNewPos); 257 if( bUndo ) 258 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoObjectOrdNum(*pObj,nNowPos,nNewPos)); 259 ObjOrderChanged(pObj,nNowPos,nNewPos); 260 } 261 nNewPos++; 262 } 263 264 if(bUndo) 265 EndUndo(); 266 267 if(bChg) 268 MarkListHasChanged(); 269 } 270 } 271 272 void SdrEditView::PutMarkedToTop() 273 { 274 PutMarkedInFrontOfObj(NULL); 275 } 276 277 void SdrEditView::PutMarkedInFrontOfObj(const SdrObject* pRefObj) 278 { 279 sal_uIntPtr nAnz=GetMarkedObjectCount(); 280 if (nAnz!=0) 281 { 282 const bool bUndo = IsUndoEnabled(); 283 if( bUndo ) 284 BegUndo(ImpGetResStr(STR_EditPutToTop),GetDescriptionOfMarkedObjects(),SDRREPFUNC_OBJ_PUTTOTOP); 285 286 SortMarkedObjects(); 287 288 if (pRefObj!=NULL) 289 { 290 // Damit "Vor das Objekt" auch funktioniert wenn die 291 // markierten Objekte bereits vor dem Objekt stehen 292 sal_uIntPtr nRefMark=TryToFindMarkedObject(pRefObj); 293 SdrMark aRefMark; 294 if (nRefMark!=CONTAINER_ENTRY_NOTFOUND) 295 { 296 aRefMark=*GetSdrMarkByIndex(nRefMark); 297 GetMarkedObjectListWriteAccess().DeleteMark(nRefMark); 298 } 299 PutMarkedToBtm(); 300 if (nRefMark!=CONTAINER_ENTRY_NOTFOUND) 301 { 302 GetMarkedObjectListWriteAccess().InsertEntry(aRefMark); 303 SortMarkedObjects(); 304 } 305 } 306 sal_uIntPtr nm; 307 for (nm=0; nm<nAnz; nm++) 308 { // Ordnums muessen alle stimmen! 309 GetMarkedObjectByIndex(nm)->GetOrdNum(); 310 } 311 sal_Bool bChg=sal_False; 312 SdrObjList* pOL0=NULL; 313 sal_uIntPtr nNewPos=0; 314 for (nm=nAnz; nm>0;) 315 { 316 nm--; 317 SdrMark* pM=GetSdrMarkByIndex(nm); 318 SdrObject* pObj=pM->GetMarkedSdrObj(); 319 if (pObj!=pRefObj) 320 { 321 SdrObjList* pOL=pObj->GetObjList(); 322 if (pOL!=pOL0) 323 { 324 nNewPos=sal_uIntPtr(pOL->GetObjCount()-1); 325 pOL0=pOL; 326 } 327 sal_uIntPtr nNowPos=pObj->GetOrdNumDirect(); 328 SdrObject* pMaxObj=GetMaxToTopObj(pObj); 329 if (pMaxObj!=NULL) 330 { 331 sal_uIntPtr nMaxOrd=pMaxObj->GetOrdNum(); // geht leider nicht anders 332 if (nMaxOrd>0) 333 nMaxOrd--; 334 if (nNewPos>nMaxOrd) 335 nNewPos=nMaxOrd; // nicht ueberholen. 336 if (nNewPos<nNowPos) 337 nNewPos=nNowPos; // aber dabei auch nicht in die falsche Richtung schieben 338 } 339 if (pRefObj!=NULL) 340 { 341 if (pRefObj->GetObjList()==pObj->GetObjList()) 342 { 343 sal_uIntPtr nMaxOrd=pRefObj->GetOrdNum(); // geht leider nicht anders 344 if (nNewPos>nMaxOrd) 345 nNewPos=nMaxOrd; // nicht ueberholen. 346 if (nNewPos<nNowPos) 347 nNewPos=nNowPos; // aber dabei auch nicht in die falsche Richtung schieben 348 } 349 else 350 { 351 nNewPos=nNowPos; // andere PageView, also nicht veraendern 352 } 353 } 354 if (nNowPos!=nNewPos) 355 { 356 bChg=sal_True; 357 pOL->SetObjectOrdNum(nNowPos,nNewPos); 358 if( bUndo ) 359 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoObjectOrdNum(*pObj,nNowPos,nNewPos)); 360 ObjOrderChanged(pObj,nNowPos,nNewPos); 361 } 362 nNewPos--; 363 } // if (pObj!=pRefObj) 364 } // for-Schleife ueber alle Markierten Objekte 365 366 if( bUndo ) 367 EndUndo(); 368 369 if(bChg) 370 MarkListHasChanged(); 371 } 372 } 373 374 void SdrEditView::PutMarkedToBtm() 375 { 376 PutMarkedBehindObj(NULL); 377 } 378 379 void SdrEditView::PutMarkedBehindObj(const SdrObject* pRefObj) 380 { 381 sal_uIntPtr nAnz=GetMarkedObjectCount(); 382 if (nAnz!=0) 383 { 384 const bool bUndo = IsUndoEnabled(); 385 386 if( bUndo ) 387 BegUndo(ImpGetResStr(STR_EditPutToBtm),GetDescriptionOfMarkedObjects(),SDRREPFUNC_OBJ_PUTTOBTM); 388 389 SortMarkedObjects(); 390 if (pRefObj!=NULL) 391 { 392 // Damit "Hinter das Objekt" auch funktioniert wenn die 393 // markierten Objekte bereits hinter dem Objekt stehen 394 sal_uIntPtr nRefMark=TryToFindMarkedObject(pRefObj); 395 SdrMark aRefMark; 396 if (nRefMark!=CONTAINER_ENTRY_NOTFOUND) 397 { 398 aRefMark=*GetSdrMarkByIndex(nRefMark); 399 GetMarkedObjectListWriteAccess().DeleteMark(nRefMark); 400 } 401 PutMarkedToTop(); 402 if (nRefMark!=CONTAINER_ENTRY_NOTFOUND) 403 { 404 GetMarkedObjectListWriteAccess().InsertEntry(aRefMark); 405 SortMarkedObjects(); 406 } 407 } 408 sal_uIntPtr nm; 409 for (nm=0; nm<nAnz; nm++) { // Ordnums muessen alle stimmen! 410 GetMarkedObjectByIndex(nm)->GetOrdNum(); 411 } 412 sal_Bool bChg=sal_False; 413 SdrObjList* pOL0=NULL; 414 sal_uIntPtr nNewPos=0; 415 for (nm=0; nm<nAnz; nm++) { 416 SdrMark* pM=GetSdrMarkByIndex(nm); 417 SdrObject* pObj=pM->GetMarkedSdrObj(); 418 if (pObj!=pRefObj) { 419 SdrObjList* pOL=pObj->GetObjList(); 420 if (pOL!=pOL0) { 421 nNewPos=0; 422 pOL0=pOL; 423 } 424 sal_uIntPtr nNowPos=pObj->GetOrdNumDirect(); 425 SdrObject* pMinObj=GetMaxToBtmObj(pObj); 426 if (pMinObj!=NULL) { 427 sal_uIntPtr nMinOrd=pMinObj->GetOrdNum()+1; // geht leider nicht anders 428 if (nNewPos<nMinOrd) nNewPos=nMinOrd; // nicht ueberholen. 429 if (nNewPos>nNowPos) nNewPos=nNowPos; // aber dabei auch nicht in die falsche Richtung schieben 430 } 431 if (pRefObj!=NULL) { 432 if (pRefObj->GetObjList()==pObj->GetObjList()) { 433 sal_uIntPtr nMinOrd=pRefObj->GetOrdNum(); // geht leider nicht anders 434 if (nNewPos<nMinOrd) nNewPos=nMinOrd; // nicht ueberholen. 435 if (nNewPos>nNowPos) nNewPos=nNowPos; // aber dabei auch nicht in die falsche Richtung schieben 436 } else { 437 nNewPos=nNowPos; // andere PageView, also nicht veraendern 438 } 439 } 440 if (nNowPos!=nNewPos) { 441 bChg=sal_True; 442 pOL->SetObjectOrdNum(nNowPos,nNewPos); 443 if( bUndo ) 444 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoObjectOrdNum(*pObj,nNowPos,nNewPos)); 445 ObjOrderChanged(pObj,nNowPos,nNewPos); 446 } 447 nNewPos++; 448 } // if (pObj!=pRefObj) 449 } // for-Schleife ueber alle markierten Objekte 450 451 if(bUndo) 452 EndUndo(); 453 454 if(bChg) 455 MarkListHasChanged(); 456 } 457 } 458 459 void SdrEditView::ReverseOrderOfMarked() 460 { 461 SortMarkedObjects(); 462 sal_uIntPtr nMarkAnz=GetMarkedObjectCount(); 463 if (nMarkAnz>0) 464 { 465 //sal_Bool bNeedBundle=sal_False; 466 sal_Bool bChg=sal_False; 467 468 bool bUndo = IsUndoEnabled(); 469 if( bUndo ) 470 BegUndo(ImpGetResStr(STR_EditRevOrder),GetDescriptionOfMarkedObjects(),SDRREPFUNC_OBJ_REVORDER); 471 472 sal_uIntPtr a=0; 473 do { 474 // Markierung ueber mehrere PageViews berueksichtigen 475 sal_uIntPtr b=a+1; 476 while (b<nMarkAnz && GetSdrPageViewOfMarkedByIndex(b) == GetSdrPageViewOfMarkedByIndex(a)) b++; 477 b--; 478 SdrObjList* pOL=GetSdrPageViewOfMarkedByIndex(a)->GetObjList(); 479 sal_uIntPtr c=b; 480 if (a<c) { // Sicherstellen, dass die OrdNums nicht Dirty sind 481 GetMarkedObjectByIndex(a)->GetOrdNum(); 482 } 483 while (a<c) { 484 SdrObject* pObj1=GetMarkedObjectByIndex(a); 485 SdrObject* pObj2=GetMarkedObjectByIndex(c); 486 sal_uIntPtr nOrd1=pObj1->GetOrdNumDirect(); 487 sal_uIntPtr nOrd2=pObj2->GetOrdNumDirect(); 488 if( bUndo ) 489 { 490 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoObjectOrdNum(*pObj1,nOrd1,nOrd2)); 491 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoObjectOrdNum(*pObj2,nOrd2-1,nOrd1)); 492 } 493 pOL->SetObjectOrdNum(nOrd1,nOrd2); 494 // Obj 2 ist um eine Position nach vorn gerutscht, deshalb nun nOrd2-1 495 pOL->SetObjectOrdNum(nOrd2-1,nOrd1); 496 // Verwendung von Replace statt SetOrdNum wg. Performance (Neuberechnung der Ordnums) 497 a++; c--; 498 bChg=sal_True; 499 } 500 a=b+1; 501 } while (a<nMarkAnz); 502 503 if(bUndo) 504 EndUndo(); 505 506 if(bChg) 507 MarkListHasChanged(); 508 } 509 } 510 511 void SdrEditView::ImpCheckToTopBtmPossible() 512 { 513 sal_uIntPtr nAnz=GetMarkedObjectCount(); 514 if (nAnz==0) 515 return; 516 if (nAnz==1) 517 { // Sonderbehandlung fuer Einzelmarkierung 518 SdrObject* pObj=GetMarkedObjectByIndex(0); 519 SdrObjList* pOL=pObj->GetObjList(); 520 sal_uIntPtr nMax=pOL->GetObjCount(); 521 sal_uIntPtr nMin=0; 522 sal_uIntPtr nObjNum=pObj->GetOrdNum(); 523 SdrObject* pRestrict=GetMaxToTopObj(pObj); 524 if (pRestrict!=NULL) { 525 sal_uIntPtr nRestrict=pRestrict->GetOrdNum(); 526 if (nRestrict<nMax) nMax=nRestrict; 527 } 528 pRestrict=GetMaxToBtmObj(pObj); 529 if (pRestrict!=NULL) { 530 sal_uIntPtr nRestrict=pRestrict->GetOrdNum(); 531 if (nRestrict>nMin) nMin=nRestrict; 532 } 533 bToTopPossible=nObjNum<sal_uIntPtr(nMax-1); 534 bToBtmPossible=nObjNum>nMin; 535 } else { // Mehrfachselektion 536 sal_uIntPtr nm=0; 537 SdrObjList* pOL0=NULL; 538 long nPos0=-1; 539 while (!bToBtmPossible && nm<nAnz) { // 'nach hinten' checken 540 SdrObject* pObj=GetMarkedObjectByIndex(nm); 541 SdrObjList* pOL=pObj->GetObjList(); 542 if (pOL!=pOL0) { 543 nPos0=-1; 544 pOL0=pOL; 545 } 546 sal_uIntPtr nPos=pObj->GetOrdNum(); 547 bToBtmPossible=nPos>sal_uIntPtr(nPos0+1); 548 nPos0=long(nPos); 549 nm++; 550 } 551 nm=nAnz; 552 pOL0=NULL; 553 nPos0=0x7FFFFFFF; 554 while (!bToTopPossible && nm>0) { // 'nach vorn' checken 555 nm--; 556 SdrObject* pObj=GetMarkedObjectByIndex(nm); 557 SdrObjList* pOL=pObj->GetObjList(); 558 if (pOL!=pOL0) { 559 nPos0=pOL->GetObjCount(); 560 pOL0=pOL; 561 } 562 sal_uIntPtr nPos=pObj->GetOrdNum(); 563 bToTopPossible=nPos+1<sal_uIntPtr(nPos0); 564 nPos0=nPos; 565 } 566 } 567 } 568 569 //////////////////////////////////////////////////////////////////////////////////////////////////// 570 // 571 // @@@@ @@@@ @@ @@ @@@@@ @@ @@ @@ @@@@@ 572 // @@ @@ @@ @@ @@@ @@@ @@ @@ @@ @@@ @@ @@ 573 // @@ @@ @@ @@@@@@@ @@ @@ @@ @@@@@@ @@ 574 // @@ @@ @@ @@@@@@@ @@@@@ @@ @@@@@@ @@@@ 575 // @@ @@ @@ @@ @ @@ @@ @@ @@ @@ @@@ @@ 576 // @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ 577 // @@@@ @@@@ @@ @@ @@@@@ @@ @@ @@ @@@@@ 578 // 579 //////////////////////////////////////////////////////////////////////////////////////////////////// 580 581 void SdrEditView::ImpCopyAttributes(const SdrObject* pSource, SdrObject* pDest) const 582 { 583 if (pSource!=NULL) { 584 SdrObjList* pOL=pSource->GetSubList(); 585 if (pOL!=NULL && !pSource->Is3DObj()) { // erstes Nichtgruppenobjekt aus der Gruppe holen 586 SdrObjListIter aIter(*pOL,IM_DEEPNOGROUPS); 587 pSource=aIter.Next(); 588 } 589 } 590 591 if(pSource && pDest) 592 { 593 SfxItemSet aSet(pMod->GetItemPool(), 594 SDRATTR_START, SDRATTR_NOTPERSIST_FIRST-1, 595 SDRATTR_NOTPERSIST_LAST+1, SDRATTR_END, 596 EE_ITEMS_START, EE_ITEMS_END, 597 0, 0); // #52757#, #52762# 598 599 aSet.Put(pSource->GetMergedItemSet()); 600 601 pDest->ClearMergedItem(); 602 pDest->SetMergedItemSet(aSet); 603 604 pDest->NbcSetLayer(pSource->GetLayer()); 605 pDest->NbcSetStyleSheet(pSource->GetStyleSheet(), sal_True); 606 } 607 } 608 609 sal_Bool SdrEditView::ImpCanConvertForCombine1(const SdrObject* pObj) const 610 { 611 // #69711 : new condition IsLine() to be able to combine simple Lines 612 sal_Bool bIsLine(sal_False); 613 614 const SdrPathObj* pPath = PTR_CAST(SdrPathObj,pObj); 615 616 if(pPath) 617 { 618 bIsLine = pPath->IsLine(); 619 } 620 621 SdrObjTransformInfoRec aInfo; 622 pObj->TakeObjInfo(aInfo); 623 624 return (aInfo.bCanConvToPath || aInfo.bCanConvToPoly || bIsLine); 625 } 626 627 sal_Bool SdrEditView::ImpCanConvertForCombine(const SdrObject* pObj) const 628 { 629 SdrObjList* pOL = pObj->GetSubList(); 630 631 if(pOL && !pObj->Is3DObj()) 632 { 633 SdrObjListIter aIter(*pOL, IM_DEEPNOGROUPS); 634 635 while(aIter.IsMore()) 636 { 637 SdrObject* pObj1 = aIter.Next(); 638 639 // Es muessen alle Member einer Gruppe konvertierbar sein 640 if(!ImpCanConvertForCombine1(pObj1)) 641 { 642 return sal_False; 643 } 644 } 645 } 646 else 647 { 648 if(!ImpCanConvertForCombine1(pObj)) 649 { 650 return sal_False; 651 } 652 } 653 654 return sal_True; 655 } 656 657 basegfx::B2DPolyPolygon SdrEditView::ImpGetPolyPolygon1(const SdrObject* pObj, sal_Bool bCombine) const 658 { 659 basegfx::B2DPolyPolygon aRetval; 660 SdrPathObj* pPath = PTR_CAST(SdrPathObj, pObj); 661 662 if(bCombine && pPath && !pObj->GetOutlinerParaObject()) 663 { 664 aRetval = pPath->GetPathPoly(); 665 } 666 else 667 { 668 SdrObject* pConvObj = pObj->ConvertToPolyObj(bCombine, sal_False); 669 670 if(pConvObj) 671 { 672 SdrObjList* pOL = pConvObj->GetSubList(); 673 674 if(pOL) 675 { 676 SdrObjListIter aIter(*pOL, IM_DEEPNOGROUPS); 677 678 while(aIter.IsMore()) 679 { 680 SdrObject* pObj1 = aIter.Next(); 681 pPath = PTR_CAST(SdrPathObj, pObj1); 682 683 if(pPath) 684 { 685 aRetval.append(pPath->GetPathPoly()); 686 } 687 } 688 } 689 else 690 { 691 pPath = PTR_CAST(SdrPathObj, pConvObj); 692 693 if(pPath) 694 { 695 aRetval = pPath->GetPathPoly(); 696 } 697 } 698 699 SdrObject::Free( pConvObj ); 700 } 701 } 702 703 return aRetval; 704 } 705 706 basegfx::B2DPolyPolygon SdrEditView::ImpGetPolyPolygon(const SdrObject* pObj, sal_Bool bCombine) const 707 { 708 SdrObjList* pOL = pObj->GetSubList(); 709 710 if(pOL && !pObj->Is3DObj()) 711 { 712 basegfx::B2DPolyPolygon aRetval; 713 SdrObjListIter aIter(*pOL, IM_DEEPNOGROUPS); 714 715 while(aIter.IsMore()) 716 { 717 SdrObject* pObj1 = aIter.Next(); 718 aRetval.append(ImpGetPolyPolygon1(pObj1, bCombine)); 719 } 720 721 return aRetval; 722 } 723 else 724 { 725 return ImpGetPolyPolygon1(pObj, bCombine); 726 } 727 } 728 729 basegfx::B2DPolygon SdrEditView::ImpCombineToSinglePolygon(const basegfx::B2DPolyPolygon& rPolyPolygon) const 730 { 731 const sal_uInt32 nPolyCount(rPolyPolygon.count()); 732 733 if(0L == nPolyCount) 734 { 735 return basegfx::B2DPolygon(); 736 } 737 else if(1L == nPolyCount) 738 { 739 return rPolyPolygon.getB2DPolygon(0L); 740 } 741 else 742 { 743 basegfx::B2DPolygon aRetval(rPolyPolygon.getB2DPolygon(0L)); 744 745 for(sal_uInt32 a(1L); a < nPolyCount; a++) 746 { 747 basegfx::B2DPolygon aCandidate(rPolyPolygon.getB2DPolygon(a)); 748 749 if(aRetval.count()) 750 { 751 if(aCandidate.count()) 752 { 753 const basegfx::B2DPoint aCA(aCandidate.getB2DPoint(0L)); 754 const basegfx::B2DPoint aCB(aCandidate.getB2DPoint(aCandidate.count() - 1L)); 755 const basegfx::B2DPoint aRA(aRetval.getB2DPoint(0L)); 756 const basegfx::B2DPoint aRB(aRetval.getB2DPoint(aRetval.count() - 1L)); 757 758 const double fRACA(basegfx::B2DVector(aCA - aRA).getLength()); 759 const double fRACB(basegfx::B2DVector(aCB - aRA).getLength()); 760 const double fRBCA(basegfx::B2DVector(aCA - aRB).getLength()); 761 const double fRBCB(basegfx::B2DVector(aCB - aRB).getLength()); 762 763 const double fSmallestRA(fRACA < fRACB ? fRACA : fRACB); 764 const double fSmallestRB(fRBCA < fRBCB ? fRBCA : fRBCB); 765 766 if(fSmallestRA < fSmallestRB) 767 { 768 // flip result 769 aRetval.flip(); 770 } 771 772 const double fSmallestCA(fRACA < fRBCA ? fRACA : fRBCA); 773 const double fSmallestCB(fRACB < fRBCB ? fRACB : fRBCB); 774 775 if(fSmallestCB < fSmallestCA) 776 { 777 // flip candidate 778 aCandidate.flip(); 779 } 780 781 // append candidate to retval 782 aRetval.append(aCandidate); 783 } 784 } 785 else 786 { 787 aRetval = aCandidate; 788 } 789 } 790 791 return aRetval; 792 } 793 } 794 795 // for distribution dialog function 796 struct ImpDistributeEntry 797 { 798 SdrObject* mpObj; 799 sal_Int32 mnPos; 800 sal_Int32 mnLength; 801 }; 802 803 DECLARE_LIST(ImpDistributeEntryList, ImpDistributeEntry*) 804 805 void SdrEditView::DistributeMarkedObjects() 806 { 807 sal_uInt32 nMark(GetMarkedObjectCount()); 808 809 if(nMark > 2) 810 { 811 SfxItemSet aNewAttr(pMod->GetItemPool()); 812 //CHINA001 SvxDistributeDialog* pDlg = new SvxDistributeDialog(NULL, aNewAttr); 813 SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create(); 814 if(pFact) 815 { 816 AbstractSvxDistributeDialog *pDlg = pFact->CreateSvxDistributeDialog(NULL, aNewAttr); 817 DBG_ASSERT(pDlg, "Dialogdiet fail!");//CHINA001 818 819 sal_uInt16 nResult = pDlg->Execute(); 820 821 if(nResult == RET_OK) 822 { 823 SvxDistributeHorizontal eHor = pDlg->GetDistributeHor(); 824 SvxDistributeVertical eVer = pDlg->GetDistributeVer(); 825 ImpDistributeEntryList aEntryList; 826 sal_uInt32 a, nInsPos, nFullLength; 827 828 const bool bUndo = IsUndoEnabled(); 829 if( bUndo ) 830 BegUndo(); 831 832 if(eHor != SvxDistributeHorizontalNone) 833 { 834 // build sorted entry list 835 nFullLength = 0L; 836 837 for(a=0;a<nMark;a++) 838 { 839 SdrMark* pMark = GetSdrMarkByIndex(a); 840 ImpDistributeEntry* pNew = new ImpDistributeEntry; 841 842 pNew->mpObj = pMark->GetMarkedSdrObj(); 843 nInsPos = 0; 844 845 switch(eHor) 846 { 847 case SvxDistributeHorizontalLeft: 848 { 849 pNew->mnPos = pNew->mpObj->GetSnapRect().Left(); 850 break; 851 } 852 case SvxDistributeHorizontalCenter: 853 { 854 pNew->mnPos = (pNew->mpObj->GetSnapRect().Right() + pNew->mpObj->GetSnapRect().Left()) / 2; 855 break; 856 } 857 case SvxDistributeHorizontalDistance: 858 { 859 pNew->mnLength = pNew->mpObj->GetSnapRect().GetWidth() + 1; 860 nFullLength += pNew->mnLength; 861 pNew->mnPos = (pNew->mpObj->GetSnapRect().Right() + pNew->mpObj->GetSnapRect().Left()) / 2; 862 break; 863 } 864 case SvxDistributeHorizontalRight: 865 { 866 pNew->mnPos = pNew->mpObj->GetSnapRect().Right(); 867 break; 868 } 869 default: break; 870 } 871 872 while(nInsPos < aEntryList.Count() && aEntryList.GetObject(nInsPos)->mnPos < pNew->mnPos) 873 nInsPos++; 874 875 aEntryList.Insert(pNew, nInsPos); 876 } 877 878 if(eHor == SvxDistributeHorizontalDistance) 879 { 880 // calc room in-between 881 sal_Int32 nWidth = GetAllMarkedBoundRect().GetWidth() + 1; 882 double fStepWidth = ((double)nWidth - (double)nFullLength) / (double)(aEntryList.Count() - 1); 883 double fStepStart = (double)aEntryList.GetObject(0)->mnPos; 884 fStepStart += fStepWidth + (double)((aEntryList.GetObject(0)->mnLength + aEntryList.GetObject(1)->mnLength) / 2); 885 886 // move entries 1..n-1 887 for(a=1;a<aEntryList.Count()-1;a++) 888 { 889 ImpDistributeEntry* pCurr = aEntryList.GetObject(a); 890 ImpDistributeEntry* pNext = aEntryList.GetObject(a+1); 891 sal_Int32 nDelta = (sal_Int32)(fStepStart + 0.5) - pCurr->mnPos; 892 if( bUndo ) 893 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoGeoObject(*pCurr->mpObj)); 894 pCurr->mpObj->Move(Size(nDelta, 0)); 895 fStepStart += fStepWidth + (double)((pCurr->mnLength + pNext->mnLength) / 2); 896 } 897 } 898 else 899 { 900 // calc distances 901 sal_Int32 nWidth = aEntryList.GetObject(aEntryList.Count() - 1)->mnPos - aEntryList.GetObject(0)->mnPos; 902 double fStepWidth = (double)nWidth / (double)(aEntryList.Count() - 1); 903 double fStepStart = (double)aEntryList.GetObject(0)->mnPos; 904 fStepStart += fStepWidth; 905 906 // move entries 1..n-1 907 for(a=1;a<aEntryList.Count()-1;a++) 908 { 909 ImpDistributeEntry* pCurr = aEntryList.GetObject(a); 910 sal_Int32 nDelta = (sal_Int32)(fStepStart + 0.5) - pCurr->mnPos; 911 if( bUndo ) 912 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoGeoObject(*pCurr->mpObj)); 913 pCurr->mpObj->Move(Size(nDelta, 0)); 914 fStepStart += fStepWidth; 915 } 916 } 917 918 // clear list 919 while(aEntryList.Count()) 920 delete aEntryList.Remove((sal_uIntPtr)0L); 921 } 922 923 if(eVer != SvxDistributeVerticalNone) 924 { 925 // build sorted entry list 926 nFullLength = 0L; 927 928 for(a=0;a<nMark;a++) 929 { 930 SdrMark* pMark = GetSdrMarkByIndex(a); 931 ImpDistributeEntry* pNew = new ImpDistributeEntry; 932 933 pNew->mpObj = pMark->GetMarkedSdrObj(); 934 nInsPos = 0; 935 936 switch(eVer) 937 { 938 case SvxDistributeVerticalTop: 939 { 940 pNew->mnPos = pNew->mpObj->GetSnapRect().Top(); 941 break; 942 } 943 case SvxDistributeVerticalCenter: 944 { 945 pNew->mnPos = (pNew->mpObj->GetSnapRect().Bottom() + pNew->mpObj->GetSnapRect().Top()) / 2; 946 break; 947 } 948 case SvxDistributeVerticalDistance: 949 { 950 pNew->mnLength = pNew->mpObj->GetSnapRect().GetHeight() + 1; 951 nFullLength += pNew->mnLength; 952 pNew->mnPos = (pNew->mpObj->GetSnapRect().Bottom() + pNew->mpObj->GetSnapRect().Top()) / 2; 953 break; 954 } 955 case SvxDistributeVerticalBottom: 956 { 957 pNew->mnPos = pNew->mpObj->GetSnapRect().Bottom(); 958 break; 959 } 960 default: break; 961 } 962 963 while(nInsPos < aEntryList.Count() && aEntryList.GetObject(nInsPos)->mnPos < pNew->mnPos) 964 nInsPos++; 965 966 aEntryList.Insert(pNew, nInsPos); 967 } 968 969 if(eVer == SvxDistributeVerticalDistance) 970 { 971 // calc room in-between 972 sal_Int32 nHeight = GetAllMarkedBoundRect().GetHeight() + 1; 973 double fStepWidth = ((double)nHeight - (double)nFullLength) / (double)(aEntryList.Count() - 1); 974 double fStepStart = (double)aEntryList.GetObject(0)->mnPos; 975 fStepStart += fStepWidth + (double)((aEntryList.GetObject(0)->mnLength + aEntryList.GetObject(1)->mnLength) / 2); 976 977 // move entries 1..n-1 978 for(a=1;a<aEntryList.Count()-1;a++) 979 { 980 ImpDistributeEntry* pCurr = aEntryList.GetObject(a); 981 ImpDistributeEntry* pNext = aEntryList.GetObject(a+1); 982 sal_Int32 nDelta = (sal_Int32)(fStepStart + 0.5) - pCurr->mnPos; 983 if( bUndo ) 984 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoGeoObject(*pCurr->mpObj)); 985 pCurr->mpObj->Move(Size(0, nDelta)); 986 fStepStart += fStepWidth + (double)((pCurr->mnLength + pNext->mnLength) / 2); 987 } 988 } 989 else 990 { 991 // calc distances 992 sal_Int32 nHeight = aEntryList.GetObject(aEntryList.Count() - 1)->mnPos - aEntryList.GetObject(0)->mnPos; 993 double fStepWidth = (double)nHeight / (double)(aEntryList.Count() - 1); 994 double fStepStart = (double)aEntryList.GetObject(0)->mnPos; 995 fStepStart += fStepWidth; 996 997 // move entries 1..n-1 998 for(a=1;a<aEntryList.Count()-1;a++) 999 { 1000 ImpDistributeEntry* pCurr = aEntryList.GetObject(a); 1001 sal_Int32 nDelta = (sal_Int32)(fStepStart + 0.5) - pCurr->mnPos; 1002 if( bUndo ) 1003 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoGeoObject(*pCurr->mpObj)); 1004 pCurr->mpObj->Move(Size(0, nDelta)); 1005 fStepStart += fStepWidth; 1006 } 1007 } 1008 1009 // clear list 1010 while(aEntryList.Count()) 1011 delete aEntryList.Remove((sal_uIntPtr)0L); 1012 } 1013 1014 // UNDO-Comment and end of UNDO 1015 SetUndoComment(ImpGetResStr(STR_DistributeMarkedObjects)); 1016 1017 if( bUndo ) 1018 EndUndo(); 1019 } 1020 1021 delete(pDlg); 1022 } 1023 } 1024 } 1025 1026 void SdrEditView::MergeMarkedObjects(SdrMergeMode eMode) 1027 { 1028 // #i73441# check content 1029 if(AreObjectsMarked()) 1030 { 1031 SdrMarkList aRemove; 1032 SortMarkedObjects(); 1033 1034 const bool bUndo = IsUndoEnabled(); 1035 1036 if( bUndo ) 1037 BegUndo(); 1038 1039 sal_uInt32 nInsPos=0xFFFFFFFF; 1040 const SdrObject* pAttrObj = NULL; 1041 basegfx::B2DPolyPolygon aMergePolyPolygonA; 1042 basegfx::B2DPolyPolygon aMergePolyPolygonB; 1043 1044 SdrObjList* pInsOL = NULL; 1045 SdrPageView* pInsPV = NULL; 1046 sal_Bool bFirstObjectComplete(sal_False); 1047 1048 // make sure selected objects are contour objects 1049 // since now basegfx::tools::adaptiveSubdivide() is used, it is no longer 1050 // necessary to use ConvertMarkedToPolyObj which will subdivide curves using the old 1051 // mechanisms. In a next step the polygon clipper will even be able to clip curves... 1052 // ConvertMarkedToPolyObj(sal_True); 1053 ConvertMarkedToPathObj(sal_True); 1054 OSL_ENSURE(AreObjectsMarked(), "no more objects selected after preparations (!)"); 1055 1056 for(sal_uInt32 a=0;a<GetMarkedObjectCount();a++) 1057 { 1058 SdrMark* pM = GetSdrMarkByIndex(a); 1059 SdrObject* pObj = pM->GetMarkedSdrObj(); 1060 1061 if(ImpCanConvertForCombine(pObj)) 1062 { 1063 if(!pAttrObj) 1064 pAttrObj = pObj; 1065 1066 nInsPos = pObj->GetOrdNum() + 1; 1067 pInsPV = pM->GetPageView(); 1068 pInsOL = pObj->GetObjList(); 1069 1070 // #i76891# use single iter from SJ here whcih works on SdrObjects and takes 1071 // groups into account by itself 1072 SdrObjListIter aIter(*pObj, IM_DEEPWITHGROUPS); 1073 1074 while(aIter.IsMore()) 1075 { 1076 SdrObject* pCandidate = aIter.Next(); 1077 SdrPathObj* pPathObj = PTR_CAST(SdrPathObj, pCandidate); 1078 if(pPathObj) 1079 { 1080 basegfx::B2DPolyPolygon aTmpPoly(pPathObj->GetPathPoly()); 1081 1082 // #i76891# unfortunately ConvertMarkedToPathObj has converted all 1083 // involved polygon data to curve segments, even if not necessary. 1084 // It is better to try to reduce to more simple polygons. 1085 aTmpPoly = basegfx::tools::simplifyCurveSegments(aTmpPoly); 1086 1087 // for each part polygon as preparation, remove self-intersections 1088 // correct orientations and get rid of evtl. neutral polygons. 1089 aTmpPoly = basegfx::tools::prepareForPolygonOperation(aTmpPoly); 1090 1091 if(!bFirstObjectComplete) 1092 { 1093 // #i111987# Also need to collect ORed source shape when more than 1094 // a single polygon is involved 1095 if(aMergePolyPolygonA.count()) 1096 { 1097 aMergePolyPolygonA = basegfx::tools::solvePolygonOperationOr(aMergePolyPolygonA, aTmpPoly); 1098 } 1099 else 1100 { 1101 aMergePolyPolygonA = aTmpPoly; 1102 } 1103 } 1104 else 1105 { 1106 if(aMergePolyPolygonB.count()) 1107 { 1108 // to topologically correctly collect the 2nd polygon 1109 // group it is necessary to OR the parts (each is seen as 1110 // XOR-FillRule polygon and they are drawn over each-other) 1111 aMergePolyPolygonB = basegfx::tools::solvePolygonOperationOr(aMergePolyPolygonB, aTmpPoly); 1112 } 1113 else 1114 { 1115 aMergePolyPolygonB = aTmpPoly; 1116 } 1117 } 1118 } 1119 } 1120 1121 // was there something added to the first poly? 1122 if(!bFirstObjectComplete && aMergePolyPolygonA.count()) 1123 { 1124 bFirstObjectComplete = sal_True; 1125 } 1126 1127 // move object to temporary delete list 1128 aRemove.InsertEntry(SdrMark(pObj, pM->GetPageView())); 1129 } 1130 } 1131 1132 switch(eMode) 1133 { 1134 case SDR_MERGE_MERGE: 1135 { 1136 // merge all contained parts (OR) 1137 static bool bTestXOR(false); 1138 if(bTestXOR) 1139 { 1140 aMergePolyPolygonA = basegfx::tools::solvePolygonOperationXor(aMergePolyPolygonA, aMergePolyPolygonB); 1141 } 1142 else 1143 { 1144 aMergePolyPolygonA = basegfx::tools::solvePolygonOperationOr(aMergePolyPolygonA, aMergePolyPolygonB); 1145 } 1146 break; 1147 } 1148 case SDR_MERGE_SUBSTRACT: 1149 { 1150 // Substract B from A 1151 aMergePolyPolygonA = basegfx::tools::solvePolygonOperationDiff(aMergePolyPolygonA, aMergePolyPolygonB); 1152 break; 1153 } 1154 case SDR_MERGE_INTERSECT: 1155 { 1156 // AND B and A 1157 aMergePolyPolygonA = basegfx::tools::solvePolygonOperationAnd(aMergePolyPolygonA, aMergePolyPolygonB); 1158 break; 1159 } 1160 } 1161 1162 // #i73441# check insert list before taking actions 1163 if(pInsOL) 1164 { 1165 SdrPathObj* pPath = new SdrPathObj(OBJ_PATHFILL, aMergePolyPolygonA); 1166 ImpCopyAttributes(pAttrObj, pPath); 1167 SdrInsertReason aReason(SDRREASON_VIEWCALL, pAttrObj); 1168 pInsOL->InsertObject(pPath, nInsPos, &aReason); 1169 if( bUndo ) 1170 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoNewObject(*pPath)); 1171 MarkObj(pPath, pInsPV, sal_False, sal_True); 1172 } 1173 1174 aRemove.ForceSort(); 1175 switch(eMode) 1176 { 1177 case SDR_MERGE_MERGE: 1178 { 1179 SetUndoComment( 1180 ImpGetResStr(STR_EditMergeMergePoly), 1181 aRemove.GetMarkDescription()); 1182 break; 1183 } 1184 case SDR_MERGE_SUBSTRACT: 1185 { 1186 SetUndoComment( 1187 ImpGetResStr(STR_EditMergeSubstractPoly), 1188 aRemove.GetMarkDescription()); 1189 break; 1190 } 1191 case SDR_MERGE_INTERSECT: 1192 { 1193 SetUndoComment( 1194 ImpGetResStr(STR_EditMergeIntersectPoly), 1195 aRemove.GetMarkDescription()); 1196 break; 1197 } 1198 } 1199 DeleteMarkedList(aRemove); 1200 1201 if( bUndo ) 1202 EndUndo(); 1203 } 1204 } 1205 1206 void SdrEditView::CombineMarkedObjects(sal_Bool bNoPolyPoly) 1207 { 1208 // #105899# Start of Combine-Undo put to front, else ConvertMarkedToPolyObj would 1209 // create a 2nd Undo-action and Undo-Comment. 1210 1211 bool bUndo = IsUndoEnabled(); 1212 1213 // Undo-String will be set later 1214 if( bUndo ) 1215 BegUndo(String(), String(), bNoPolyPoly ? SDRREPFUNC_OBJ_COMBINE_ONEPOLY : SDRREPFUNC_OBJ_COMBINE_POLYPOLY); 1216 1217 // #105899# First, guarantee that all objects are converted to polyobjects, 1218 // especially for SdrGrafObj with bitmap filling this is necessary to not 1219 // loose the bitmap filling. 1220 1221 // #i12392# 1222 // ConvertMarkedToPolyObj was too strong here, it will loose quality and 1223 // information when curve objects are combined. This can be replaced by 1224 // using ConvertMarkedToPathObj without changing the previous fix. 1225 1226 // #i21250# 1227 // Instead of simply passing sal_True as LineToArea, use bNoPolyPoly as info 1228 // if this command is a 'Combine' or a 'Connect' command. On Connect it's sal_True. 1229 // To not concert line segments with a set line width to polygons in that case, 1230 // use this info. Do not convert LineToArea on Connect commands. 1231 // ConvertMarkedToPathObj(!bNoPolyPoly); 1232 1233 // #114310# 1234 // This is used for Combine and Connect. In no case it is necessary to force 1235 // the content to curve, but it is also not good to force to polygons. Thus, 1236 // curve is the less information loosing one. Remember: This place is not 1237 // used for merge. 1238 // LineToArea is never necessary, both commands are able to take over the 1239 // set line style and to display it correctly. Thus, i will use a 1240 // ConvertMarkedToPathObj with a sal_False in any case. Only drawback is that 1241 // simple polygons will be changed to curves, but with no information loss. 1242 ConvertMarkedToPathObj(sal_False /* bLineToArea */); 1243 1244 // continue as before 1245 basegfx::B2DPolyPolygon aPolyPolygon; 1246 SdrObjList* pAktOL = 0L; 1247 SdrMarkList aRemoveMerker; 1248 1249 SortMarkedObjects(); 1250 sal_uInt32 nInsPos(0xFFFFFFFF); 1251 SdrObjList* pInsOL = 0L; 1252 SdrPageView* pInsPV = 0L; 1253 const sal_uInt32 nAnz(GetMarkedObjectCount()); 1254 const SdrObject* pAttrObj = 0L; 1255 1256 for(sal_uInt32 a(nAnz); a > 0L; ) 1257 { 1258 a--; 1259 SdrMark* pM = GetSdrMarkByIndex(a); 1260 SdrObject* pObj = pM->GetMarkedSdrObj(); 1261 SdrObjList* pThisOL = pObj->GetObjList(); 1262 1263 if(pAktOL != pThisOL) 1264 { 1265 pAktOL = pThisOL; 1266 } 1267 1268 if(ImpCanConvertForCombine(pObj)) 1269 { 1270 // Obj merken fuer Attribute kopieren 1271 pAttrObj = pObj; 1272 1273 // unfortunately ConvertMarkedToPathObj has converted all 1274 // involved polygon data to curve segments, even if not necessary. 1275 // It is better to try to reduce to more simple polygons. 1276 basegfx::B2DPolyPolygon aTmpPoly(basegfx::tools::simplifyCurveSegments(ImpGetPolyPolygon(pObj, sal_True))); 1277 aPolyPolygon.insert(0L, aTmpPoly); 1278 1279 if(!pInsOL) 1280 { 1281 nInsPos = pObj->GetOrdNum() + 1L; 1282 pInsPV = pM->GetPageView(); 1283 pInsOL = pObj->GetObjList(); 1284 } 1285 1286 aRemoveMerker.InsertEntry(SdrMark(pObj, pM->GetPageView())); 1287 } 1288 } 1289 1290 if(bNoPolyPoly) 1291 { 1292 basegfx::B2DPolygon aCombinedPolygon(ImpCombineToSinglePolygon(aPolyPolygon)); 1293 aPolyPolygon.clear(); 1294 aPolyPolygon.append(aCombinedPolygon); 1295 } 1296 1297 const sal_uInt32 nPolyCount(aPolyPolygon.count()); 1298 1299 if(nPolyCount) 1300 { 1301 SdrObjKind eKind = OBJ_PATHFILL; 1302 1303 if(nPolyCount > 1L) 1304 { 1305 aPolyPolygon.setClosed(true); 1306 } 1307 else 1308 { 1309 // auf Polyline Checken 1310 const basegfx::B2DPolygon aPolygon(aPolyPolygon.getB2DPolygon(0L)); 1311 const sal_uInt32 nPointCount(aPolygon.count()); 1312 1313 if(nPointCount <= 2L) 1314 { 1315 eKind = OBJ_PATHLINE; 1316 } 1317 else 1318 { 1319 if(!aPolygon.isClosed()) 1320 { 1321 const basegfx::B2DPoint aPointA(aPolygon.getB2DPoint(0L)); 1322 const basegfx::B2DPoint aPointB(aPolygon.getB2DPoint(nPointCount - 1L)); 1323 const double fDistance(basegfx::B2DVector(aPointB - aPointA).getLength()); 1324 const double fJoinTolerance(10.0); 1325 1326 if(fDistance < fJoinTolerance) 1327 { 1328 aPolyPolygon.setClosed(true); 1329 } 1330 else 1331 { 1332 eKind = OBJ_PATHLINE; 1333 } 1334 } 1335 } 1336 } 1337 1338 SdrPathObj* pPath = new SdrPathObj(eKind,aPolyPolygon); 1339 1340 // Attribute des untersten Objekts 1341 ImpCopyAttributes(pAttrObj, pPath); 1342 1343 // #100408# If LineStyle of pAttrObj is XLINE_NONE force to XLINE_SOLID to make visible. 1344 const XLineStyle eLineStyle = ((const XLineStyleItem&)pAttrObj->GetMergedItem(XATTR_LINESTYLE)).GetValue(); 1345 const XFillStyle eFillStyle = ((const XFillStyleItem&)pAttrObj->GetMergedItem(XATTR_FILLSTYLE)).GetValue(); 1346 1347 // #110635# 1348 // Take fill style/closed state of pAttrObj in account when deciding to change the line style 1349 sal_Bool bIsClosedPathObj(pAttrObj->ISA(SdrPathObj) && ((SdrPathObj*)pAttrObj)->IsClosed()); 1350 1351 if(XLINE_NONE == eLineStyle && (XFILL_NONE == eFillStyle || !bIsClosedPathObj)) 1352 { 1353 pPath->SetMergedItem(XLineStyleItem(XLINE_SOLID)); 1354 } 1355 1356 SdrInsertReason aReason(SDRREASON_VIEWCALL,pAttrObj); 1357 pInsOL->InsertObject(pPath,nInsPos,&aReason); 1358 if( bUndo ) 1359 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoNewObject(*pPath)); 1360 1361 // #111111# 1362 // Here was a severe error: Without UnmarkAllObj, the new object was marked 1363 // additionally to the two ones which are deleted below. As long as those are 1364 // in the UNDO there is no problem, but as soon as they get deleted, the 1365 // MarkList will contain deleted objects -> GPF. 1366 UnmarkAllObj(pInsPV); 1367 MarkObj(pPath, pInsPV, sal_False, sal_True); 1368 } 1369 1370 // UndoComment aus den tatsaechlich verwendeten Objekten zusammenbauen 1371 aRemoveMerker.ForceSort(); // wichtig fuer Remove (s.u.) 1372 if( bUndo ) 1373 SetUndoComment(ImpGetResStr(bNoPolyPoly?STR_EditCombine_OnePoly:STR_EditCombine_PolyPoly),aRemoveMerker.GetMarkDescription()); 1374 1375 // die tatsaechlich verwendeten Objekten aus der Liste entfernen 1376 DeleteMarkedList(aRemoveMerker); 1377 if( bUndo ) 1378 EndUndo(); 1379 } 1380 1381 //////////////////////////////////////////////////////////////////////////////////////////////////// 1382 // 1383 // @@@@@ @@ @@@@ @@ @@ @@@@ @@ @@ @@@@@@ @@ @@@@@ 1384 // @@ @@ @@ @@ @@ @@@ @@@ @@ @@ @@@ @@ @@ @@ @@ 1385 // @@ @@ @@ @@ @@@@@@@ @@ @@ @@@@@@ @@ @@ @@ 1386 // @@ @@ @@ @@@@ @@@@@@@ @@@@@@ @@@@@@ @@ @@ @@@@ 1387 // @@ @@ @@ @@ @@ @ @@ @@ @@ @@ @@@ @@ @@ @@ 1388 // @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ 1389 // @@@@@ @@ @@@@ @@ @@ @@ @@ @@ @@ @@ @@@@@ @@@@@ 1390 // 1391 //////////////////////////////////////////////////////////////////////////////////////////////////// 1392 1393 sal_Bool SdrEditView::ImpCanDismantle(const basegfx::B2DPolyPolygon& rPpolyPolygon, sal_Bool bMakeLines) const 1394 { 1395 sal_Bool bCan(sal_False); 1396 const sal_uInt32 nPolygonCount(rPpolyPolygon.count()); 1397 1398 if(nPolygonCount >= 2L) 1399 { 1400 // #i69172# dismantle makes sense with 2 or more polygons in a polyPolygon 1401 bCan = sal_True; 1402 } 1403 else if(bMakeLines && 1L == nPolygonCount) 1404 { 1405 // #i69172# ..or with at least 2 edges (curves or lines) 1406 const basegfx::B2DPolygon aPolygon(rPpolyPolygon.getB2DPolygon(0L)); 1407 const sal_uInt32 nPointCount(aPolygon.count()); 1408 1409 if(nPointCount > 2L) 1410 { 1411 bCan = sal_True; 1412 } 1413 } 1414 1415 return bCan; 1416 } 1417 1418 sal_Bool SdrEditView::ImpCanDismantle(const SdrObject* pObj, sal_Bool bMakeLines) const 1419 { 1420 sal_Bool bOtherObjs(sal_False); // sal_True=andere Objekte ausser PathObj's vorhanden 1421 sal_Bool bMin1PolyPoly(sal_False); // sal_True=mind. 1 PolyPolygon mit mehr als ein Polygon vorhanden 1422 SdrObjList* pOL = pObj->GetSubList(); 1423 1424 if(pOL) 1425 { 1426 // Aha, Gruppenobjekt. Also alle Member ansehen. 1427 // Alle muessen PathObjs sein ! 1428 SdrObjListIter aIter(*pOL, IM_DEEPNOGROUPS); 1429 1430 while(aIter.IsMore() && !bOtherObjs) 1431 { 1432 const SdrObject* pObj1 = aIter.Next(); 1433 const SdrPathObj* pPath = PTR_CAST(SdrPathObj, pObj1); 1434 1435 if(pPath) 1436 { 1437 if(ImpCanDismantle(pPath->GetPathPoly(), bMakeLines)) 1438 { 1439 bMin1PolyPoly = sal_True; 1440 } 1441 1442 SdrObjTransformInfoRec aInfo; 1443 pObj1->TakeObjInfo(aInfo); 1444 1445 if(!aInfo.bCanConvToPath) 1446 { 1447 // Passiert z.B. im Falle Fontwork (Joe, 28-11-95) 1448 bOtherObjs = sal_True; 1449 } 1450 } 1451 else 1452 { 1453 bOtherObjs = sal_True; 1454 } 1455 } 1456 } 1457 else 1458 { 1459 const SdrPathObj* pPath = PTR_CAST(SdrPathObj, pObj); 1460 const SdrObjCustomShape* pCustomShape = PTR_CAST(SdrObjCustomShape, pObj); 1461 1462 // #i37011# 1463 if(pPath) 1464 { 1465 if(ImpCanDismantle(pPath->GetPathPoly(),bMakeLines)) 1466 { 1467 bMin1PolyPoly = sal_True; 1468 } 1469 1470 SdrObjTransformInfoRec aInfo; 1471 pObj->TakeObjInfo(aInfo); 1472 1473 // #69711 : new condition IsLine() to be able to break simple Lines 1474 if(!(aInfo.bCanConvToPath || aInfo.bCanConvToPoly) && !pPath->IsLine()) 1475 { 1476 // Passiert z.B. im Falle Fontwork (Joe, 28-11-95) 1477 bOtherObjs = sal_True; 1478 } 1479 } 1480 else if(pCustomShape) 1481 { 1482 if(bMakeLines) 1483 { 1484 // allow break command 1485 bMin1PolyPoly = sal_True; 1486 } 1487 } 1488 else 1489 { 1490 bOtherObjs = sal_True; 1491 } 1492 } 1493 return bMin1PolyPoly && !bOtherObjs; 1494 } 1495 1496 void SdrEditView::ImpDismantleOneObject(const SdrObject* pObj, SdrObjList& rOL, sal_uIntPtr& rPos, SdrPageView* pPV, sal_Bool bMakeLines) 1497 { 1498 const SdrPathObj* pSrcPath = PTR_CAST(SdrPathObj, pObj); 1499 const SdrObjCustomShape* pCustomShape = PTR_CAST(SdrObjCustomShape, pObj); 1500 1501 const bool bUndo = IsUndoEnabled(); 1502 1503 if(pSrcPath) 1504 { 1505 // #i74631# redesigned due to XpolyPolygon removal and explicit constructors 1506 SdrObject* pLast = 0; // fuer die Zuweisung des OutlinerParaObject 1507 const basegfx::B2DPolyPolygon& rPolyPolygon(pSrcPath->GetPathPoly()); 1508 const sal_uInt32 nPolyCount(rPolyPolygon.count()); 1509 1510 for(sal_uInt32 a(0); a < nPolyCount; a++) 1511 { 1512 const basegfx::B2DPolygon& rCandidate(rPolyPolygon.getB2DPolygon(a)); 1513 const sal_uInt32 nPointCount(rCandidate.count()); 1514 1515 if(!bMakeLines || nPointCount < 2) 1516 { 1517 SdrPathObj* pPath = new SdrPathObj((SdrObjKind)pSrcPath->GetObjIdentifier(), basegfx::B2DPolyPolygon(rCandidate)); 1518 ImpCopyAttributes(pSrcPath, pPath); 1519 pLast = pPath; 1520 SdrInsertReason aReason(SDRREASON_VIEWCALL, pSrcPath); 1521 rOL.InsertObject(pPath, rPos, &aReason); 1522 if( bUndo ) 1523 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoNewObject(*pPath, sal_True)); 1524 MarkObj(pPath, pPV, sal_False, sal_True); 1525 rPos++; 1526 } 1527 else 1528 { 1529 const sal_uInt32 nLoopCount(rCandidate.isClosed() ? nPointCount : nPointCount - 1); 1530 1531 for(sal_uInt32 b(0); b < nLoopCount; b++) 1532 { 1533 SdrObjKind eKind(OBJ_PLIN); 1534 basegfx::B2DPolygon aNewPolygon; 1535 const sal_uInt32 nNextIndex((b + 1) % nPointCount); 1536 1537 aNewPolygon.append(rCandidate.getB2DPoint(b)); 1538 1539 if(rCandidate.areControlPointsUsed()) 1540 { 1541 aNewPolygon.appendBezierSegment( 1542 rCandidate.getNextControlPoint(b), 1543 rCandidate.getPrevControlPoint(nNextIndex), 1544 rCandidate.getB2DPoint(nNextIndex)); 1545 eKind = OBJ_PATHLINE; 1546 } 1547 else 1548 { 1549 aNewPolygon.append(rCandidate.getB2DPoint(nNextIndex)); 1550 } 1551 1552 SdrPathObj* pPath = new SdrPathObj(eKind, basegfx::B2DPolyPolygon(aNewPolygon)); 1553 ImpCopyAttributes(pSrcPath, pPath); 1554 pLast = pPath; 1555 SdrInsertReason aReason(SDRREASON_VIEWCALL, pSrcPath); 1556 rOL.InsertObject(pPath, rPos, &aReason); 1557 if( bUndo ) 1558 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoNewObject(*pPath, sal_True)); 1559 MarkObj(pPath, pPV, sal_False, sal_True); 1560 rPos++; 1561 } 1562 } 1563 } 1564 1565 if(pLast && pSrcPath->GetOutlinerParaObject()) 1566 { 1567 pLast->SetOutlinerParaObject(new OutlinerParaObject(*pSrcPath->GetOutlinerParaObject())); 1568 } 1569 } 1570 else if(pCustomShape) 1571 { 1572 if(bMakeLines) 1573 { 1574 // break up custom shape 1575 const SdrObject* pReplacement = pCustomShape->GetSdrObjectFromCustomShape(); 1576 1577 if(pReplacement) 1578 { 1579 SdrObject* pCandidate = pReplacement->Clone(); 1580 DBG_ASSERT(pCandidate, "SdrEditView::ImpDismantleOneObject: Could not clone SdrObject (!)"); 1581 pCandidate->SetModel(pCustomShape->GetModel()); 1582 1583 if(((SdrShadowItem&)pCustomShape->GetMergedItem(SDRATTR_SHADOW)).GetValue()) 1584 { 1585 if(pReplacement->ISA(SdrObjGroup)) 1586 { 1587 pCandidate->SetMergedItem(SdrShadowItem(sal_True)); 1588 } 1589 } 1590 1591 SdrInsertReason aReason(SDRREASON_VIEWCALL, pCustomShape); 1592 rOL.InsertObject(pCandidate, rPos, &aReason); 1593 if( bUndo ) 1594 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoNewObject(*pCandidate, true)); 1595 MarkObj(pCandidate, pPV, sal_False, sal_True); 1596 1597 if(pCustomShape->HasText() && !pCustomShape->IsTextPath()) 1598 { 1599 // #i37011# also create a text object and add at rPos + 1 1600 SdrTextObj* pTextObj = (SdrTextObj*)SdrObjFactory::MakeNewObject( 1601 pCustomShape->GetObjInventor(), OBJ_TEXT, 0L, pCustomShape->GetModel()); 1602 1603 // Copy text content 1604 OutlinerParaObject* pParaObj = pCustomShape->GetOutlinerParaObject(); 1605 if(pParaObj) 1606 { 1607 pTextObj->NbcSetOutlinerParaObject(new OutlinerParaObject(*pParaObj)); 1608 } 1609 1610 // copy all attributes 1611 SfxItemSet aTargetItemSet(pCustomShape->GetMergedItemSet()); 1612 1613 // clear fill and line style 1614 aTargetItemSet.Put(XLineStyleItem(XLINE_NONE)); 1615 aTargetItemSet.Put(XFillStyleItem(XFILL_NONE)); 1616 1617 // get the text bounds and set at text object 1618 Rectangle aTextBounds = pCustomShape->GetSnapRect(); 1619 if(pCustomShape->GetTextBounds(aTextBounds)) 1620 { 1621 pTextObj->SetSnapRect(aTextBounds); 1622 } 1623 1624 // if rotated, copy GeoStat, too. 1625 const GeoStat& rSourceGeo = pCustomShape->GetGeoStat(); 1626 if(rSourceGeo.nDrehWink) 1627 { 1628 pTextObj->NbcRotate( 1629 pCustomShape->GetSnapRect().Center(), rSourceGeo.nDrehWink, 1630 rSourceGeo.nSin, rSourceGeo.nCos); 1631 } 1632 1633 // set modified ItemSet at text object 1634 pTextObj->SetMergedItemSet(aTargetItemSet); 1635 1636 // insert object 1637 rOL.InsertObject(pTextObj, rPos + 1, &aReason); 1638 if( bUndo ) 1639 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoNewObject(*pTextObj, true)); 1640 MarkObj(pTextObj, pPV, sal_False, sal_True); 1641 } 1642 } 1643 } 1644 } 1645 } 1646 1647 void SdrEditView::DismantleMarkedObjects(sal_Bool bMakeLines) 1648 { 1649 //sal_uInt32 nCnt(0); 1650 // Temporaere Marklist 1651 SdrMarkList aRemoveMerker; 1652 1653 SortMarkedObjects(); 1654 1655 const bool bUndo = IsUndoEnabled(); 1656 1657 if( bUndo ) 1658 { 1659 // Der Comment wird spaeter zusammengebaut 1660 BegUndo(String(), String(), 1661 bMakeLines ? SDRREPFUNC_OBJ_DISMANTLE_LINES : SDRREPFUNC_OBJ_DISMANTLE_POLYS); 1662 } 1663 1664 sal_uIntPtr nm; 1665 sal_uIntPtr nAnz=GetMarkedObjectCount(); 1666 SdrObjList* pOL0=NULL; 1667 for (nm=nAnz; nm>0;) { 1668 nm--; 1669 SdrMark* pM=GetSdrMarkByIndex(nm); 1670 SdrObject* pObj=pM->GetMarkedSdrObj(); 1671 SdrPageView* pPV=pM->GetPageView(); 1672 SdrObjList* pOL=pObj->GetObjList(); 1673 if (pOL!=pOL0) { pOL0=pOL; pObj->GetOrdNum(); } // sicherstellen, dass OrdNums stimmen! 1674 if (ImpCanDismantle(pObj,bMakeLines)) { 1675 aRemoveMerker.InsertEntry(SdrMark(pObj,pM->GetPageView())); 1676 sal_uIntPtr nPos0=pObj->GetOrdNumDirect(); 1677 sal_uIntPtr nPos=nPos0+1; 1678 SdrObjList* pSubList=pObj->GetSubList(); 1679 if (pSubList!=NULL && !pObj->Is3DObj()) { 1680 SdrObjListIter aIter(*pSubList,IM_DEEPNOGROUPS); 1681 while (aIter.IsMore()) { 1682 const SdrObject* pObj1=aIter.Next(); 1683 ImpDismantleOneObject(pObj1,*pOL,nPos,pPV,bMakeLines); 1684 } 1685 } else { 1686 ImpDismantleOneObject(pObj,*pOL,nPos,pPV,bMakeLines); 1687 } 1688 if( bUndo ) 1689 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoDeleteObject(*pObj,sal_True)); 1690 pOL->RemoveObject(nPos0); 1691 1692 if( !bUndo ) 1693 SdrObject::Free(pObj); 1694 } 1695 } 1696 1697 if( bUndo ) 1698 { 1699 // UndoComment aus den tatsaechlich verwendeten Objekten zusammenbauen 1700 SetUndoComment(ImpGetResStr(bMakeLines?STR_EditDismantle_Lines:STR_EditDismantle_Polys),aRemoveMerker.GetMarkDescription()); 1701 // die tatsaechlich verwendeten Objekten aus der Liste entfernen 1702 EndUndo(); 1703 } 1704 } 1705 1706 //////////////////////////////////////////////////////////////////////////////////////////////////// 1707 // 1708 // #### #### ### # # #### 1709 // # # # # # # # # # 1710 // # ## #### # # # # #### 1711 // # # # # # # # # # 1712 // #### # # ### ### # 1713 // 1714 //////////////////////////////////////////////////////////////////////////////////////////////////// 1715 1716 void SdrEditView::GroupMarked(const SdrObject* pUserGrp) 1717 { 1718 if (AreObjectsMarked()) 1719 { 1720 SortMarkedObjects(); 1721 1722 const bool bUndo = IsUndoEnabled(); 1723 if( bUndo ) 1724 { 1725 BegUndo(ImpGetResStr(STR_EditGroup),GetDescriptionOfMarkedObjects(),SDRREPFUNC_OBJ_GROUP); 1726 1727 const sal_uIntPtr nAnz = GetMarkedObjectCount(); 1728 for(sal_uIntPtr nm = nAnz; nm>0; ) 1729 { 1730 // UndoActions fuer alle betroffenen Objekte anlegen 1731 nm--; 1732 SdrMark* pM=GetSdrMarkByIndex(nm); 1733 SdrObject* pObj = pM->GetMarkedSdrObj(); 1734 std::vector< SdrUndoAction* > vConnectorUndoActions( CreateConnectorUndo( *pObj ) ); 1735 AddUndoActions( vConnectorUndoActions ); 1736 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoRemoveObject( *pObj )); 1737 } 1738 } 1739 1740 SdrMarkList aNewMark; 1741 SdrPageView* pPV = GetSdrPageView(); 1742 1743 if(pPV) 1744 { 1745 SdrObjList* pAktLst=pPV->GetObjList(); 1746 SdrObjList* pSrcLst=pAktLst; 1747 SdrObjList* pSrcLst0=pSrcLst; 1748 SdrPage* pPage=pPV->GetPage(); 1749 // sicherstellen, dass die OrdNums stimmen 1750 if (pSrcLst->IsObjOrdNumsDirty()) 1751 pSrcLst->RecalcObjOrdNums(); 1752 SdrObject* pGrp=NULL; 1753 SdrObject* pRefObj=NULL; // Referenz fuer InsertReason (-> rumankern im Writer) 1754 SdrObject* pRefObj1=NULL; // Referenz fuer InsertReason (-> rumankern im Writer) 1755 SdrObjList* pDstLst=NULL; 1756 // Falls alle markierten Objekte aus Fremden Obj-Listen 1757 // kommen, kommt das Gruppenobjekt an das Ende der Liste. 1758 sal_uIntPtr nInsPos=pSrcLst->GetObjCount(); 1759 sal_Bool bNeedInsPos=sal_True; 1760 for (sal_uIntPtr nm=GetMarkedObjectCount(); nm>0;) 1761 { 1762 nm--; 1763 SdrMark* pM=GetSdrMarkByIndex(nm); 1764 if (pM->GetPageView()==pPV) 1765 { 1766 if (pGrp==NULL) 1767 { 1768 if (pUserGrp!=NULL) 1769 pGrp=pUserGrp->Clone(); 1770 if (pGrp==NULL) 1771 pGrp=new SdrObjGroup; 1772 pDstLst=pGrp->GetSubList(); 1773 DBG_ASSERT(pDstLst!=NULL,"Angebliches Gruppenobjekt liefert keine Objektliste"); 1774 } 1775 SdrObject* pObj=pM->GetMarkedSdrObj(); 1776 pSrcLst=pObj->GetObjList(); 1777 if (pSrcLst!=pSrcLst0) 1778 { 1779 if (pSrcLst->IsObjOrdNumsDirty()) 1780 pSrcLst->RecalcObjOrdNums(); 1781 } 1782 sal_Bool bForeignList=pSrcLst!=pAktLst; 1783 sal_Bool bGrouped=pSrcLst!=pPage; 1784 if (!bForeignList && bNeedInsPos) 1785 { 1786 nInsPos=pObj->GetOrdNum(); // ua, damit sind alle ObjOrdNum der Page gesetzt 1787 nInsPos++; 1788 bNeedInsPos=sal_False; 1789 } 1790 pSrcLst->RemoveObject(pObj->GetOrdNumDirect()); 1791 if (!bForeignList) 1792 nInsPos--; // InsertPos korregieren 1793 SdrInsertReason aReason(SDRREASON_VIEWCALL); 1794 pDstLst->InsertObject(pObj,0,&aReason); 1795 GetMarkedObjectListWriteAccess().DeleteMark(nm); 1796 if (pRefObj1==NULL) 1797 pRefObj1=pObj; // Das oberste sichtbare Objekt 1798 if (!bGrouped) 1799 { 1800 if (pRefObj==NULL) 1801 pRefObj=pObj; // Das oberste sichtbare nicht gruppierte Objekt 1802 } 1803 pSrcLst0=pSrcLst; 1804 } 1805 } 1806 if (pRefObj==NULL) 1807 pRefObj=pRefObj1; 1808 if (pGrp!=NULL) 1809 { 1810 aNewMark.InsertEntry(SdrMark(pGrp,pPV)); 1811 sal_uIntPtr nAnz=pDstLst->GetObjCount(); 1812 SdrInsertReason aReason(SDRREASON_VIEWCALL,pRefObj); 1813 pAktLst->InsertObject(pGrp,nInsPos,&aReason); 1814 if( bUndo ) 1815 { 1816 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoNewObject(*pGrp,true)); // Kein Recalc! 1817 for (sal_uIntPtr no=0; no<nAnz; no++) 1818 { 1819 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoInsertObject(*pDstLst->GetObj(no))); 1820 } 1821 } 1822 } 1823 } 1824 GetMarkedObjectListWriteAccess().Merge(aNewMark); 1825 MarkListHasChanged(); 1826 1827 if( bUndo ) 1828 EndUndo(); 1829 } 1830 } 1831 1832 //////////////////////////////////////////////////////////////////////////////////////////////////// 1833 // 1834 // # # # # #### #### ### # # #### 1835 // # # ## # # # # # # # # # # 1836 // # # # # # # ## #### # # # # #### 1837 // # # # ## # # # # # # # # # 1838 // ### # # #### # # ### ### # 1839 // 1840 //////////////////////////////////////////////////////////////////////////////////////////////////// 1841 1842 void SdrEditView::UnGroupMarked() 1843 { 1844 SdrMarkList aNewMark; 1845 1846 const bool bUndo = IsUndoEnabled(); 1847 if( bUndo ) 1848 BegUndo(String(), String(), SDRREPFUNC_OBJ_UNGROUP); 1849 1850 sal_uIntPtr nCount=0; 1851 XubString aName1; 1852 XubString aName; 1853 sal_Bool bNameOk=sal_False; 1854 for (sal_uIntPtr nm=GetMarkedObjectCount(); nm>0;) { 1855 nm--; 1856 SdrMark* pM=GetSdrMarkByIndex(nm); 1857 SdrObject* pGrp=pM->GetMarkedSdrObj(); 1858 SdrObjList* pSrcLst=pGrp->GetSubList(); 1859 if (pSrcLst!=NULL) { 1860 nCount++; 1861 if (nCount==1) { 1862 pGrp->TakeObjNameSingul(aName); // Bezeichnung der Gruppe holen 1863 pGrp->TakeObjNamePlural(aName1); // Bezeichnung der Gruppe holen 1864 bNameOk=sal_True; 1865 } else { 1866 if (nCount==2) aName=aName1; // Pluralname setzen 1867 if (bNameOk) { 1868 XubString aStr; 1869 pGrp->TakeObjNamePlural(aStr); // Bezeichnung der Gruppe holen 1870 1871 if(!aStr.Equals(aName)) 1872 bNameOk = sal_False; 1873 } 1874 } 1875 sal_uIntPtr nDstCnt=pGrp->GetOrdNum(); 1876 SdrObjList* pDstLst=pM->GetPageView()->GetObjList(); 1877 1878 // FIRST move contained objects to parent of group, so that 1879 // the contained objects are NOT migrated to the UNDO-ItemPool 1880 // when AddUndo(new SdrUndoDelObj(*pGrp)) is called. 1881 sal_uIntPtr nAnz=pSrcLst->GetObjCount(); 1882 sal_uIntPtr no; 1883 1884 if( bUndo ) 1885 { 1886 for (no=nAnz; no>0;) 1887 { 1888 no--; 1889 SdrObject* pObj=pSrcLst->GetObj(no); 1890 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoRemoveObject(*pObj)); 1891 } 1892 } 1893 for (no=0; no<nAnz; no++) 1894 { 1895 SdrObject* pObj=pSrcLst->RemoveObject(0); 1896 SdrInsertReason aReason(SDRREASON_VIEWCALL,pGrp); 1897 pDstLst->InsertObject(pObj,nDstCnt,&aReason); 1898 if( bUndo ) 1899 AddUndo( GetModel()->GetSdrUndoFactory().CreateUndoInsertObject(*pObj,true)); 1900 nDstCnt++; 1901 // Kein SortCheck beim einfuegen in die MarkList, denn das 1902 // wuerde wg. pObj->GetOrdNum() jedesmal ein RecalcOrdNums() 1903 // provozieren: 1904 aNewMark.InsertEntry(SdrMark(pObj,pM->GetPageView()),sal_False); 1905 } 1906 1907 if( bUndo ) 1908 { 1909 // Now it is safe to add the delete-UNDO which trigers the 1910 // MigrateItemPool now only for itself, not for the subobjects. 1911 // nDstCnt is right, because previous inserts move group 1912 // object deeper and increase nDstCnt. 1913 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoDeleteObject(*pGrp)); 1914 } 1915 pDstLst->RemoveObject(nDstCnt); 1916 1917 if( !bUndo ) 1918 SdrObject::Free(pGrp); 1919 1920 GetMarkedObjectListWriteAccess().DeleteMark(nm); 1921 } 1922 } 1923 if (nCount!=0) 1924 { 1925 if (!bNameOk) 1926 aName=ImpGetResStr(STR_ObjNamePluralGRUP); // Oberbegriff Gruppenobjekte verwenden, wenn verschiedene Objekte. 1927 SetUndoComment(ImpGetResStr(STR_EditUngroup),aName); 1928 } 1929 1930 if( bUndo ) 1931 EndUndo(); 1932 1933 if (nCount!=0) 1934 { 1935 GetMarkedObjectListWriteAccess().Merge(aNewMark,sal_True); // Durch das obige Einsortieren ist aNewMark genau verkehrtherum 1936 MarkListHasChanged(); 1937 } 1938 } 1939 1940 //////////////////////////////////////////////////////////////////////////////////////////////////// 1941 // 1942 // ### ### # # # # ##### #### ##### ##### ### #### ### # # # 1943 // # # # # ## # # # # # # # # # # # # # # # # # 1944 // # # # # # # # # #### #### # # # # #### # # # # 1945 // # # # # # ## # # # # # # # # # # # # # # 1946 // ### ### # # # ##### # # # # ### # ### #### # 1947 // 1948 //////////////////////////////////////////////////////////////////////////////////////////////////// 1949 1950 SdrObject* SdrEditView::ImpConvertOneObj(SdrObject* pObj, sal_Bool bPath, sal_Bool bLineToArea) 1951 { 1952 SdrObject* pNewObj = pObj->ConvertToPolyObj(bPath, bLineToArea); 1953 if (pNewObj!=NULL) 1954 { 1955 SdrObjList* pOL=pObj->GetObjList(); 1956 DBG_ASSERT(pOL!=NULL,"ConvertTo: Obj liefert keine ObjList"); 1957 if (pOL!=NULL) 1958 { 1959 const bool bUndo = IsUndoEnabled(); 1960 if( bUndo ) 1961 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoReplaceObject(*pObj,*pNewObj)); 1962 1963 pOL->ReplaceObject(pNewObj,pObj->GetOrdNum()); 1964 1965 if( !bUndo ) 1966 SdrObject::Free(pObj); 1967 } 1968 } 1969 return pNewObj; 1970 } 1971 1972 void SdrEditView::ImpConvertTo(sal_Bool bPath, sal_Bool bLineToArea) 1973 { 1974 sal_Bool bMrkChg=sal_False; 1975 sal_Bool bModChg=sal_False; 1976 if (AreObjectsMarked()) { 1977 sal_uIntPtr nMarkAnz=GetMarkedObjectCount(); 1978 sal_uInt16 nDscrID=0; 1979 if(bLineToArea) 1980 { 1981 if(nMarkAnz == 1) 1982 nDscrID = STR_EditConvToContour; 1983 else 1984 nDscrID = STR_EditConvToContours; 1985 1986 BegUndo(ImpGetResStr(nDscrID), GetDescriptionOfMarkedObjects()); 1987 } 1988 else 1989 { 1990 if (bPath) { 1991 if (nMarkAnz==1) nDscrID=STR_EditConvToCurve; 1992 else nDscrID=STR_EditConvToCurves; 1993 BegUndo(ImpGetResStr(nDscrID),GetDescriptionOfMarkedObjects(),SDRREPFUNC_OBJ_CONVERTTOPATH); 1994 } else { 1995 if (nMarkAnz==1) nDscrID=STR_EditConvToPoly; 1996 else nDscrID=STR_EditConvToPolys; 1997 BegUndo(ImpGetResStr(nDscrID),GetDescriptionOfMarkedObjects(),SDRREPFUNC_OBJ_CONVERTTOPOLY); 1998 } 1999 } 2000 for (sal_uIntPtr nm=nMarkAnz; nm>0;) { 2001 nm--; 2002 SdrMark* pM=GetSdrMarkByIndex(nm); 2003 SdrObject* pObj=pM->GetMarkedSdrObj(); 2004 SdrPageView* pPV=pM->GetPageView(); 2005 if (pObj->IsGroupObject() && !pObj->Is3DObj()) { 2006 SdrObject* pGrp=pObj; 2007 SdrObjListIter aIter(*pGrp,IM_DEEPNOGROUPS); 2008 while (aIter.IsMore()) { 2009 pObj=aIter.Next(); 2010 if (ImpConvertOneObj(pObj,bPath,bLineToArea)) bModChg=sal_True; 2011 } 2012 } else { 2013 SdrObject* pNewObj=ImpConvertOneObj(pObj,bPath,bLineToArea); 2014 if (pNewObj!=NULL) { 2015 bModChg=sal_True; 2016 bMrkChg=sal_True; 2017 GetMarkedObjectListWriteAccess().ReplaceMark(SdrMark(pNewObj,pPV),nm); 2018 } 2019 } 2020 } 2021 EndUndo(); 2022 if (bMrkChg) AdjustMarkHdl(); 2023 if (bMrkChg) MarkListHasChanged(); 2024 } 2025 } 2026 2027 void SdrEditView::ConvertMarkedToPathObj(sal_Bool bLineToArea) 2028 { 2029 ImpConvertTo(sal_True, bLineToArea); 2030 } 2031 2032 void SdrEditView::ConvertMarkedToPolyObj(sal_Bool bLineToArea) 2033 { 2034 ImpConvertTo(sal_False, bLineToArea); 2035 } 2036 2037 //////////////////////////////////////////////////////////////////////////////////////////////////// 2038 // 2039 // # # ##### ##### ### ##### # # ##### # # # #### ### #### ##### 2040 // ## ## # # # # # # # # # ## ## # # # # # # # 2041 // # # # #### # ##### ### # # #### ### # # # # #### # # #### # 2042 // # # # # # # # # # # # # # # # # # # # 2043 // # # ##### # # # # # #### ##### # # # # ### # # # 2044 // 2045 //////////////////////////////////////////////////////////////////////////////////////////////////// 2046 2047 void SdrEditView::DoImportMarkedMtf(SvdProgressInfo *pProgrInfo) 2048 { 2049 const bool bUndo = IsUndoEnabled(); 2050 2051 if( bUndo ) 2052 BegUndo(String(), String(), SDRREPFUNC_OBJ_IMPORTMTF); 2053 2054 SortMarkedObjects(); 2055 SdrMarkList aForTheDescription; 2056 SdrMarkList aNewMarked; 2057 sal_uIntPtr nAnz=GetMarkedObjectCount(); 2058 2059 for (sal_uIntPtr nm=nAnz; nm>0;) 2060 { // Undo Objekte fuer alle neuen Objekte erzeugen 2061 // zwischen den Metafiles auf Abbruch testen 2062 if( pProgrInfo != NULL ) 2063 { 2064 pProgrInfo->SetNextObject(); 2065 if(!pProgrInfo->ReportActions(0)) 2066 break; 2067 } 2068 2069 nm--; 2070 SdrMark* pM=GetSdrMarkByIndex(nm); 2071 SdrObject* pObj=pM->GetMarkedSdrObj(); 2072 SdrPageView* pPV=pM->GetPageView(); 2073 SdrObjList* pOL=pObj->GetObjList(); 2074 sal_uIntPtr nInsPos=pObj->GetOrdNum()+1; 2075 SdrGrafObj* pGraf=PTR_CAST(SdrGrafObj,pObj); 2076 SdrOle2Obj* pOle2=PTR_CAST(SdrOle2Obj,pObj); 2077 sal_uIntPtr nInsAnz=0; 2078 Rectangle aLogicRect; 2079 2080 if (pGraf!=NULL && pGraf->HasGDIMetaFile()) 2081 { 2082 ImpSdrGDIMetaFileImport aFilter(*pMod); 2083 2084 aLogicRect = pGraf->GetLogicRect(); 2085 aFilter.SetScaleRect(aLogicRect); 2086 aFilter.SetLayer(pObj->GetLayer()); 2087 2088 nInsAnz=aFilter.DoImport(pGraf->GetTransformedGraphic( 2089 SDRGRAFOBJ_TRANSFORMATTR_COLOR|SDRGRAFOBJ_TRANSFORMATTR_MIRROR).GetGDIMetaFile(), 2090 *pOL,nInsPos,pProgrInfo); 2091 } 2092 if ( pOle2!=NULL && pOle2->GetGraphic() ) 2093 { 2094 //const GDIMetaFile* pMtf=pOle2->GetGDIMetaFile(); 2095 ImpSdrGDIMetaFileImport aFilter(*pMod); 2096 2097 aLogicRect = pOle2->GetLogicRect(); 2098 aFilter.SetScaleRect(aLogicRect); 2099 aFilter.SetLayer(pObj->GetLayer()); 2100 2101 nInsAnz=aFilter.DoImport(pOle2->GetGraphic()->GetGDIMetaFile(),*pOL,nInsPos,pProgrInfo); 2102 } 2103 if (nInsAnz!=0) 2104 { 2105 // transformation 2106 GeoStat aGeoStat(pGraf ? pGraf->GetGeoStat() : pOle2->GetGeoStat()); 2107 sal_uIntPtr nObj=nInsPos; 2108 2109 if(aGeoStat.nShearWink) 2110 { 2111 aGeoStat.RecalcTan(); 2112 } 2113 2114 if(aGeoStat.nDrehWink) 2115 { 2116 aGeoStat.RecalcSinCos(); 2117 } 2118 2119 for (sal_uIntPtr i=0; i<nInsAnz; i++) 2120 { 2121 if( bUndo ) 2122 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoNewObject(*pOL->GetObj(nObj))); 2123 2124 // Neue MarkList pflegen 2125 SdrObject* pCandidate = pOL->GetObj(nObj); 2126 2127 // apply original transformation 2128 if(aGeoStat.nShearWink) 2129 { 2130 pCandidate->NbcShear(aLogicRect.TopLeft(), aGeoStat.nShearWink, aGeoStat.nTan, false); 2131 } 2132 2133 if(aGeoStat.nDrehWink) 2134 { 2135 pCandidate->NbcRotate(aLogicRect.TopLeft(), aGeoStat.nDrehWink, aGeoStat.nSin, aGeoStat.nCos); 2136 } 2137 2138 SdrMark aNewMark(pCandidate, pPV); 2139 aNewMarked.InsertEntry(aNewMark); 2140 2141 nObj++; 2142 } 2143 aForTheDescription.InsertEntry(*pM); 2144 2145 if( bUndo ) 2146 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoDeleteObject(*pObj)); 2147 2148 // Objekt aus selektion loesen und loeschen 2149 GetMarkedObjectListWriteAccess().DeleteMark(TryToFindMarkedObject(pObj)); 2150 pOL->RemoveObject(nInsPos-1); 2151 2152 if( !bUndo ) 2153 SdrObject::Free(pObj); 2154 } 2155 } 2156 2157 // MarkObj... fehlt... jetzt nicht mehr (AW) 2158 if(aNewMarked.GetMarkCount()) 2159 { 2160 // Neue Selektion bilden 2161 for(sal_uIntPtr a(0); a < aNewMarked.GetMarkCount(); a++) 2162 { 2163 GetMarkedObjectListWriteAccess().InsertEntry(*aNewMarked.GetMark(a)); 2164 } 2165 2166 SortMarkedObjects(); 2167 } 2168 2169 if( bUndo ) 2170 { 2171 SetUndoComment(ImpGetResStr(STR_EditImportMtf),aForTheDescription.GetMarkDescription()); 2172 EndUndo(); 2173 } 2174 } 2175 2176