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