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 MarkObj(pPath, pInsPV, sal_False, sal_True); 1168 } 1169 1170 aRemove.ForceSort(); 1171 switch(eMode) 1172 { 1173 case SDR_MERGE_MERGE: 1174 { 1175 SetUndoComment( 1176 ImpGetResStr(STR_EditMergeMergePoly), 1177 aRemove.GetMarkDescription()); 1178 break; 1179 } 1180 case SDR_MERGE_SUBSTRACT: 1181 { 1182 SetUndoComment( 1183 ImpGetResStr(STR_EditMergeSubstractPoly), 1184 aRemove.GetMarkDescription()); 1185 break; 1186 } 1187 case SDR_MERGE_INTERSECT: 1188 { 1189 SetUndoComment( 1190 ImpGetResStr(STR_EditMergeIntersectPoly), 1191 aRemove.GetMarkDescription()); 1192 break; 1193 } 1194 } 1195 DeleteMarkedList(aRemove); 1196 1197 if( bUndo ) 1198 EndUndo(); 1199 } 1200 } 1201 1202 void SdrEditView::CombineMarkedObjects(sal_Bool bNoPolyPoly) 1203 { 1204 // #105899# Start of Combine-Undo put to front, else ConvertMarkedToPolyObj would 1205 // create a 2nd Undo-action and Undo-Comment. 1206 1207 bool bUndo = IsUndoEnabled(); 1208 1209 // Undo-String will be set later 1210 if( bUndo ) 1211 BegUndo(String(), String(), bNoPolyPoly ? SDRREPFUNC_OBJ_COMBINE_ONEPOLY : SDRREPFUNC_OBJ_COMBINE_POLYPOLY); 1212 1213 // #105899# First, guarantee that all objects are converted to polyobjects, 1214 // especially for SdrGrafObj with bitmap filling this is necessary to not 1215 // loose the bitmap filling. 1216 1217 // #i12392# 1218 // ConvertMarkedToPolyObj was too strong here, it will loose quality and 1219 // information when curve objects are combined. This can be replaced by 1220 // using ConvertMarkedToPathObj without changing the previous fix. 1221 1222 // #i21250# 1223 // Instead of simply passing sal_True as LineToArea, use bNoPolyPoly as info 1224 // if this command is a 'Combine' or a 'Connect' command. On Connect it's sal_True. 1225 // To not concert line segments with a set line width to polygons in that case, 1226 // use this info. Do not convert LineToArea on Connect commands. 1227 // ConvertMarkedToPathObj(!bNoPolyPoly); 1228 1229 // #114310# 1230 // This is used for Combine and Connect. In no case it is necessary to force 1231 // the content to curve, but it is also not good to force to polygons. Thus, 1232 // curve is the less information loosing one. Remember: This place is not 1233 // used for merge. 1234 // LineToArea is never necessary, both commands are able to take over the 1235 // set line style and to display it correctly. Thus, i will use a 1236 // ConvertMarkedToPathObj with a sal_False in any case. Only drawback is that 1237 // simple polygons will be changed to curves, but with no information loss. 1238 ConvertMarkedToPathObj(sal_False /* bLineToArea */); 1239 1240 // continue as before 1241 basegfx::B2DPolyPolygon aPolyPolygon; 1242 SdrObjList* pAktOL = 0L; 1243 SdrMarkList aRemoveMerker; 1244 1245 SortMarkedObjects(); 1246 sal_uInt32 nInsPos(0xFFFFFFFF); 1247 SdrObjList* pInsOL = 0L; 1248 SdrPageView* pInsPV = 0L; 1249 const sal_uInt32 nAnz(GetMarkedObjectCount()); 1250 const SdrObject* pAttrObj = 0L; 1251 1252 for(sal_uInt32 a(nAnz); a > 0L; ) 1253 { 1254 a--; 1255 SdrMark* pM = GetSdrMarkByIndex(a); 1256 SdrObject* pObj = pM->GetMarkedSdrObj(); 1257 SdrObjList* pThisOL = pObj->GetObjList(); 1258 1259 if(pAktOL != pThisOL) 1260 { 1261 pAktOL = pThisOL; 1262 } 1263 1264 if(ImpCanConvertForCombine(pObj)) 1265 { 1266 // Obj merken fuer Attribute kopieren 1267 pAttrObj = pObj; 1268 1269 // unfortunately ConvertMarkedToPathObj has converted all 1270 // involved polygon data to curve segments, even if not necessary. 1271 // It is better to try to reduce to more simple polygons. 1272 basegfx::B2DPolyPolygon aTmpPoly(basegfx::tools::simplifyCurveSegments(ImpGetPolyPolygon(pObj, sal_True))); 1273 aPolyPolygon.insert(0L, aTmpPoly); 1274 1275 if(!pInsOL) 1276 { 1277 nInsPos = pObj->GetOrdNum() + 1L; 1278 pInsPV = pM->GetPageView(); 1279 pInsOL = pObj->GetObjList(); 1280 } 1281 1282 aRemoveMerker.InsertEntry(SdrMark(pObj, pM->GetPageView())); 1283 } 1284 } 1285 1286 if(bNoPolyPoly) 1287 { 1288 basegfx::B2DPolygon aCombinedPolygon(ImpCombineToSinglePolygon(aPolyPolygon)); 1289 aPolyPolygon.clear(); 1290 aPolyPolygon.append(aCombinedPolygon); 1291 } 1292 1293 const sal_uInt32 nPolyCount(aPolyPolygon.count()); 1294 1295 if(nPolyCount) 1296 { 1297 SdrObjKind eKind = OBJ_PATHFILL; 1298 1299 if(nPolyCount > 1L) 1300 { 1301 aPolyPolygon.setClosed(true); 1302 } 1303 else 1304 { 1305 // auf Polyline Checken 1306 const basegfx::B2DPolygon aPolygon(aPolyPolygon.getB2DPolygon(0L)); 1307 const sal_uInt32 nPointCount(aPolygon.count()); 1308 1309 if(nPointCount <= 2L) 1310 { 1311 eKind = OBJ_PATHLINE; 1312 } 1313 else 1314 { 1315 if(!aPolygon.isClosed()) 1316 { 1317 const basegfx::B2DPoint aPointA(aPolygon.getB2DPoint(0L)); 1318 const basegfx::B2DPoint aPointB(aPolygon.getB2DPoint(nPointCount - 1L)); 1319 const double fDistance(basegfx::B2DVector(aPointB - aPointA).getLength()); 1320 const double fJoinTolerance(10.0); 1321 1322 if(fDistance < fJoinTolerance) 1323 { 1324 aPolyPolygon.setClosed(true); 1325 } 1326 else 1327 { 1328 eKind = OBJ_PATHLINE; 1329 } 1330 } 1331 } 1332 } 1333 1334 SdrPathObj* pPath = new SdrPathObj(eKind,aPolyPolygon); 1335 1336 // Attribute des untersten Objekts 1337 ImpCopyAttributes(pAttrObj, pPath); 1338 1339 // #100408# If LineStyle of pAttrObj is XLINE_NONE force to XLINE_SOLID to make visible. 1340 const XLineStyle eLineStyle = ((const XLineStyleItem&)pAttrObj->GetMergedItem(XATTR_LINESTYLE)).GetValue(); 1341 const XFillStyle eFillStyle = ((const XFillStyleItem&)pAttrObj->GetMergedItem(XATTR_FILLSTYLE)).GetValue(); 1342 1343 // #110635# 1344 // Take fill style/closed state of pAttrObj in account when deciding to change the line style 1345 sal_Bool bIsClosedPathObj(pAttrObj->ISA(SdrPathObj) && ((SdrPathObj*)pAttrObj)->IsClosed()); 1346 1347 if(XLINE_NONE == eLineStyle && (XFILL_NONE == eFillStyle || !bIsClosedPathObj)) 1348 { 1349 pPath->SetMergedItem(XLineStyleItem(XLINE_SOLID)); 1350 } 1351 1352 SdrInsertReason aReason(SDRREASON_VIEWCALL,pAttrObj); 1353 pInsOL->InsertObject(pPath,nInsPos,&aReason); 1354 if( bUndo ) 1355 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoNewObject(*pPath)); 1356 1357 // #111111# 1358 // Here was a severe error: Without UnmarkAllObj, the new object was marked 1359 // additionally to the two ones which are deleted below. As long as those are 1360 // in the UNDO there is no problem, but as soon as they get deleted, the 1361 // MarkList will contain deleted objects -> GPF. 1362 UnmarkAllObj(pInsPV); 1363 MarkObj(pPath, pInsPV, sal_False, sal_True); 1364 } 1365 1366 // UndoComment aus den tatsaechlich verwendeten Objekten zusammenbauen 1367 aRemoveMerker.ForceSort(); // wichtig fuer Remove (s.u.) 1368 if( bUndo ) 1369 SetUndoComment(ImpGetResStr(bNoPolyPoly?STR_EditCombine_OnePoly:STR_EditCombine_PolyPoly),aRemoveMerker.GetMarkDescription()); 1370 1371 // die tatsaechlich verwendeten Objekten aus der Liste entfernen 1372 DeleteMarkedList(aRemoveMerker); 1373 if( bUndo ) 1374 EndUndo(); 1375 } 1376 1377 //////////////////////////////////////////////////////////////////////////////////////////////////// 1378 // 1379 // @@@@@ @@ @@@@ @@ @@ @@@@ @@ @@ @@@@@@ @@ @@@@@ 1380 // @@ @@ @@ @@ @@ @@@ @@@ @@ @@ @@@ @@ @@ @@ @@ 1381 // @@ @@ @@ @@ @@@@@@@ @@ @@ @@@@@@ @@ @@ @@ 1382 // @@ @@ @@ @@@@ @@@@@@@ @@@@@@ @@@@@@ @@ @@ @@@@ 1383 // @@ @@ @@ @@ @@ @ @@ @@ @@ @@ @@@ @@ @@ @@ 1384 // @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ 1385 // @@@@@ @@ @@@@ @@ @@ @@ @@ @@ @@ @@ @@@@@ @@@@@ 1386 // 1387 //////////////////////////////////////////////////////////////////////////////////////////////////// 1388 1389 sal_Bool SdrEditView::ImpCanDismantle(const basegfx::B2DPolyPolygon& rPpolyPolygon, sal_Bool bMakeLines) const 1390 { 1391 sal_Bool bCan(sal_False); 1392 const sal_uInt32 nPolygonCount(rPpolyPolygon.count()); 1393 1394 if(nPolygonCount >= 2L) 1395 { 1396 // #i69172# dismantle makes sense with 2 or more polygons in a polyPolygon 1397 bCan = sal_True; 1398 } 1399 else if(bMakeLines && 1L == nPolygonCount) 1400 { 1401 // #i69172# ..or with at least 2 edges (curves or lines) 1402 const basegfx::B2DPolygon aPolygon(rPpolyPolygon.getB2DPolygon(0L)); 1403 const sal_uInt32 nPointCount(aPolygon.count()); 1404 1405 if(nPointCount > 2L) 1406 { 1407 bCan = sal_True; 1408 } 1409 } 1410 1411 return bCan; 1412 } 1413 1414 sal_Bool SdrEditView::ImpCanDismantle(const SdrObject* pObj, sal_Bool bMakeLines) const 1415 { 1416 sal_Bool bOtherObjs(sal_False); // sal_True=andere Objekte ausser PathObj's vorhanden 1417 sal_Bool bMin1PolyPoly(sal_False); // sal_True=mind. 1 PolyPolygon mit mehr als ein Polygon vorhanden 1418 SdrObjList* pOL = pObj->GetSubList(); 1419 1420 if(pOL) 1421 { 1422 // Aha, Gruppenobjekt. Also alle Member ansehen. 1423 // Alle muessen PathObjs sein ! 1424 SdrObjListIter aIter(*pOL, IM_DEEPNOGROUPS); 1425 1426 while(aIter.IsMore() && !bOtherObjs) 1427 { 1428 const SdrObject* pObj1 = aIter.Next(); 1429 const SdrPathObj* pPath = PTR_CAST(SdrPathObj, pObj1); 1430 1431 if(pPath) 1432 { 1433 if(ImpCanDismantle(pPath->GetPathPoly(), bMakeLines)) 1434 { 1435 bMin1PolyPoly = sal_True; 1436 } 1437 1438 SdrObjTransformInfoRec aInfo; 1439 pObj1->TakeObjInfo(aInfo); 1440 1441 if(!aInfo.bCanConvToPath) 1442 { 1443 // Passiert z.B. im Falle Fontwork (Joe, 28-11-95) 1444 bOtherObjs = sal_True; 1445 } 1446 } 1447 else 1448 { 1449 bOtherObjs = sal_True; 1450 } 1451 } 1452 } 1453 else 1454 { 1455 const SdrPathObj* pPath = PTR_CAST(SdrPathObj, pObj); 1456 const SdrObjCustomShape* pCustomShape = PTR_CAST(SdrObjCustomShape, pObj); 1457 1458 // #i37011# 1459 if(pPath) 1460 { 1461 if(ImpCanDismantle(pPath->GetPathPoly(),bMakeLines)) 1462 { 1463 bMin1PolyPoly = sal_True; 1464 } 1465 1466 SdrObjTransformInfoRec aInfo; 1467 pObj->TakeObjInfo(aInfo); 1468 1469 // #69711 : new condition IsLine() to be able to break simple Lines 1470 if(!(aInfo.bCanConvToPath || aInfo.bCanConvToPoly) && !pPath->IsLine()) 1471 { 1472 // Passiert z.B. im Falle Fontwork (Joe, 28-11-95) 1473 bOtherObjs = sal_True; 1474 } 1475 } 1476 else if(pCustomShape) 1477 { 1478 if(bMakeLines) 1479 { 1480 // allow break command 1481 bMin1PolyPoly = sal_True; 1482 } 1483 } 1484 else 1485 { 1486 bOtherObjs = sal_True; 1487 } 1488 } 1489 return bMin1PolyPoly && !bOtherObjs; 1490 } 1491 1492 void SdrEditView::ImpDismantleOneObject(const SdrObject* pObj, SdrObjList& rOL, sal_uIntPtr& rPos, SdrPageView* pPV, sal_Bool bMakeLines) 1493 { 1494 const SdrPathObj* pSrcPath = PTR_CAST(SdrPathObj, pObj); 1495 const SdrObjCustomShape* pCustomShape = PTR_CAST(SdrObjCustomShape, pObj); 1496 1497 const bool bUndo = IsUndoEnabled(); 1498 1499 if(pSrcPath) 1500 { 1501 // #i74631# redesigned due to XpolyPolygon removal and explicit constructors 1502 SdrObject* pLast = 0; // fuer die Zuweisung des OutlinerParaObject 1503 const basegfx::B2DPolyPolygon& rPolyPolygon(pSrcPath->GetPathPoly()); 1504 const sal_uInt32 nPolyCount(rPolyPolygon.count()); 1505 1506 for(sal_uInt32 a(0); a < nPolyCount; a++) 1507 { 1508 const basegfx::B2DPolygon& rCandidate(rPolyPolygon.getB2DPolygon(a)); 1509 const sal_uInt32 nPointCount(rCandidate.count()); 1510 1511 if(!bMakeLines || nPointCount < 2) 1512 { 1513 SdrPathObj* pPath = new SdrPathObj((SdrObjKind)pSrcPath->GetObjIdentifier(), basegfx::B2DPolyPolygon(rCandidate)); 1514 ImpCopyAttributes(pSrcPath, pPath); 1515 pLast = pPath; 1516 SdrInsertReason aReason(SDRREASON_VIEWCALL, pSrcPath); 1517 rOL.InsertObject(pPath, rPos, &aReason); 1518 if( bUndo ) 1519 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoNewObject(*pPath, sal_True)); 1520 MarkObj(pPath, pPV, sal_False, sal_True); 1521 rPos++; 1522 } 1523 else 1524 { 1525 const sal_uInt32 nLoopCount(rCandidate.isClosed() ? nPointCount : nPointCount - 1); 1526 1527 for(sal_uInt32 b(0); b < nLoopCount; b++) 1528 { 1529 SdrObjKind eKind(OBJ_PLIN); 1530 basegfx::B2DPolygon aNewPolygon; 1531 const sal_uInt32 nNextIndex((b + 1) % nPointCount); 1532 1533 aNewPolygon.append(rCandidate.getB2DPoint(b)); 1534 1535 if(rCandidate.areControlPointsUsed()) 1536 { 1537 aNewPolygon.appendBezierSegment( 1538 rCandidate.getNextControlPoint(b), 1539 rCandidate.getPrevControlPoint(nNextIndex), 1540 rCandidate.getB2DPoint(nNextIndex)); 1541 eKind = OBJ_PATHLINE; 1542 } 1543 else 1544 { 1545 aNewPolygon.append(rCandidate.getB2DPoint(nNextIndex)); 1546 } 1547 1548 SdrPathObj* pPath = new SdrPathObj(eKind, basegfx::B2DPolyPolygon(aNewPolygon)); 1549 ImpCopyAttributes(pSrcPath, pPath); 1550 pLast = pPath; 1551 SdrInsertReason aReason(SDRREASON_VIEWCALL, pSrcPath); 1552 rOL.InsertObject(pPath, rPos, &aReason); 1553 if( bUndo ) 1554 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoNewObject(*pPath, sal_True)); 1555 MarkObj(pPath, pPV, sal_False, sal_True); 1556 rPos++; 1557 } 1558 } 1559 } 1560 1561 if(pLast && pSrcPath->GetOutlinerParaObject()) 1562 { 1563 pLast->SetOutlinerParaObject(new OutlinerParaObject(*pSrcPath->GetOutlinerParaObject())); 1564 } 1565 } 1566 else if(pCustomShape) 1567 { 1568 if(bMakeLines) 1569 { 1570 // break up custom shape 1571 const SdrObject* pReplacement = pCustomShape->GetSdrObjectFromCustomShape(); 1572 1573 if(pReplacement) 1574 { 1575 SdrObject* pCandidate = pReplacement->Clone(); 1576 DBG_ASSERT(pCandidate, "SdrEditView::ImpDismantleOneObject: Could not clone SdrObject (!)"); 1577 pCandidate->SetModel(pCustomShape->GetModel()); 1578 1579 if(((SdrShadowItem&)pCustomShape->GetMergedItem(SDRATTR_SHADOW)).GetValue()) 1580 { 1581 if(pReplacement->ISA(SdrObjGroup)) 1582 { 1583 pCandidate->SetMergedItem(SdrShadowItem(sal_True)); 1584 } 1585 } 1586 1587 SdrInsertReason aReason(SDRREASON_VIEWCALL, pCustomShape); 1588 rOL.InsertObject(pCandidate, rPos, &aReason); 1589 if( bUndo ) 1590 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoNewObject(*pCandidate, true)); 1591 MarkObj(pCandidate, pPV, sal_False, sal_True); 1592 1593 if(pCustomShape->HasText() && !pCustomShape->IsTextPath()) 1594 { 1595 // #i37011# also create a text object and add at rPos + 1 1596 SdrTextObj* pTextObj = (SdrTextObj*)SdrObjFactory::MakeNewObject( 1597 pCustomShape->GetObjInventor(), OBJ_TEXT, 0L, pCustomShape->GetModel()); 1598 1599 // Copy text content 1600 OutlinerParaObject* pParaObj = pCustomShape->GetOutlinerParaObject(); 1601 if(pParaObj) 1602 { 1603 pTextObj->NbcSetOutlinerParaObject(new OutlinerParaObject(*pParaObj)); 1604 } 1605 1606 // copy all attributes 1607 SfxItemSet aTargetItemSet(pCustomShape->GetMergedItemSet()); 1608 1609 // clear fill and line style 1610 aTargetItemSet.Put(XLineStyleItem(XLINE_NONE)); 1611 aTargetItemSet.Put(XFillStyleItem(XFILL_NONE)); 1612 1613 // get the text bounds and set at text object 1614 Rectangle aTextBounds = pCustomShape->GetSnapRect(); 1615 if(pCustomShape->GetTextBounds(aTextBounds)) 1616 { 1617 pTextObj->SetSnapRect(aTextBounds); 1618 } 1619 1620 // if rotated, copy GeoStat, too. 1621 const GeoStat& rSourceGeo = pCustomShape->GetGeoStat(); 1622 if(rSourceGeo.nDrehWink) 1623 { 1624 pTextObj->NbcRotate( 1625 pCustomShape->GetSnapRect().Center(), rSourceGeo.nDrehWink, 1626 rSourceGeo.nSin, rSourceGeo.nCos); 1627 } 1628 1629 // set modified ItemSet at text object 1630 pTextObj->SetMergedItemSet(aTargetItemSet); 1631 1632 // insert object 1633 rOL.InsertObject(pTextObj, rPos + 1, &aReason); 1634 if( bUndo ) 1635 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoNewObject(*pTextObj, true)); 1636 MarkObj(pTextObj, pPV, sal_False, sal_True); 1637 } 1638 } 1639 } 1640 } 1641 } 1642 1643 void SdrEditView::DismantleMarkedObjects(sal_Bool bMakeLines) 1644 { 1645 //sal_uInt32 nCnt(0); 1646 // Temporaere Marklist 1647 SdrMarkList aRemoveMerker; 1648 1649 SortMarkedObjects(); 1650 1651 const bool bUndo = IsUndoEnabled(); 1652 1653 if( bUndo ) 1654 { 1655 // Der Comment wird spaeter zusammengebaut 1656 BegUndo(String(), String(), 1657 bMakeLines ? SDRREPFUNC_OBJ_DISMANTLE_LINES : SDRREPFUNC_OBJ_DISMANTLE_POLYS); 1658 } 1659 1660 sal_uIntPtr nm; 1661 sal_uIntPtr nAnz=GetMarkedObjectCount(); 1662 SdrObjList* pOL0=NULL; 1663 for (nm=nAnz; nm>0;) { 1664 nm--; 1665 SdrMark* pM=GetSdrMarkByIndex(nm); 1666 SdrObject* pObj=pM->GetMarkedSdrObj(); 1667 SdrPageView* pPV=pM->GetPageView(); 1668 SdrObjList* pOL=pObj->GetObjList(); 1669 if (pOL!=pOL0) { pOL0=pOL; pObj->GetOrdNum(); } // sicherstellen, dass OrdNums stimmen! 1670 if (ImpCanDismantle(pObj,bMakeLines)) { 1671 aRemoveMerker.InsertEntry(SdrMark(pObj,pM->GetPageView())); 1672 sal_uIntPtr nPos0=pObj->GetOrdNumDirect(); 1673 sal_uIntPtr nPos=nPos0+1; 1674 SdrObjList* pSubList=pObj->GetSubList(); 1675 if (pSubList!=NULL && !pObj->Is3DObj()) { 1676 SdrObjListIter aIter(*pSubList,IM_DEEPNOGROUPS); 1677 while (aIter.IsMore()) { 1678 const SdrObject* pObj1=aIter.Next(); 1679 ImpDismantleOneObject(pObj1,*pOL,nPos,pPV,bMakeLines); 1680 } 1681 } else { 1682 ImpDismantleOneObject(pObj,*pOL,nPos,pPV,bMakeLines); 1683 } 1684 if( bUndo ) 1685 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoDeleteObject(*pObj,sal_True)); 1686 pOL->RemoveObject(nPos0); 1687 1688 if( !bUndo ) 1689 SdrObject::Free(pObj); 1690 } 1691 } 1692 1693 if( bUndo ) 1694 { 1695 // UndoComment aus den tatsaechlich verwendeten Objekten zusammenbauen 1696 SetUndoComment(ImpGetResStr(bMakeLines?STR_EditDismantle_Lines:STR_EditDismantle_Polys),aRemoveMerker.GetMarkDescription()); 1697 // die tatsaechlich verwendeten Objekten aus der Liste entfernen 1698 EndUndo(); 1699 } 1700 } 1701 1702 //////////////////////////////////////////////////////////////////////////////////////////////////// 1703 // 1704 // #### #### ### # # #### 1705 // # # # # # # # # # 1706 // # ## #### # # # # #### 1707 // # # # # # # # # # 1708 // #### # # ### ### # 1709 // 1710 //////////////////////////////////////////////////////////////////////////////////////////////////// 1711 1712 void SdrEditView::GroupMarked(const SdrObject* pUserGrp) 1713 { 1714 if (AreObjectsMarked()) 1715 { 1716 SortMarkedObjects(); 1717 1718 const bool bUndo = IsUndoEnabled(); 1719 if( bUndo ) 1720 { 1721 BegUndo(ImpGetResStr(STR_EditGroup),GetDescriptionOfMarkedObjects(),SDRREPFUNC_OBJ_GROUP); 1722 1723 const sal_uIntPtr nAnz = GetMarkedObjectCount(); 1724 for(sal_uIntPtr nm = nAnz; nm>0; ) 1725 { 1726 // UndoActions fuer alle betroffenen Objekte anlegen 1727 nm--; 1728 SdrMark* pM=GetSdrMarkByIndex(nm); 1729 SdrObject* pObj = pM->GetMarkedSdrObj(); 1730 std::vector< SdrUndoAction* > vConnectorUndoActions( CreateConnectorUndo( *pObj ) ); 1731 AddUndoActions( vConnectorUndoActions ); 1732 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoRemoveObject( *pObj )); 1733 } 1734 } 1735 1736 SdrMarkList aNewMark; 1737 SdrPageView* pPV = GetSdrPageView(); 1738 1739 if(pPV) 1740 { 1741 SdrObjList* pAktLst=pPV->GetObjList(); 1742 SdrObjList* pSrcLst=pAktLst; 1743 SdrObjList* pSrcLst0=pSrcLst; 1744 SdrPage* pPage=pPV->GetPage(); 1745 // sicherstellen, dass die OrdNums stimmen 1746 if (pSrcLst->IsObjOrdNumsDirty()) 1747 pSrcLst->RecalcObjOrdNums(); 1748 SdrObject* pGrp=NULL; 1749 SdrObject* pRefObj=NULL; // Referenz fuer InsertReason (-> rumankern im Writer) 1750 SdrObject* pRefObj1=NULL; // Referenz fuer InsertReason (-> rumankern im Writer) 1751 SdrObjList* pDstLst=NULL; 1752 // Falls alle markierten Objekte aus Fremden Obj-Listen 1753 // kommen, kommt das Gruppenobjekt an das Ende der Liste. 1754 sal_uIntPtr nInsPos=pSrcLst->GetObjCount(); 1755 sal_Bool bNeedInsPos=sal_True; 1756 for (sal_uIntPtr nm=GetMarkedObjectCount(); nm>0;) 1757 { 1758 nm--; 1759 SdrMark* pM=GetSdrMarkByIndex(nm); 1760 if (pM->GetPageView()==pPV) 1761 { 1762 if (pGrp==NULL) 1763 { 1764 if (pUserGrp!=NULL) 1765 pGrp=pUserGrp->Clone(); 1766 if (pGrp==NULL) 1767 pGrp=new SdrObjGroup; 1768 pDstLst=pGrp->GetSubList(); 1769 DBG_ASSERT(pDstLst!=NULL,"Angebliches Gruppenobjekt liefert keine Objektliste"); 1770 } 1771 SdrObject* pObj=pM->GetMarkedSdrObj(); 1772 pSrcLst=pObj->GetObjList(); 1773 if (pSrcLst!=pSrcLst0) 1774 { 1775 if (pSrcLst->IsObjOrdNumsDirty()) 1776 pSrcLst->RecalcObjOrdNums(); 1777 } 1778 sal_Bool bForeignList=pSrcLst!=pAktLst; 1779 sal_Bool bGrouped=pSrcLst!=pPage; 1780 if (!bForeignList && bNeedInsPos) 1781 { 1782 nInsPos=pObj->GetOrdNum(); // ua, damit sind alle ObjOrdNum der Page gesetzt 1783 nInsPos++; 1784 bNeedInsPos=sal_False; 1785 } 1786 pSrcLst->RemoveObject(pObj->GetOrdNumDirect()); 1787 if (!bForeignList) 1788 nInsPos--; // InsertPos korregieren 1789 SdrInsertReason aReason(SDRREASON_VIEWCALL); 1790 pDstLst->InsertObject(pObj,0,&aReason); 1791 GetMarkedObjectListWriteAccess().DeleteMark(nm); 1792 if (pRefObj1==NULL) 1793 pRefObj1=pObj; // Das oberste sichtbare Objekt 1794 if (!bGrouped) 1795 { 1796 if (pRefObj==NULL) 1797 pRefObj=pObj; // Das oberste sichtbare nicht gruppierte Objekt 1798 } 1799 pSrcLst0=pSrcLst; 1800 } 1801 } 1802 if (pRefObj==NULL) 1803 pRefObj=pRefObj1; 1804 if (pGrp!=NULL) 1805 { 1806 aNewMark.InsertEntry(SdrMark(pGrp,pPV)); 1807 sal_uIntPtr nAnz=pDstLst->GetObjCount(); 1808 SdrInsertReason aReason(SDRREASON_VIEWCALL,pRefObj); 1809 pAktLst->InsertObject(pGrp,nInsPos,&aReason); 1810 if( bUndo ) 1811 { 1812 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoNewObject(*pGrp,true)); // Kein Recalc! 1813 for (sal_uIntPtr no=0; no<nAnz; no++) 1814 { 1815 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoInsertObject(*pDstLst->GetObj(no))); 1816 } 1817 } 1818 } 1819 } 1820 GetMarkedObjectListWriteAccess().Merge(aNewMark); 1821 MarkListHasChanged(); 1822 1823 if( bUndo ) 1824 EndUndo(); 1825 } 1826 } 1827 1828 //////////////////////////////////////////////////////////////////////////////////////////////////// 1829 // 1830 // # # # # #### #### ### # # #### 1831 // # # ## # # # # # # # # # # 1832 // # # # # # # ## #### # # # # #### 1833 // # # # ## # # # # # # # # # 1834 // ### # # #### # # ### ### # 1835 // 1836 //////////////////////////////////////////////////////////////////////////////////////////////////// 1837 1838 void SdrEditView::UnGroupMarked() 1839 { 1840 SdrMarkList aNewMark; 1841 1842 const bool bUndo = IsUndoEnabled(); 1843 if( bUndo ) 1844 BegUndo(String(), String(), SDRREPFUNC_OBJ_UNGROUP); 1845 1846 sal_uIntPtr nCount=0; 1847 XubString aName1; 1848 XubString aName; 1849 sal_Bool bNameOk=sal_False; 1850 for (sal_uIntPtr nm=GetMarkedObjectCount(); nm>0;) { 1851 nm--; 1852 SdrMark* pM=GetSdrMarkByIndex(nm); 1853 SdrObject* pGrp=pM->GetMarkedSdrObj(); 1854 SdrObjList* pSrcLst=pGrp->GetSubList(); 1855 if (pSrcLst!=NULL) { 1856 nCount++; 1857 if (nCount==1) { 1858 pGrp->TakeObjNameSingul(aName); // Bezeichnung der Gruppe holen 1859 pGrp->TakeObjNamePlural(aName1); // Bezeichnung der Gruppe holen 1860 bNameOk=sal_True; 1861 } else { 1862 if (nCount==2) aName=aName1; // Pluralname setzen 1863 if (bNameOk) { 1864 XubString aStr; 1865 pGrp->TakeObjNamePlural(aStr); // Bezeichnung der Gruppe holen 1866 1867 if(!aStr.Equals(aName)) 1868 bNameOk = sal_False; 1869 } 1870 } 1871 sal_uIntPtr nDstCnt=pGrp->GetOrdNum(); 1872 SdrObjList* pDstLst=pM->GetPageView()->GetObjList(); 1873 1874 // FIRST move contained objects to parent of group, so that 1875 // the contained objects are NOT migrated to the UNDO-ItemPool 1876 // when AddUndo(new SdrUndoDelObj(*pGrp)) is called. 1877 sal_uIntPtr nAnz=pSrcLst->GetObjCount(); 1878 sal_uIntPtr no; 1879 1880 if( bUndo ) 1881 { 1882 for (no=nAnz; no>0;) 1883 { 1884 no--; 1885 SdrObject* pObj=pSrcLst->GetObj(no); 1886 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoRemoveObject(*pObj)); 1887 } 1888 } 1889 for (no=0; no<nAnz; no++) 1890 { 1891 SdrObject* pObj=pSrcLst->RemoveObject(0); 1892 SdrInsertReason aReason(SDRREASON_VIEWCALL,pGrp); 1893 pDstLst->InsertObject(pObj,nDstCnt,&aReason); 1894 if( bUndo ) 1895 AddUndo( GetModel()->GetSdrUndoFactory().CreateUndoInsertObject(*pObj,true)); 1896 nDstCnt++; 1897 // Kein SortCheck beim einfuegen in die MarkList, denn das 1898 // wuerde wg. pObj->GetOrdNum() jedesmal ein RecalcOrdNums() 1899 // provozieren: 1900 aNewMark.InsertEntry(SdrMark(pObj,pM->GetPageView()),sal_False); 1901 } 1902 1903 if( bUndo ) 1904 { 1905 // Now it is safe to add the delete-UNDO which trigers the 1906 // MigrateItemPool now only for itself, not for the subobjects. 1907 // nDstCnt is right, because previous inserts move group 1908 // object deeper and increase nDstCnt. 1909 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoDeleteObject(*pGrp)); 1910 } 1911 pDstLst->RemoveObject(nDstCnt); 1912 1913 if( !bUndo ) 1914 SdrObject::Free(pGrp); 1915 1916 GetMarkedObjectListWriteAccess().DeleteMark(nm); 1917 } 1918 } 1919 if (nCount!=0) 1920 { 1921 if (!bNameOk) 1922 aName=ImpGetResStr(STR_ObjNamePluralGRUP); // Oberbegriff Gruppenobjekte verwenden, wenn verschiedene Objekte. 1923 SetUndoComment(ImpGetResStr(STR_EditUngroup),aName); 1924 } 1925 1926 if( bUndo ) 1927 EndUndo(); 1928 1929 if (nCount!=0) 1930 { 1931 GetMarkedObjectListWriteAccess().Merge(aNewMark,sal_True); // Durch das obige Einsortieren ist aNewMark genau verkehrtherum 1932 MarkListHasChanged(); 1933 } 1934 } 1935 1936 //////////////////////////////////////////////////////////////////////////////////////////////////// 1937 // 1938 // ### ### # # # # ##### #### ##### ##### ### #### ### # # # 1939 // # # # # ## # # # # # # # # # # # # # # # # # 1940 // # # # # # # # # #### #### # # # # #### # # # # 1941 // # # # # # ## # # # # # # # # # # # # # # 1942 // ### ### # # # ##### # # # # ### # ### #### # 1943 // 1944 //////////////////////////////////////////////////////////////////////////////////////////////////// 1945 1946 SdrObject* SdrEditView::ImpConvertOneObj(SdrObject* pObj, sal_Bool bPath, sal_Bool bLineToArea) 1947 { 1948 SdrObject* pNewObj = pObj->ConvertToPolyObj(bPath, bLineToArea); 1949 if (pNewObj!=NULL) 1950 { 1951 SdrObjList* pOL=pObj->GetObjList(); 1952 DBG_ASSERT(pOL!=NULL,"ConvertTo: Obj liefert keine ObjList"); 1953 if (pOL!=NULL) 1954 { 1955 const bool bUndo = IsUndoEnabled(); 1956 if( bUndo ) 1957 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoReplaceObject(*pObj,*pNewObj)); 1958 1959 pOL->ReplaceObject(pNewObj,pObj->GetOrdNum()); 1960 1961 if( !bUndo ) 1962 SdrObject::Free(pObj); 1963 } 1964 } 1965 return pNewObj; 1966 } 1967 1968 void SdrEditView::ImpConvertTo(sal_Bool bPath, sal_Bool bLineToArea) 1969 { 1970 sal_Bool bMrkChg=sal_False; 1971 sal_Bool bModChg=sal_False; 1972 if (AreObjectsMarked()) { 1973 sal_uIntPtr nMarkAnz=GetMarkedObjectCount(); 1974 sal_uInt16 nDscrID=0; 1975 if(bLineToArea) 1976 { 1977 if(nMarkAnz == 1) 1978 nDscrID = STR_EditConvToContour; 1979 else 1980 nDscrID = STR_EditConvToContours; 1981 1982 BegUndo(ImpGetResStr(nDscrID), GetDescriptionOfMarkedObjects()); 1983 } 1984 else 1985 { 1986 if (bPath) { 1987 if (nMarkAnz==1) nDscrID=STR_EditConvToCurve; 1988 else nDscrID=STR_EditConvToCurves; 1989 BegUndo(ImpGetResStr(nDscrID),GetDescriptionOfMarkedObjects(),SDRREPFUNC_OBJ_CONVERTTOPATH); 1990 } else { 1991 if (nMarkAnz==1) nDscrID=STR_EditConvToPoly; 1992 else nDscrID=STR_EditConvToPolys; 1993 BegUndo(ImpGetResStr(nDscrID),GetDescriptionOfMarkedObjects(),SDRREPFUNC_OBJ_CONVERTTOPOLY); 1994 } 1995 } 1996 for (sal_uIntPtr nm=nMarkAnz; nm>0;) { 1997 nm--; 1998 SdrMark* pM=GetSdrMarkByIndex(nm); 1999 SdrObject* pObj=pM->GetMarkedSdrObj(); 2000 SdrPageView* pPV=pM->GetPageView(); 2001 if (pObj->IsGroupObject() && !pObj->Is3DObj()) { 2002 SdrObject* pGrp=pObj; 2003 SdrObjListIter aIter(*pGrp,IM_DEEPNOGROUPS); 2004 while (aIter.IsMore()) { 2005 pObj=aIter.Next(); 2006 if (ImpConvertOneObj(pObj,bPath,bLineToArea)) bModChg=sal_True; 2007 } 2008 } else { 2009 SdrObject* pNewObj=ImpConvertOneObj(pObj,bPath,bLineToArea); 2010 if (pNewObj!=NULL) { 2011 bModChg=sal_True; 2012 bMrkChg=sal_True; 2013 GetMarkedObjectListWriteAccess().ReplaceMark(SdrMark(pNewObj,pPV),nm); 2014 } 2015 } 2016 } 2017 EndUndo(); 2018 if (bMrkChg) AdjustMarkHdl(); 2019 if (bMrkChg) MarkListHasChanged(); 2020 } 2021 } 2022 2023 void SdrEditView::ConvertMarkedToPathObj(sal_Bool bLineToArea) 2024 { 2025 ImpConvertTo(sal_True, bLineToArea); 2026 } 2027 2028 void SdrEditView::ConvertMarkedToPolyObj(sal_Bool bLineToArea) 2029 { 2030 ImpConvertTo(sal_False, bLineToArea); 2031 } 2032 2033 //////////////////////////////////////////////////////////////////////////////////////////////////// 2034 // 2035 // # # ##### ##### ### ##### # # ##### # # # #### ### #### ##### 2036 // ## ## # # # # # # # # # ## ## # # # # # # # 2037 // # # # #### # ##### ### # # #### ### # # # # #### # # #### # 2038 // # # # # # # # # # # # # # # # # # # # 2039 // # # ##### # # # # # #### ##### # # # # ### # # # 2040 // 2041 //////////////////////////////////////////////////////////////////////////////////////////////////// 2042 2043 void SdrEditView::DoImportMarkedMtf(SvdProgressInfo *pProgrInfo) 2044 { 2045 const bool bUndo = IsUndoEnabled(); 2046 2047 if( bUndo ) 2048 BegUndo(String(), String(), SDRREPFUNC_OBJ_IMPORTMTF); 2049 2050 SortMarkedObjects(); 2051 SdrMarkList aForTheDescription; 2052 SdrMarkList aNewMarked; 2053 sal_uIntPtr nAnz=GetMarkedObjectCount(); 2054 2055 for (sal_uIntPtr nm=nAnz; nm>0;) 2056 { // Undo Objekte fuer alle neuen Objekte erzeugen 2057 // zwischen den Metafiles auf Abbruch testen 2058 if( pProgrInfo != NULL ) 2059 { 2060 pProgrInfo->SetNextObject(); 2061 if(!pProgrInfo->ReportActions(0)) 2062 break; 2063 } 2064 2065 nm--; 2066 SdrMark* pM=GetSdrMarkByIndex(nm); 2067 SdrObject* pObj=pM->GetMarkedSdrObj(); 2068 SdrPageView* pPV=pM->GetPageView(); 2069 SdrObjList* pOL=pObj->GetObjList(); 2070 sal_uIntPtr nInsPos=pObj->GetOrdNum()+1; 2071 SdrGrafObj* pGraf=PTR_CAST(SdrGrafObj,pObj); 2072 SdrOle2Obj* pOle2=PTR_CAST(SdrOle2Obj,pObj); 2073 sal_uIntPtr nInsAnz=0; 2074 Rectangle aLogicRect; 2075 2076 if (pGraf!=NULL && pGraf->HasGDIMetaFile()) 2077 { 2078 ImpSdrGDIMetaFileImport aFilter(*pMod); 2079 2080 aLogicRect = pGraf->GetLogicRect(); 2081 aFilter.SetScaleRect(aLogicRect); 2082 aFilter.SetLayer(pObj->GetLayer()); 2083 2084 nInsAnz=aFilter.DoImport(pGraf->GetTransformedGraphic( 2085 SDRGRAFOBJ_TRANSFORMATTR_COLOR|SDRGRAFOBJ_TRANSFORMATTR_MIRROR).GetGDIMetaFile(), 2086 *pOL,nInsPos,pProgrInfo); 2087 } 2088 if ( pOle2!=NULL && pOle2->GetGraphic() ) 2089 { 2090 //const GDIMetaFile* pMtf=pOle2->GetGDIMetaFile(); 2091 ImpSdrGDIMetaFileImport aFilter(*pMod); 2092 2093 aLogicRect = pOle2->GetLogicRect(); 2094 aFilter.SetScaleRect(aLogicRect); 2095 aFilter.SetLayer(pObj->GetLayer()); 2096 2097 nInsAnz=aFilter.DoImport(pOle2->GetGraphic()->GetGDIMetaFile(),*pOL,nInsPos,pProgrInfo); 2098 } 2099 if (nInsAnz!=0) 2100 { 2101 // transformation 2102 GeoStat aGeoStat(pGraf ? pGraf->GetGeoStat() : pOle2->GetGeoStat()); 2103 sal_uIntPtr nObj=nInsPos; 2104 2105 if(aGeoStat.nShearWink) 2106 { 2107 aGeoStat.RecalcTan(); 2108 } 2109 2110 if(aGeoStat.nDrehWink) 2111 { 2112 aGeoStat.RecalcSinCos(); 2113 } 2114 2115 for (sal_uIntPtr i=0; i<nInsAnz; i++) 2116 { 2117 if( bUndo ) 2118 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoNewObject(*pOL->GetObj(nObj))); 2119 2120 // Neue MarkList pflegen 2121 SdrObject* pCandidate = pOL->GetObj(nObj); 2122 2123 // apply original transformation 2124 if(aGeoStat.nShearWink) 2125 { 2126 pCandidate->NbcShear(aLogicRect.TopLeft(), aGeoStat.nShearWink, aGeoStat.nTan, false); 2127 } 2128 2129 if(aGeoStat.nDrehWink) 2130 { 2131 pCandidate->NbcRotate(aLogicRect.TopLeft(), aGeoStat.nDrehWink, aGeoStat.nSin, aGeoStat.nCos); 2132 } 2133 2134 SdrMark aNewMark(pCandidate, pPV); 2135 aNewMarked.InsertEntry(aNewMark); 2136 2137 nObj++; 2138 } 2139 aForTheDescription.InsertEntry(*pM); 2140 2141 if( bUndo ) 2142 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoDeleteObject(*pObj)); 2143 2144 // Objekt aus selektion loesen und loeschen 2145 GetMarkedObjectListWriteAccess().DeleteMark(TryToFindMarkedObject(pObj)); 2146 pOL->RemoveObject(nInsPos-1); 2147 2148 if( !bUndo ) 2149 SdrObject::Free(pObj); 2150 } 2151 } 2152 2153 // MarkObj... fehlt... jetzt nicht mehr (AW) 2154 if(aNewMarked.GetMarkCount()) 2155 { 2156 // Neue Selektion bilden 2157 for(sal_uIntPtr a(0); a < aNewMarked.GetMarkCount(); a++) 2158 { 2159 GetMarkedObjectListWriteAccess().InsertEntry(*aNewMarked.GetMark(a)); 2160 } 2161 2162 SortMarkedObjects(); 2163 } 2164 2165 if( bUndo ) 2166 { 2167 SetUndoComment(ImpGetResStr(STR_EditImportMtf),aForTheDescription.GetMarkDescription()); 2168 EndUndo(); 2169 } 2170 } 2171 2172