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_sc.hxx" 26 #include <com/sun/star/uno/Reference.hxx> 27 #include <com/sun/star/chart/XChartDocument.hpp> 28 #include <com/sun/star/embed/XEmbeddedObject.hpp> 29 #include <com/sun/star/embed/XVisualObject.hpp> 30 #include <com/sun/star/embed/XClassifiedObject.hpp> 31 #include <com/sun/star/embed/XComponentSupplier.hpp> 32 #include <com/sun/star/embed/EmbedStates.hpp> 33 #include <com/sun/star/embed/ElementModes.hpp> 34 #include <com/sun/star/embed/NoVisualAreaSizeException.hpp> 35 #include <com/sun/star/datatransfer/XTransferable.hpp> 36 37 // INCLUDE --------------------------------------------------------------- 38 39 #include "scitems.hxx" 40 #include <editeng/eeitem.hxx> 41 #include <editeng/frmdiritem.hxx> 42 #include <sot/exchange.hxx> 43 #include <svx/objfac3d.hxx> 44 #include <svx/xtable.hxx> 45 #include <svx/svdoutl.hxx> 46 #include <svx/svditer.hxx> 47 #include <svx/svdocapt.hxx> 48 #include <svx/svdocirc.hxx> 49 #include <svx/svdoedge.hxx> 50 #include <svx/svdograf.hxx> 51 #include <svx/svdoole2.hxx> 52 #include <svx/svdundo.hxx> 53 #include <editeng/unolingu.hxx> 54 #include <svx/drawitem.hxx> 55 #include <editeng/fhgtitem.hxx> 56 #include <editeng/scriptspaceitem.hxx> 57 #include <svx/shapepropertynotifier.hxx> 58 #include <sfx2/viewsh.hxx> 59 #include <sfx2/docfile.hxx> 60 #include <sot/storage.hxx> 61 #include <unotools/pathoptions.hxx> 62 #include <svl/itempool.hxx> 63 #include <vcl/virdev.hxx> 64 #include <vcl/svapp.hxx> 65 #include <unotools/ucbstreamhelper.hxx> 66 67 #include "drwlayer.hxx" 68 #include "drawpage.hxx" 69 #include "global.hxx" 70 #include "document.hxx" 71 #include "rechead.hxx" 72 #include "userdat.hxx" 73 #include "markdata.hxx" 74 #include "globstr.hrc" 75 #include "scmod.hxx" 76 #include "chartarr.hxx" 77 #include "postit.hxx" 78 #include "attrib.hxx" 79 #include "charthelper.hxx" 80 81 #define DET_ARROW_OFFSET 1000 82 83 // Abstand zur naechsten Zelle beim Loeschen (bShrink), damit der Anker 84 // immer an der richtigen Zelle angezeigt wird 85 //#define SHRINK_DIST 3 86 // und noch etwas mehr, damit das Objekt auch sichtbar in der Zelle liegt 87 #define SHRINK_DIST 25 88 89 #define SHRINK_DIST_TWIPS 15 90 91 using namespace ::com::sun::star; 92 93 // STATIC DATA ----------------------------------------------------------- 94 95 TYPEINIT1(ScTabDeletedHint, SfxHint); 96 TYPEINIT1(ScTabSizeChangedHint, SfxHint); 97 98 static ScDrawObjFactory* pFac = NULL; 99 static E3dObjFactory* pF3d = NULL; 100 static sal_uInt16 nInst = 0; 101 102 SfxObjectShell* ScDrawLayer::pGlobalDrawPersist = NULL; 103 //REMOVE SvPersist* ScDrawLayer::pGlobalDrawPersist = NULL; 104 105 sal_Bool bDrawIsInUndo = sal_False; //! Member 106 107 // ----------------------------------------------------------------------- 108 109 ScUndoObjData::ScUndoObjData( SdrObject* pObjP, const ScAddress& rOS, const ScAddress& rOE, 110 const ScAddress& rNS, const ScAddress& rNE ) : 111 SdrUndoObj( *pObjP ), 112 aOldStt( rOS ), 113 aOldEnd( rOE ), 114 aNewStt( rNS ), 115 aNewEnd( rNE ) 116 { 117 } 118 119 __EXPORT ScUndoObjData::~ScUndoObjData() 120 { 121 } 122 123 void ScUndoObjData::Undo() 124 { 125 ScDrawObjData* pData = ScDrawLayer::GetObjData( pObj ); 126 DBG_ASSERT(pData,"ScUndoObjData: Daten nicht da"); 127 if (pData) 128 { 129 pData->maStart = aOldStt; 130 pData->maEnd = aOldEnd; 131 } 132 } 133 134 void __EXPORT ScUndoObjData::Redo() 135 { 136 ScDrawObjData* pData = ScDrawLayer::GetObjData( pObj ); 137 DBG_ASSERT(pData,"ScUndoObjData: Daten nicht da"); 138 if (pData) 139 { 140 pData->maStart = aNewStt; 141 pData->maEnd = aNewEnd; 142 } 143 } 144 145 // ----------------------------------------------------------------------- 146 147 ScTabDeletedHint::ScTabDeletedHint( SCTAB nTabNo ) : 148 nTab( nTabNo ) 149 { 150 } 151 152 __EXPORT ScTabDeletedHint::~ScTabDeletedHint() 153 { 154 } 155 156 ScTabSizeChangedHint::ScTabSizeChangedHint( SCTAB nTabNo ) : 157 nTab( nTabNo ) 158 { 159 } 160 161 __EXPORT ScTabSizeChangedHint::~ScTabSizeChangedHint() 162 { 163 } 164 165 // ----------------------------------------------------------------------- 166 167 #define MAXMM 10000000 168 169 inline void TwipsToMM( long& nVal ) 170 { 171 nVal = (long) ( nVal * HMM_PER_TWIPS ); 172 } 173 174 inline void ReverseTwipsToMM( long& nVal ) 175 { 176 // reverse the effect of TwipsToMM - round up here (add 1) 177 178 nVal = ((long) ( nVal / HMM_PER_TWIPS )) + 1; 179 } 180 181 void lcl_TwipsToMM( Point& rPoint ) 182 { 183 TwipsToMM( rPoint.X() ); 184 TwipsToMM( rPoint.Y() ); 185 } 186 187 void lcl_ReverseTwipsToMM( Point& rPoint ) 188 { 189 ReverseTwipsToMM( rPoint.X() ); 190 ReverseTwipsToMM( rPoint.Y() ); 191 } 192 193 void lcl_ReverseTwipsToMM( Rectangle& rRect ) 194 { 195 ReverseTwipsToMM( rRect.Left() ); 196 ReverseTwipsToMM( rRect.Right() ); 197 ReverseTwipsToMM( rRect.Top() ); 198 ReverseTwipsToMM( rRect.Bottom() ); 199 } 200 201 // ----------------------------------------------------------------------- 202 203 204 ScDrawLayer::ScDrawLayer( ScDocument* pDocument, const String& rName ) : 205 FmFormModel( SvtPathOptions().GetPalettePath(), 206 NULL, // SfxItemPool* Pool 207 pGlobalDrawPersist ? 208 pGlobalDrawPersist : 209 ( pDocument ? pDocument->GetDocumentShell() : NULL )), 210 aName( rName ), 211 pDoc( pDocument ), 212 pUndoGroup( NULL ), 213 bRecording( sal_False ), 214 bAdjustEnabled( sal_True ), 215 bHyphenatorSet( sal_False ), 216 mbUndoAllowed( sal_True ) 217 { 218 pGlobalDrawPersist = NULL; // nur einmal benutzen 219 220 SfxObjectShell* pObjSh = pDocument ? pDocument->GetDocumentShell() : NULL; 221 if ( pObjSh ) 222 { 223 SetObjectShell( pObjSh ); 224 225 // set color table 226 const SvxColorTableItem* pColItem = static_cast< const SvxColorTableItem* >(pObjSh->GetItem( SID_COLOR_TABLE )); 227 XColorListSharedPtr aXCol = pColItem ? pColItem->GetColorTable() : XColorList::GetStdColorList(); 228 SetColorTableAtSdrModel( aXCol ); 229 } 230 else 231 SetColorTableAtSdrModel( XColorList::GetStdColorList() ); 232 233 SetSwapGraphics(sal_True); 234 // SetSwapAsynchron(sal_True); // an der View 235 236 SetScaleUnit(MAP_100TH_MM); 237 SfxItemPool& rPool = GetItemPool(); 238 rPool.SetDefaultMetric(SFX_MAPUNIT_100TH_MM); 239 SvxFrameDirectionItem aModeItem( FRMDIR_ENVIRONMENT, EE_PARA_WRITINGDIR ); 240 rPool.SetPoolDefaultItem( aModeItem ); 241 242 // #i33700# 243 // Set shadow distance defaults as PoolDefaultItems. Details see bug. 244 rPool.SetPoolDefaultItem(SdrShadowXDistItem(300)); 245 rPool.SetPoolDefaultItem(SdrShadowYDistItem(300)); 246 247 // #111216# default for script spacing depends on locale, see SdDrawDocument ctor in sd 248 LanguageType eOfficeLanguage = Application::GetSettings().GetLanguage(); 249 if ( eOfficeLanguage == LANGUAGE_KOREAN || eOfficeLanguage == LANGUAGE_KOREAN_JOHAB || 250 eOfficeLanguage == LANGUAGE_JAPANESE ) 251 { 252 // secondary is edit engine pool 253 rPool.GetSecondaryPool()->SetPoolDefaultItem( SvxScriptSpaceItem( sal_False, EE_PARA_ASIANCJKSPACING ) ); 254 } 255 256 rPool.FreezeIdRanges(); // the pool is also used directly 257 258 SdrLayerAdmin& rAdmin = GetLayerAdmin(); 259 rAdmin.NewLayer(String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("vorne")), SC_LAYER_FRONT); 260 rAdmin.NewLayer(String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("hinten")), SC_LAYER_BACK); 261 rAdmin.NewLayer(String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("intern")), SC_LAYER_INTERN); 262 rAdmin.NewLayer(String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("Controls")), SC_LAYER_CONTROLS); 263 rAdmin.NewLayer(String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("hidden")), SC_LAYER_HIDDEN); 264 // "Controls" is new - must also be created when loading 265 266 // Link fuer URL-Fields setzen 267 ScModule* pScMod = SC_MOD(); 268 Outliner& rOutliner = GetDrawOutliner(); 269 rOutliner.SetCalcFieldValueHdl( LINK( pScMod, ScModule, CalcFieldValueHdl ) ); 270 271 Outliner& rHitOutliner = GetHitTestOutliner(); 272 rHitOutliner.SetCalcFieldValueHdl( LINK( pScMod, ScModule, CalcFieldValueHdl ) ); 273 274 // #95129# SJ: set FontHeight pool defaults without changing static SdrEngineDefaults 275 SfxItemPool* pOutlinerPool = rOutliner.GetEditTextObjectPool(); 276 if ( pOutlinerPool ) 277 pItemPool->SetPoolDefaultItem(SvxFontHeightItem( 423, 100, EE_CHAR_FONTHEIGHT )); // 12Pt 278 SfxItemPool* pHitOutlinerPool = rHitOutliner.GetEditTextObjectPool(); 279 if ( pHitOutlinerPool ) 280 pHitOutlinerPool->SetPoolDefaultItem(SvxFontHeightItem( 423, 100, EE_CHAR_FONTHEIGHT )); // 12Pt 281 282 // initial undo mode as in Calc document 283 if( pDoc ) 284 EnableUndo( pDoc->IsUndoEnabled() ); 285 286 // URL-Buttons haben keinen Handler mehr, machen alles selber 287 288 if( !nInst++ ) 289 { 290 pFac = new ScDrawObjFactory; 291 pF3d = new E3dObjFactory; 292 } 293 } 294 295 __EXPORT ScDrawLayer::~ScDrawLayer() 296 { 297 Broadcast(SdrHint(HINT_MODELCLEARED)); 298 299 // #116168# 300 //Clear(); 301 ClearModel(sal_True); 302 303 delete pUndoGroup; 304 if( !--nInst ) 305 { 306 delete pFac, pFac = NULL; 307 delete pF3d, pF3d = NULL; 308 } 309 } 310 311 void ScDrawLayer::UseHyphenator() 312 { 313 if (!bHyphenatorSet) 314 { 315 com::sun::star::uno::Reference< com::sun::star::linguistic2::XHyphenator > 316 xHyphenator = LinguMgr::GetHyphenator(); 317 318 GetDrawOutliner().SetHyphenator( xHyphenator ); 319 GetHitTestOutliner().SetHyphenator( xHyphenator ); 320 321 bHyphenatorSet = sal_True; 322 } 323 } 324 325 SdrPage* __EXPORT ScDrawLayer::AllocPage(FASTBOOL bMasterPage) 326 { 327 // don't create basic until it is needed 328 StarBASIC* pBasic = NULL; 329 ScDrawPage* pPage = new ScDrawPage( *this, pBasic, sal::static_int_cast<sal_Bool>(bMasterPage) ); 330 return pPage; 331 } 332 333 sal_Bool ScDrawLayer::HasObjects() const 334 { 335 sal_Bool bFound = sal_False; 336 337 sal_uInt16 nCount = GetPageCount(); 338 for (sal_uInt16 i=0; i<nCount && !bFound; i++) 339 if (GetPage(i)->GetObjCount()) 340 bFound = sal_True; 341 342 return bFound; 343 } 344 345 void ScDrawLayer::UpdateBasic() 346 { 347 // don't create basic until it is needed 348 //! remove this method? 349 } 350 351 SdrModel* __EXPORT ScDrawLayer::AllocModel() const 352 { 353 // #103849# Allocated model (for clipboard etc) must not have a pointer 354 // to the original model's document, pass NULL as document: 355 356 return new ScDrawLayer( NULL, aName ); 357 } 358 359 Window* __EXPORT ScDrawLayer::GetCurDocViewWin() 360 { 361 DBG_ASSERT( pDoc, "ScDrawLayer::GetCurDocViewWin without document" ); 362 if ( !pDoc ) 363 return NULL; 364 365 SfxViewShell* pViewSh = SfxViewShell::Current(); 366 SfxObjectShell* pObjSh = pDoc->GetDocumentShell(); 367 368 if (pViewSh && pViewSh->GetObjectShell() == pObjSh) 369 return pViewSh->GetWindow(); 370 371 return NULL; 372 } 373 374 sal_Bool ScDrawLayer::ScAddPage( SCTAB nTab ) 375 { 376 if (bDrawIsInUndo) 377 return sal_False; // not inserted 378 379 ScDrawPage* pPage = (ScDrawPage*)AllocPage( sal_False ); 380 InsertPage(pPage, static_cast<sal_uInt16>(nTab)); 381 if (bRecording) 382 AddCalcUndo< SdrUndoNewPage >(*pPage); 383 384 return sal_True; // inserted 385 } 386 387 void ScDrawLayer::ScRemovePage( SCTAB nTab ) 388 { 389 if (bDrawIsInUndo) 390 return; 391 392 Broadcast( ScTabDeletedHint( nTab ) ); 393 if (bRecording) 394 { 395 SdrPage* pPage = GetPage(static_cast<sal_uInt16>(nTab)); 396 AddCalcUndo< SdrUndoDelPage >(*pPage); // Undo-Action wird Owner der Page 397 RemovePage( static_cast<sal_uInt16>(nTab) ); // nur austragen, nicht loeschen 398 } 399 else 400 DeletePage( static_cast<sal_uInt16>(nTab) ); // einfach weg damit 401 } 402 403 void ScDrawLayer::ScRenamePage( SCTAB nTab, const String& rNewName ) 404 { 405 ScDrawPage* pPage = (ScDrawPage*) GetPage(static_cast<sal_uInt16>(nTab)); 406 if (pPage) 407 pPage->SetName(rNewName); 408 } 409 410 void ScDrawLayer::ScMovePage( sal_uInt16 nOldPos, sal_uInt16 nNewPos ) 411 { 412 MovePage( nOldPos, nNewPos ); 413 } 414 415 void ScDrawLayer::ScCopyPage( sal_uInt16 nOldPos, sal_uInt16 nNewPos, sal_Bool bAlloc ) 416 { 417 //! remove argument bAlloc (always sal_False) 418 419 if (bDrawIsInUndo) 420 return; 421 422 SdrPage* pOldPage = GetPage(nOldPos); 423 SdrPage* pNewPage = bAlloc ? AllocPage(sal_False) : GetPage(nNewPos); 424 425 // kopieren 426 427 if (pOldPage && pNewPage) 428 { 429 SdrObjListIter aIter( *pOldPage, IM_FLAT ); 430 SdrObject* pOldObject = aIter.Next(); 431 while (pOldObject) 432 { 433 // #i112034# do not copy internal objects (detective) and note captions 434 if ( pOldObject->GetLayer() != SC_LAYER_INTERN && !IsNoteCaption( pOldObject ) ) 435 { 436 // #116235# 437 SdrObject* pNewObject = pOldObject->Clone(); 438 //SdrObject* pNewObject = pOldObject->Clone( pNewPage, this ); 439 pNewObject->SetModel(this); 440 pNewObject->SetPage(pNewPage); 441 442 pNewObject->NbcMove(Size(0,0)); 443 pNewPage->InsertObject( pNewObject ); 444 if (bRecording) 445 AddCalcUndo< SdrUndoInsertObj >( *pNewObject ); 446 } 447 448 pOldObject = aIter.Next(); 449 } 450 } 451 452 if (bAlloc) 453 InsertPage(pNewPage, nNewPos); 454 } 455 456 inline sal_Bool IsInBlock( const ScAddress& rPos, SCCOL nCol1,SCROW nRow1, SCCOL nCol2,SCROW nRow2 ) 457 { 458 return rPos.Col() >= nCol1 && rPos.Col() <= nCol2 && 459 rPos.Row() >= nRow1 && rPos.Row() <= nRow2; 460 } 461 462 void ScDrawLayer::MoveCells( SCTAB nTab, SCCOL nCol1,SCROW nRow1, SCCOL nCol2,SCROW nRow2, 463 SCsCOL nDx,SCsROW nDy, bool bUpdateNoteCaptionPos ) 464 { 465 SdrPage* pPage = GetPage(static_cast<sal_uInt16>(nTab)); 466 DBG_ASSERT(pPage,"Page nicht gefunden"); 467 if (!pPage) 468 return; 469 470 sal_Bool bNegativePage = pDoc && pDoc->IsNegativePage( nTab ); 471 472 sal_uLong nCount = pPage->GetObjCount(); 473 for ( sal_uLong i = 0; i < nCount; i++ ) 474 { 475 SdrObject* pObj = pPage->GetObj( i ); 476 ScDrawObjData* pData = GetObjDataTab( pObj, nTab ); 477 if( pData ) 478 { 479 const ScAddress aOldStt = pData->maStart; 480 const ScAddress aOldEnd = pData->maEnd; 481 sal_Bool bChange = sal_False; 482 if ( aOldStt.IsValid() && IsInBlock( aOldStt, nCol1,nRow1, nCol2,nRow2 ) ) 483 { 484 pData->maStart.IncCol( nDx ); 485 pData->maStart.IncRow( nDy ); 486 bChange = sal_True; 487 } 488 if ( aOldEnd.IsValid() && IsInBlock( aOldEnd, nCol1,nRow1, nCol2,nRow2 ) ) 489 { 490 pData->maEnd.IncCol( nDx ); 491 pData->maEnd.IncRow( nDy ); 492 bChange = sal_True; 493 } 494 if (bChange) 495 { 496 if ( pObj->ISA( SdrRectObj ) && pData->maStart.IsValid() && pData->maEnd.IsValid() ) 497 pData->maStart.PutInOrder( pData->maEnd ); 498 AddCalcUndo< ScUndoObjData >( pObj, aOldStt, aOldEnd, pData->maStart, pData->maEnd ); 499 RecalcPos( pObj, *pData, bNegativePage, bUpdateNoteCaptionPos ); 500 } 501 } 502 } 503 } 504 505 void ScDrawLayer::SetPageSize( sal_uInt16 nPageNo, const Size& rSize, bool bUpdateNoteCaptionPos ) 506 { 507 SdrPage* pPage = GetPage(nPageNo); 508 if (pPage) 509 { 510 if ( rSize != pPage->GetSize() ) 511 { 512 pPage->SetSize( rSize ); 513 Broadcast( ScTabSizeChangedHint( static_cast<SCTAB>(nPageNo) ) ); // SetWorkArea() an den Views 514 } 515 516 // Detektivlinien umsetzen (an neue Hoehen/Breiten anpassen) 517 // auch wenn Groesse gleich geblieben ist 518 // (einzelne Zeilen/Spalten koennen geaendert sein) 519 520 sal_Bool bNegativePage = pDoc && pDoc->IsNegativePage( static_cast<SCTAB>(nPageNo) ); 521 522 sal_uLong nCount = pPage->GetObjCount(); 523 for ( sal_uLong i = 0; i < nCount; i++ ) 524 { 525 SdrObject* pObj = pPage->GetObj( i ); 526 ScDrawObjData* pData = GetObjDataTab( pObj, static_cast<SCTAB>(nPageNo) ); 527 if( pData ) 528 RecalcPos( pObj, *pData, bNegativePage, bUpdateNoteCaptionPos ); 529 } 530 } 531 } 532 533 void ScDrawLayer::RecalcPos( SdrObject* pObj, const ScDrawObjData& rData, bool bNegativePage, bool bUpdateNoteCaptionPos ) 534 { 535 DBG_ASSERT( pDoc, "ScDrawLayer::RecalcPos - missing document" ); 536 if( !pDoc ) 537 return; 538 539 if( rData.mbNote ) 540 { 541 DBG_ASSERT( rData.maStart.IsValid(), "ScDrawLayer::RecalcPos - invalid position for cell note" ); 542 /* #i109372# On insert/remove rows/columns/cells: Updating the caption 543 position must not be done, if the cell containing the note has not 544 been moved yet in the document. The calling code now passes an 545 additional boolean stating if the cells are already moved. */ 546 if( bUpdateNoteCaptionPos ) 547 /* When inside an undo action, there may be pending note captions 548 where cell note is already deleted (thus document cannot find 549 the note object anymore). The caption will be deleted later 550 with drawing undo. */ 551 if( ScPostIt* pNote = pDoc->GetNote( rData.maStart ) ) 552 pNote->UpdateCaptionPos( rData.maStart ); 553 return; 554 } 555 556 bool bValid1 = rData.maStart.IsValid(); 557 SCCOL nCol1 = rData.maStart.Col(); 558 SCROW nRow1 = rData.maStart.Row(); 559 SCTAB nTab1 = rData.maStart.Tab(); 560 bool bValid2 = rData.maEnd.IsValid(); 561 SCCOL nCol2 = rData.maEnd.Col(); 562 SCROW nRow2 = rData.maEnd.Row(); 563 SCTAB nTab2 = rData.maEnd.Tab(); 564 565 // validation circle 566 bool bCircle = pObj->ISA( SdrCircObj ); 567 // detective arrow 568 bool bArrow = pObj->IsPolyObj() && (pObj->GetPointCount() == 2); 569 570 if( bCircle ) 571 { 572 Point aPos( pDoc->GetColOffset( nCol1, nTab1 ), pDoc->GetRowOffset( nRow1, nTab1 ) ); 573 TwipsToMM( aPos.X() ); 574 TwipsToMM( aPos.Y() ); 575 576 // Berechnung und Werte wie in detfunc.cxx 577 578 Size aSize( (long)(pDoc->GetColWidth( nCol1, nTab1 ) * HMM_PER_TWIPS), 579 (long)(pDoc->GetRowHeight( nRow1, nTab1 ) * HMM_PER_TWIPS) ); 580 Rectangle aRect( aPos, aSize ); 581 aRect.Left() -= 250; 582 aRect.Right() += 250; 583 aRect.Top() -= 70; 584 aRect.Bottom() += 70; 585 if ( bNegativePage ) 586 MirrorRectRTL( aRect ); 587 588 if ( pObj->GetLogicRect() != aRect ) 589 { 590 if (bRecording) 591 AddCalcUndo<SdrUndoGeoObj>( *pObj ); 592 pObj->SetLogicRect(aRect); 593 } 594 } 595 else if( bArrow ) 596 { 597 //! nicht mehrere Undos fuer ein Objekt erzeugen (hinteres kann dann weggelassen werden) 598 599 SCCOL nLastCol; 600 SCROW nLastRow; 601 if( bValid1 ) 602 { 603 Point aPos( pDoc->GetColOffset( nCol1, nTab1 ), pDoc->GetRowOffset( nRow1, nTab1 ) ); 604 if (!pDoc->ColHidden(nCol1, nTab1, nLastCol)) 605 aPos.X() += pDoc->GetColWidth( nCol1, nTab1 ) / 4; 606 if (!pDoc->RowHidden(nRow1, nTab1, nLastRow)) 607 aPos.Y() += pDoc->GetRowHeight( nRow1, nTab1 ) / 2; 608 TwipsToMM( aPos.X() ); 609 TwipsToMM( aPos.Y() ); 610 Point aStartPos = aPos; 611 if ( bNegativePage ) 612 aStartPos.X() = -aStartPos.X(); // don't modify aPos - used below 613 if ( pObj->GetPoint( 0 ) != aStartPos ) 614 { 615 if (bRecording) 616 AddCalcUndo< SdrUndoGeoObj> ( *pObj ); 617 pObj->SetPoint( aStartPos, 0 ); 618 } 619 620 if( !bValid2 ) 621 { 622 Point aEndPos( aPos.X() + DET_ARROW_OFFSET, aPos.Y() - DET_ARROW_OFFSET ); 623 if (aEndPos.Y() < 0) 624 aEndPos.Y() += (2 * DET_ARROW_OFFSET); 625 if ( bNegativePage ) 626 aEndPos.X() = -aEndPos.X(); 627 if ( pObj->GetPoint( 1 ) != aEndPos ) 628 { 629 if (bRecording) 630 AddCalcUndo< SdrUndoGeoObj >( *pObj ); 631 pObj->SetPoint( aEndPos, 1 ); 632 } 633 } 634 } 635 if( bValid2 ) 636 { 637 Point aPos( pDoc->GetColOffset( nCol2, nTab2 ), pDoc->GetRowOffset( nRow2, nTab2 ) ); 638 if (!pDoc->ColHidden(nCol2, nTab2, nLastCol)) 639 aPos.X() += pDoc->GetColWidth( nCol2, nTab2 ) / 4; 640 if (!pDoc->RowHidden(nRow2, nTab2, nLastRow)) 641 aPos.Y() += pDoc->GetRowHeight( nRow2, nTab2 ) / 2; 642 TwipsToMM( aPos.X() ); 643 TwipsToMM( aPos.Y() ); 644 Point aEndPos = aPos; 645 if ( bNegativePage ) 646 aEndPos.X() = -aEndPos.X(); // don't modify aPos - used below 647 if ( pObj->GetPoint( 1 ) != aEndPos ) 648 { 649 if (bRecording) 650 AddCalcUndo< SdrUndoGeoObj> ( *pObj ); 651 pObj->SetPoint( aEndPos, 1 ); 652 } 653 654 if( !bValid1 ) 655 { 656 Point aStartPos( aPos.X() - DET_ARROW_OFFSET, aPos.Y() - DET_ARROW_OFFSET ); 657 if (aStartPos.X() < 0) 658 aStartPos.X() += (2 * DET_ARROW_OFFSET); 659 if (aStartPos.Y() < 0) 660 aStartPos.Y() += (2 * DET_ARROW_OFFSET); 661 if ( bNegativePage ) 662 aStartPos.X() = -aStartPos.X(); 663 if ( pObj->GetPoint( 0 ) != aStartPos ) 664 { 665 if (bRecording) 666 AddCalcUndo< SdrUndoGeoObj >( *pObj ); 667 pObj->SetPoint( aStartPos, 0 ); 668 } 669 } 670 } 671 } 672 else // Referenz-Rahmen 673 { 674 DBG_ASSERT( bValid1, "ScDrawLayer::RecalcPos - invalid start position" ); 675 Point aPos( pDoc->GetColOffset( nCol1, nTab1 ), pDoc->GetRowOffset( nRow1, nTab1 ) ); 676 TwipsToMM( aPos.X() ); 677 TwipsToMM( aPos.Y() ); 678 679 if( bValid2 ) 680 { 681 Point aEnd( pDoc->GetColOffset( nCol2 + 1, nTab2 ), pDoc->GetRowOffset( nRow2 + 1, nTab2 ) ); 682 TwipsToMM( aEnd.X() ); 683 TwipsToMM( aEnd.Y() ); 684 685 Rectangle aNew( aPos, aEnd ); 686 if ( bNegativePage ) 687 MirrorRectRTL( aNew ); 688 if ( pObj->GetLogicRect() != aNew ) 689 { 690 if (bRecording) 691 AddCalcUndo< SdrUndoGeoObj >( *pObj ); 692 pObj->SetLogicRect(aNew); 693 } 694 } 695 else 696 { 697 if ( bNegativePage ) 698 aPos.X() = -aPos.X(); 699 if ( pObj->GetRelativePos() != aPos ) 700 { 701 if (bRecording) 702 AddCalcUndo< SdrUndoGeoObj >( *pObj ); 703 pObj->SetRelativePos( aPos ); 704 } 705 } 706 } 707 } 708 709 sal_Bool ScDrawLayer::GetPrintArea( ScRange& rRange, sal_Bool bSetHor, sal_Bool bSetVer ) const 710 { 711 DBG_ASSERT( pDoc, "ScDrawLayer::GetPrintArea without document" ); 712 if ( !pDoc ) 713 return sal_False; 714 715 SCTAB nTab = rRange.aStart.Tab(); 716 DBG_ASSERT( rRange.aEnd.Tab() == nTab, "GetPrintArea: Tab unterschiedlich" ); 717 718 sal_Bool bNegativePage = pDoc->IsNegativePage( nTab ); 719 720 sal_Bool bAny = sal_False; 721 long nEndX = 0; 722 long nEndY = 0; 723 long nStartX = LONG_MAX; 724 long nStartY = LONG_MAX; 725 726 // Grenzen ausrechnen 727 728 if (!bSetHor) 729 { 730 nStartX = 0; 731 SCCOL nStartCol = rRange.aStart.Col(); 732 SCCOL i; 733 for (i=0; i<nStartCol; i++) 734 nStartX +=pDoc->GetColWidth(i,nTab); 735 nEndX = nStartX; 736 SCCOL nEndCol = rRange.aEnd.Col(); 737 for (i=nStartCol; i<=nEndCol; i++) 738 nEndX += pDoc->GetColWidth(i,nTab); 739 nStartX = (long)(nStartX * HMM_PER_TWIPS); 740 nEndX = (long)(nEndX * HMM_PER_TWIPS); 741 } 742 if (!bSetVer) 743 { 744 nStartY = pDoc->GetRowHeight( 0, rRange.aStart.Row()-1, nTab); 745 nEndY = nStartY + pDoc->GetRowHeight( rRange.aStart.Row(), 746 rRange.aEnd.Row(), nTab); 747 nStartY = (long)(nStartY * HMM_PER_TWIPS); 748 nEndY = (long)(nEndY * HMM_PER_TWIPS); 749 } 750 751 if ( bNegativePage ) 752 { 753 nStartX = -nStartX; // positions are negative, swap start/end so the same comparisons work 754 nEndX = -nEndX; 755 ::std::swap( nStartX, nEndX ); 756 } 757 758 const SdrPage* pPage = GetPage(static_cast<sal_uInt16>(nTab)); 759 DBG_ASSERT(pPage,"Page nicht gefunden"); 760 if (pPage) 761 { 762 SdrObjListIter aIter( *pPage, IM_FLAT ); 763 SdrObject* pObject = aIter.Next(); 764 while (pObject) 765 { 766 //! Flags (ausgeblendet?) testen 767 768 Rectangle aObjRect = pObject->GetCurrentBoundRect(); 769 sal_Bool bFit = sal_True; 770 if ( !bSetHor && ( aObjRect.Right() < nStartX || aObjRect.Left() > nEndX ) ) 771 bFit = sal_False; 772 if ( !bSetVer && ( aObjRect.Bottom() < nStartY || aObjRect.Top() > nEndY ) ) 773 bFit = sal_False; 774 // #i104716# don't include hidden note objects 775 if ( bFit && pObject->GetLayer() != SC_LAYER_HIDDEN ) 776 { 777 if (bSetHor) 778 { 779 if (aObjRect.Left() < nStartX) nStartX = aObjRect.Left(); 780 if (aObjRect.Right() > nEndX) nEndX = aObjRect.Right(); 781 } 782 if (bSetVer) 783 { 784 if (aObjRect.Top() < nStartY) nStartY = aObjRect.Top(); 785 if (aObjRect.Bottom() > nEndY) nEndY = aObjRect.Bottom(); 786 } 787 bAny = sal_True; 788 } 789 790 pObject = aIter.Next(); 791 } 792 } 793 794 if ( bNegativePage ) 795 { 796 nStartX = -nStartX; // reverse transformation, so the same cell address calculation works 797 nEndX = -nEndX; 798 ::std::swap( nStartX, nEndX ); 799 } 800 801 if (bAny) 802 { 803 DBG_ASSERT( nStartX<=nEndX && nStartY<=nEndY, "Start/End falsch in ScDrawLayer::GetPrintArea" ); 804 805 if (bSetHor) 806 { 807 nStartX = (long) (nStartX / HMM_PER_TWIPS); 808 nEndX = (long) (nEndX / HMM_PER_TWIPS); 809 long nWidth; 810 SCCOL i; 811 812 nWidth = 0; 813 for (i=0; i<=MAXCOL && nWidth<=nStartX; i++) 814 nWidth += pDoc->GetColWidth(i,nTab); 815 rRange.aStart.SetCol( i>0 ? (i-1) : 0 ); 816 817 nWidth = 0; 818 for (i=0; i<=MAXCOL && nWidth<=nEndX; i++) //! bei Start anfangen 819 nWidth += pDoc->GetColWidth(i,nTab); 820 rRange.aEnd.SetCol( i>0 ? (i-1) : 0 ); 821 } 822 823 if (bSetVer) 824 { 825 nStartY = (long) (nStartY / HMM_PER_TWIPS); 826 nEndY = (long) (nEndY / HMM_PER_TWIPS); 827 SCROW nRow = pDoc->GetRowForHeight( nTab, nStartY); 828 rRange.aStart.SetRow( nRow>0 ? (nRow-1) : 0); 829 nRow = pDoc->GetRowForHeight( nTab, nEndY); 830 rRange.aEnd.SetRow( nRow == MAXROW ? MAXROW : 831 (nRow>0 ? (nRow-1) : 0)); 832 } 833 } 834 else 835 { 836 if (bSetHor) 837 { 838 rRange.aStart.SetCol(0); 839 rRange.aEnd.SetCol(0); 840 } 841 if (bSetVer) 842 { 843 rRange.aStart.SetRow(0); 844 rRange.aEnd.SetRow(0); 845 } 846 } 847 return bAny; 848 } 849 850 void ScDrawLayer::AddCalcUndo( SdrUndoAction* pUndo ) 851 { 852 if (bRecording) 853 { 854 if (!pUndoGroup) 855 pUndoGroup = new SdrUndoGroup(*this); 856 857 pUndoGroup->AddAction( pUndo ); 858 } 859 else 860 delete pUndo; 861 } 862 863 void ScDrawLayer::BeginCalcUndo(bool bDisableTextEditUsesCommonUndoManager) 864 { 865 //! DBG_ASSERT( !bRecording, "BeginCalcUndo ohne GetCalcUndo" ); 866 SetDisableTextEditUsesCommonUndoManager(bDisableTextEditUsesCommonUndoManager); 867 DELETEZ(pUndoGroup); 868 bRecording = sal_True; 869 } 870 871 SdrUndoGroup* ScDrawLayer::GetCalcUndo() 872 { 873 //! DBG_ASSERT( bRecording, "GetCalcUndo ohne BeginCalcUndo" ); 874 875 SdrUndoGroup* pRet = pUndoGroup; 876 pUndoGroup = NULL; 877 bRecording = sal_False; 878 SetDisableTextEditUsesCommonUndoManager(false); 879 return pRet; 880 } 881 882 // MoveAreaTwips: all measures are kept in twips 883 void ScDrawLayer::MoveAreaTwips( SCTAB nTab, const Rectangle& rArea, 884 const Point& rMove, const Point& rTopLeft ) 885 { 886 if (!rMove.X() && !rMove.Y()) 887 return; // nix 888 889 SdrPage* pPage = GetPage(static_cast<sal_uInt16>(nTab)); 890 DBG_ASSERT(pPage,"Page nicht gefunden"); 891 if (!pPage) 892 return; 893 894 sal_Bool bNegativePage = pDoc && pDoc->IsNegativePage( nTab ); 895 896 // fuer Shrinking! 897 Rectangle aNew( rArea ); 898 sal_Bool bShrink = sal_False; 899 if ( rMove.X() < 0 || rMove.Y() < 0 ) // verkleinern 900 { 901 if ( rTopLeft != rArea.TopLeft() ) // sind gleich beim Verschieben von Zellen 902 { 903 bShrink = sal_True; 904 aNew.Left() = rTopLeft.X(); 905 aNew.Top() = rTopLeft.Y(); 906 } 907 } 908 SdrObjListIter aIter( *pPage, IM_FLAT ); 909 SdrObject* pObject = aIter.Next(); 910 while (pObject) 911 { 912 if( GetAnchor( pObject ) == SCA_CELL ) 913 { 914 if ( GetObjData( pObject ) ) // Detektiv-Pfeil ? 915 { 916 // hier nichts 917 } 918 else if ( pObject->ISA( SdrEdgeObj ) ) // Verbinder? 919 { 920 // hier auch nichts 921 //! nicht verbundene Enden wie bei Linien (s.u.) behandeln? 922 } 923 else if ( pObject->IsPolyObj() && pObject->GetPointCount()==2 ) 924 { 925 for (sal_uInt16 i=0; i<2; i++) 926 { 927 sal_Bool bMoved = sal_False; 928 Point aPoint = pObject->GetPoint(i); 929 lcl_ReverseTwipsToMM( aPoint ); 930 if (rArea.IsInside(aPoint)) 931 { 932 aPoint += rMove; bMoved = sal_True; 933 } 934 else if (bShrink && aNew.IsInside(aPoint)) 935 { 936 // Punkt ist in betroffener Zelle - Test auf geloeschten Bereich 937 if ( rMove.X() && aPoint.X() >= rArea.Left() + rMove.X() ) 938 { 939 aPoint.X() = rArea.Left() + rMove.X() - SHRINK_DIST_TWIPS; 940 if ( aPoint.X() < 0 ) aPoint.X() = 0; 941 bMoved = sal_True; 942 } 943 if ( rMove.Y() && aPoint.Y() >= rArea.Top() + rMove.Y() ) 944 { 945 aPoint.Y() = rArea.Top() + rMove.Y() - SHRINK_DIST_TWIPS; 946 if ( aPoint.Y() < 0 ) aPoint.Y() = 0; 947 bMoved = sal_True; 948 } 949 } 950 if( bMoved ) 951 { 952 AddCalcUndo< SdrUndoGeoObj >( *pObject ); 953 lcl_TwipsToMM( aPoint ); 954 pObject->SetPoint( aPoint, i ); 955 } 956 } 957 } 958 else 959 { 960 Rectangle aObjRect = pObject->GetLogicRect(); 961 // aOldMMPos: not converted, millimeters 962 Point aOldMMPos = bNegativePage ? aObjRect.TopRight() : aObjRect.TopLeft(); 963 lcl_ReverseTwipsToMM( aObjRect ); 964 Point aTopLeft = bNegativePage ? aObjRect.TopRight() : aObjRect.TopLeft(); // logical left 965 Size aMoveSize; 966 sal_Bool bDoMove = sal_False; 967 if (rArea.IsInside(aTopLeft)) 968 { 969 aMoveSize = Size(rMove.X(),rMove.Y()); 970 bDoMove = sal_True; 971 } 972 else if (bShrink && aNew.IsInside(aTopLeft)) 973 { 974 // Position ist in betroffener Zelle - Test auf geloeschten Bereich 975 if ( rMove.X() && aTopLeft.X() >= rArea.Left() + rMove.X() ) 976 { 977 aMoveSize.Width() = rArea.Left() + rMove.X() - SHRINK_DIST - aTopLeft.X(); 978 bDoMove = sal_True; 979 } 980 if ( rMove.Y() && aTopLeft.Y() >= rArea.Top() + rMove.Y() ) 981 { 982 aMoveSize.Height() = rArea.Top() + rMove.Y() - SHRINK_DIST - aTopLeft.Y(); 983 bDoMove = sal_True; 984 } 985 } 986 if ( bDoMove ) 987 { 988 if ( bNegativePage ) 989 { 990 if ( aTopLeft.X() + aMoveSize.Width() > 0 ) 991 aMoveSize.Width() = -aTopLeft.X(); 992 } 993 else 994 { 995 if ( aTopLeft.X() + aMoveSize.Width() < 0 ) 996 aMoveSize.Width() = -aTopLeft.X(); 997 } 998 if ( aTopLeft.Y() + aMoveSize.Height() < 0 ) 999 aMoveSize.Height() = -aTopLeft.Y(); 1000 1001 // get corresponding move size in millimeters: 1002 Point aNewPos( aTopLeft.X() + aMoveSize.Width(), aTopLeft.Y() + aMoveSize.Height() ); 1003 lcl_TwipsToMM( aNewPos ); 1004 aMoveSize = Size( aNewPos.X() - aOldMMPos.X(), aNewPos.Y() - aOldMMPos.Y() ); // millimeters 1005 1006 AddCalcUndo< SdrUndoMoveObj >( *pObject, aMoveSize ); 1007 pObject->Move( aMoveSize ); 1008 } 1009 else if ( rArea.IsInside( bNegativePage ? aObjRect.BottomLeft() : aObjRect.BottomRight() ) && 1010 !pObject->IsResizeProtect() ) 1011 { 1012 // geschuetzte Groessen werden nicht veraendert 1013 // (Positionen schon, weil sie ja an der Zelle "verankert" sind) 1014 AddCalcUndo< SdrUndoGeoObj >( *pObject ); 1015 long nOldSizeX = aObjRect.Right() - aObjRect.Left() + 1; 1016 long nOldSizeY = aObjRect.Bottom() - aObjRect.Top() + 1; 1017 long nLogMoveX = rMove.X() * ( bNegativePage ? -1 : 1 ); // logical direction 1018 pObject->Resize( aOldMMPos, Fraction( nOldSizeX+nLogMoveX, nOldSizeX ), 1019 Fraction( nOldSizeY+rMove.Y(), nOldSizeY ) ); 1020 } 1021 } 1022 } 1023 pObject = aIter.Next(); 1024 } 1025 } 1026 1027 void ScDrawLayer::MoveArea( SCTAB nTab, SCCOL nCol1,SCROW nRow1, SCCOL nCol2,SCROW nRow2, 1028 SCsCOL nDx,SCsROW nDy, sal_Bool bInsDel, bool bUpdateNoteCaptionPos ) 1029 { 1030 DBG_ASSERT( pDoc, "ScDrawLayer::MoveArea without document" ); 1031 if ( !pDoc ) 1032 return; 1033 1034 if (!bAdjustEnabled) 1035 return; 1036 1037 sal_Bool bNegativePage = pDoc->IsNegativePage( nTab ); 1038 1039 Rectangle aRect = pDoc->GetMMRect( nCol1, nRow1, nCol2, nRow2, nTab ); 1040 lcl_ReverseTwipsToMM( aRect ); 1041 //! use twips directly? 1042 1043 Point aMove; 1044 1045 if (nDx > 0) 1046 for (SCsCOL s=0; s<nDx; s++) 1047 aMove.X() += pDoc->GetColWidth(s+(SCsCOL)nCol1,nTab); 1048 else 1049 for (SCsCOL s=-1; s>=nDx; s--) 1050 aMove.X() -= pDoc->GetColWidth(s+(SCsCOL)nCol1,nTab); 1051 if (nDy > 0) 1052 aMove.Y() += pDoc->GetRowHeight( nRow1, nRow1+nDy-1, nTab); 1053 else 1054 aMove.Y() -= pDoc->GetRowHeight( nRow1+nDy, nRow1-1, nTab); 1055 1056 if ( bNegativePage ) 1057 aMove.X() = -aMove.X(); 1058 1059 Point aTopLeft = aRect.TopLeft(); // Anfang beim Verkleinern 1060 if (bInsDel) 1061 { 1062 if ( aMove.X() != 0 && nDx < 0 ) // nDx counts cells, sign is independent of RTL 1063 aTopLeft.X() += aMove.X(); 1064 if ( aMove.Y() < 0 ) 1065 aTopLeft.Y() += aMove.Y(); 1066 } 1067 1068 // drawing objects are now directly included in cut&paste 1069 // -> only update references when inserting/deleting (or changing widths or heights) 1070 if ( bInsDel ) 1071 MoveAreaTwips( nTab, aRect, aMove, aTopLeft ); 1072 1073 // 1074 // Detektiv-Pfeile: Zellpositionen anpassen 1075 // 1076 1077 MoveCells( nTab, nCol1,nRow1, nCol2,nRow2, nDx,nDy, bUpdateNoteCaptionPos ); 1078 } 1079 1080 void ScDrawLayer::WidthChanged( SCTAB nTab, SCCOL nCol, long nDifTwips ) 1081 { 1082 DBG_ASSERT( pDoc, "ScDrawLayer::WidthChanged without document" ); 1083 if ( !pDoc ) 1084 return; 1085 1086 if (!bAdjustEnabled) 1087 return; 1088 1089 Rectangle aRect; 1090 Point aTopLeft; 1091 1092 for (SCCOL i=0; i<nCol; i++) 1093 aRect.Left() += pDoc->GetColWidth(i,nTab); 1094 aTopLeft.X() = aRect.Left(); 1095 aRect.Left() += pDoc->GetColWidth(nCol,nTab); 1096 1097 aRect.Right() = MAXMM; 1098 aRect.Top() = 0; 1099 aRect.Bottom() = MAXMM; 1100 1101 //! aTopLeft ist falsch, wenn mehrere Spalten auf einmal ausgeblendet werden 1102 1103 sal_Bool bNegativePage = pDoc->IsNegativePage( nTab ); 1104 if ( bNegativePage ) 1105 { 1106 MirrorRectRTL( aRect ); 1107 aTopLeft.X() = -aTopLeft.X(); 1108 nDifTwips = -nDifTwips; 1109 } 1110 1111 MoveAreaTwips( nTab, aRect, Point( nDifTwips,0 ), aTopLeft ); 1112 } 1113 1114 void ScDrawLayer::HeightChanged( SCTAB nTab, SCROW nRow, long nDifTwips ) 1115 { 1116 DBG_ASSERT( pDoc, "ScDrawLayer::HeightChanged without document" ); 1117 if ( !pDoc ) 1118 return; 1119 1120 if (!bAdjustEnabled) 1121 return; 1122 1123 SdrPage* pPage = GetPage(static_cast<sal_uInt16>(nTab)); 1124 DBG_ASSERT(pPage,"Page not found"); 1125 if (!pPage) 1126 return; 1127 1128 // for an empty page, there's no need to calculate the row heights 1129 if (!pPage->GetObjCount()) 1130 return; 1131 1132 Rectangle aRect; 1133 Point aTopLeft; 1134 1135 aRect.Top() += pDoc->GetRowHeight( 0, nRow-1, nTab); 1136 aTopLeft.Y() = aRect.Top(); 1137 aRect.Top() += pDoc->GetRowHeight(nRow, nTab); 1138 1139 aRect.Bottom() = MAXMM; 1140 aRect.Left() = 0; 1141 aRect.Right() = MAXMM; 1142 1143 //! aTopLeft ist falsch, wenn mehrere Zeilen auf einmal ausgeblendet werden 1144 1145 sal_Bool bNegativePage = pDoc->IsNegativePage( nTab ); 1146 if ( bNegativePage ) 1147 { 1148 MirrorRectRTL( aRect ); 1149 aTopLeft.X() = -aTopLeft.X(); 1150 } 1151 1152 MoveAreaTwips( nTab, aRect, Point( 0,nDifTwips ), aTopLeft ); 1153 } 1154 1155 sal_Bool ScDrawLayer::HasObjectsInRows( SCTAB nTab, SCROW nStartRow, SCROW nEndRow, bool bIncludeNotes ) 1156 { 1157 DBG_ASSERT( pDoc, "ScDrawLayer::HasObjectsInRows without document" ); 1158 if ( !pDoc ) 1159 return sal_False; 1160 1161 SdrPage* pPage = GetPage(static_cast<sal_uInt16>(nTab)); 1162 DBG_ASSERT(pPage,"Page not found"); 1163 if (!pPage) 1164 return sal_False; 1165 1166 // for an empty page, there's no need to calculate the row heights 1167 if (!pPage->GetObjCount()) 1168 return sal_False; 1169 1170 Rectangle aTestRect; 1171 1172 aTestRect.Top() += pDoc->GetRowHeight( 0, nStartRow-1, nTab); 1173 1174 if (nEndRow==MAXROW) 1175 aTestRect.Bottom() = MAXMM; 1176 else 1177 { 1178 aTestRect.Bottom() = aTestRect.Top(); 1179 aTestRect.Bottom() += pDoc->GetRowHeight( nStartRow, nEndRow, nTab); 1180 TwipsToMM( aTestRect.Bottom() ); 1181 } 1182 1183 TwipsToMM( aTestRect.Top() ); 1184 1185 aTestRect.Left() = 0; 1186 aTestRect.Right() = MAXMM; 1187 1188 sal_Bool bNegativePage = pDoc->IsNegativePage( nTab ); 1189 if ( bNegativePage ) 1190 MirrorRectRTL( aTestRect ); 1191 1192 sal_Bool bFound = sal_False; 1193 1194 Rectangle aObjRect; 1195 SdrObjListIter aIter( *pPage ); 1196 SdrObject* pObject = aIter.Next(); 1197 while ( pObject && !bFound ) 1198 { 1199 aObjRect = pObject->GetSnapRect(); //! GetLogicRect ? 1200 // #i116164# note captions are handled separately, don't have to be included for each single row height change 1201 if ( (aTestRect.IsInside(aObjRect.TopLeft()) || aTestRect.IsInside(aObjRect.BottomLeft())) && 1202 (bIncludeNotes || !IsNoteCaption(pObject)) ) 1203 bFound = sal_True; 1204 1205 pObject = aIter.Next(); 1206 } 1207 1208 return bFound; 1209 } 1210 1211 #if 0 1212 void ScDrawLayer::DeleteObjects( SCTAB nTab ) 1213 { 1214 SdrPage* pPage = GetPage(static_cast<sal_uInt16>(nTab)); 1215 DBG_ASSERT(pPage,"Page ?"); 1216 if (!pPage) 1217 return; 1218 1219 pPage->RecalcObjOrdNums(); 1220 1221 long nDelCount = 0; 1222 sal_uLong nObjCount = pPage->GetObjCount(); 1223 if (nObjCount) 1224 { 1225 SdrObject** ppObj = new SdrObject*[nObjCount]; 1226 1227 SdrObjListIter aIter( *pPage, IM_FLAT ); 1228 SdrObject* pObject = aIter.Next(); 1229 while (pObject) 1230 { 1231 // alle loeschen 1232 ppObj[nDelCount++] = pObject; 1233 pObject = aIter.Next(); 1234 } 1235 1236 long i; 1237 if (bRecording) 1238 for (i=1; i<=nDelCount; i++) 1239 AddCalcUndo< SdrUndoRemoveObj >( *ppObj[nDelCount-i] ); 1240 1241 for (i=1; i<=nDelCount; i++) 1242 pPage->RemoveObject( ppObj[nDelCount-i]->GetOrdNum() ); 1243 1244 delete[] ppObj; 1245 } 1246 } 1247 #endif 1248 1249 void ScDrawLayer::DeleteObjectsInArea( SCTAB nTab, SCCOL nCol1,SCROW nRow1, 1250 SCCOL nCol2,SCROW nRow2 ) 1251 { 1252 DBG_ASSERT( pDoc, "ScDrawLayer::DeleteObjectsInArea without document" ); 1253 if ( !pDoc ) 1254 return; 1255 1256 SdrPage* pPage = GetPage(static_cast<sal_uInt16>(nTab)); 1257 DBG_ASSERT(pPage,"Page ?"); 1258 if (!pPage) 1259 return; 1260 1261 pPage->RecalcObjOrdNums(); 1262 1263 long nDelCount = 0; 1264 sal_uLong nObjCount = pPage->GetObjCount(); 1265 if (nObjCount) 1266 { 1267 Rectangle aDelRect = pDoc->GetMMRect( nCol1, nRow1, nCol2, nRow2, nTab ); 1268 1269 SdrObject** ppObj = new SdrObject*[nObjCount]; 1270 1271 SdrObjListIter aIter( *pPage, IM_FLAT ); 1272 SdrObject* pObject = aIter.Next(); 1273 while (pObject) 1274 { 1275 // do not delete note caption, they are always handled by the cell note 1276 // TODO: detective objects are still deleted, is this desired? 1277 if (!IsNoteCaption( pObject )) 1278 { 1279 Rectangle aObjRect = pObject->GetCurrentBoundRect(); 1280 if ( aDelRect.IsInside( aObjRect ) ) 1281 ppObj[nDelCount++] = pObject; 1282 } 1283 1284 pObject = aIter.Next(); 1285 } 1286 1287 long i; 1288 if (bRecording) 1289 for (i=1; i<=nDelCount; i++) 1290 AddCalcUndo< SdrUndoRemoveObj >( *ppObj[nDelCount-i] ); 1291 1292 for (i=1; i<=nDelCount; i++) 1293 pPage->RemoveObject( ppObj[nDelCount-i]->GetOrdNum() ); 1294 1295 delete[] ppObj; 1296 } 1297 } 1298 1299 void ScDrawLayer::DeleteObjectsInSelection( const ScMarkData& rMark ) 1300 { 1301 DBG_ASSERT( pDoc, "ScDrawLayer::DeleteObjectsInSelection without document" ); 1302 if ( !pDoc ) 1303 return; 1304 1305 if ( !rMark.IsMultiMarked() ) 1306 return; 1307 1308 ScRange aMarkRange; 1309 rMark.GetMultiMarkArea( aMarkRange ); 1310 1311 SCTAB nTabCount = pDoc->GetTableCount(); 1312 for (SCTAB nTab=0; nTab<=nTabCount; nTab++) 1313 if ( rMark.GetTableSelect( nTab ) ) 1314 { 1315 SdrPage* pPage = GetPage(static_cast<sal_uInt16>(nTab)); 1316 if (pPage) 1317 { 1318 pPage->RecalcObjOrdNums(); 1319 long nDelCount = 0; 1320 sal_uLong nObjCount = pPage->GetObjCount(); 1321 if (nObjCount) 1322 { 1323 // Rechteck um die ganze Selektion 1324 Rectangle aMarkBound = pDoc->GetMMRect( 1325 aMarkRange.aStart.Col(), aMarkRange.aStart.Row(), 1326 aMarkRange.aEnd.Col(), aMarkRange.aEnd.Row(), nTab ); 1327 1328 SdrObject** ppObj = new SdrObject*[nObjCount]; 1329 1330 SdrObjListIter aIter( *pPage, IM_FLAT ); 1331 SdrObject* pObject = aIter.Next(); 1332 while (pObject) 1333 { 1334 // do not delete note caption, they are always handled by the cell note 1335 // TODO: detective objects are still deleted, is this desired? 1336 if (!IsNoteCaption( pObject )) 1337 { 1338 Rectangle aObjRect = pObject->GetCurrentBoundRect(); 1339 if ( aMarkBound.IsInside( aObjRect ) ) 1340 { 1341 ScRange aRange = pDoc->GetRange( nTab, aObjRect ); 1342 if (rMark.IsAllMarked(aRange)) 1343 ppObj[nDelCount++] = pObject; 1344 } 1345 } 1346 1347 pObject = aIter.Next(); 1348 } 1349 1350 // Objekte loeschen (rueckwaerts) 1351 1352 long i; 1353 if (bRecording) 1354 for (i=1; i<=nDelCount; i++) 1355 AddCalcUndo< SdrUndoRemoveObj >( *ppObj[nDelCount-i] ); 1356 1357 for (i=1; i<=nDelCount; i++) 1358 pPage->RemoveObject( ppObj[nDelCount-i]->GetOrdNum() ); 1359 1360 delete[] ppObj; 1361 } 1362 } 1363 else 1364 { 1365 DBG_ERROR("pPage?"); 1366 } 1367 } 1368 } 1369 1370 void ScDrawLayer::CopyToClip( ScDocument* pClipDoc, SCTAB nTab, const Rectangle& rRange ) 1371 { 1372 // copy everything in the specified range into the same page (sheet) in the clipboard doc 1373 1374 SdrPage* pSrcPage = GetPage(static_cast<sal_uInt16>(nTab)); 1375 if (pSrcPage) 1376 { 1377 ScDrawLayer* pDestModel = NULL; 1378 SdrPage* pDestPage = NULL; 1379 1380 SdrObjListIter aIter( *pSrcPage, IM_FLAT ); 1381 SdrObject* pOldObject = aIter.Next(); 1382 while (pOldObject) 1383 { 1384 Rectangle aObjRect = pOldObject->GetCurrentBoundRect(); 1385 // do not copy internal objects (detective) and note captions 1386 if ( rRange.IsInside( aObjRect ) && (pOldObject->GetLayer() != SC_LAYER_INTERN) && !IsNoteCaption( pOldObject ) ) 1387 { 1388 if ( !pDestModel ) 1389 { 1390 pDestModel = pClipDoc->GetDrawLayer(); // does the document already have a drawing layer? 1391 if ( !pDestModel ) 1392 { 1393 // allocate drawing layer in clipboard document only if there are objects to copy 1394 1395 pClipDoc->InitDrawLayer(); //! create contiguous pages 1396 pDestModel = pClipDoc->GetDrawLayer(); 1397 } 1398 if (pDestModel) 1399 pDestPage = pDestModel->GetPage( static_cast<sal_uInt16>(nTab) ); 1400 } 1401 1402 DBG_ASSERT( pDestPage, "no page" ); 1403 if (pDestPage) 1404 { 1405 // #116235# 1406 SdrObject* pNewObject = pOldObject->Clone(); 1407 //SdrObject* pNewObject = pOldObject->Clone( pDestPage, pDestModel ); 1408 pNewObject->SetModel(pDestModel); 1409 pNewObject->SetPage(pDestPage); 1410 1411 uno::Reference< chart2::XChartDocument > xOldChart( ScChartHelper::GetChartFromSdrObject( pOldObject ) ); 1412 if(!xOldChart.is())//#i110034# do not move charts as they loose all their data references otherwise 1413 pNewObject->NbcMove(Size(0,0)); 1414 pDestPage->InsertObject( pNewObject ); 1415 1416 // no undo needed in clipboard document 1417 // charts are not updated 1418 } 1419 } 1420 1421 pOldObject = aIter.Next(); 1422 } 1423 } 1424 } 1425 1426 sal_Bool lcl_IsAllInRange( const ::std::vector< ScRangeList >& rRangesVector, const ScRange& rClipRange ) 1427 { 1428 // check if every range of rRangesVector is completely in rClipRange 1429 1430 ::std::vector< ScRangeList >::const_iterator aIt = rRangesVector.begin(); 1431 for( ;aIt!=rRangesVector.end(); ++aIt ) 1432 { 1433 const ScRangeList& rRanges = *aIt; 1434 sal_uLong nCount = rRanges.Count(); 1435 for (sal_uLong i=0; i<nCount; i++) 1436 { 1437 ScRange aRange = *rRanges.GetObject(i); 1438 if ( !rClipRange.In( aRange ) ) 1439 { 1440 return sal_False; // at least one range is not valid 1441 } 1442 } 1443 } 1444 1445 return sal_True; // everything is fine 1446 } 1447 1448 sal_Bool lcl_MoveRanges( ::std::vector< ScRangeList >& rRangesVector, const ScRange& rSourceRange, const ScAddress& rDestPos ) 1449 { 1450 sal_Bool bChanged = sal_False; 1451 1452 ::std::vector< ScRangeList >::iterator aIt = rRangesVector.begin(); 1453 for( ;aIt!=rRangesVector.end(); ++aIt ) 1454 { 1455 ScRangeList& rRanges = *aIt; 1456 sal_uLong nCount = rRanges.Count(); 1457 for (sal_uLong i=0; i<nCount; i++) 1458 { 1459 ScRange* pRange = rRanges.GetObject(i); 1460 if ( rSourceRange.In( *pRange ) ) 1461 { 1462 SCsCOL nDiffX = rDestPos.Col() - (SCsCOL)rSourceRange.aStart.Col(); 1463 SCsROW nDiffY = rDestPos.Row() - (SCsROW)rSourceRange.aStart.Row(); 1464 SCsTAB nDiffZ = rDestPos.Tab() - (SCsTAB)rSourceRange.aStart.Tab(); 1465 pRange->Move( nDiffX, nDiffY, nDiffZ ); 1466 bChanged = sal_True; 1467 } 1468 } 1469 } 1470 1471 return bChanged; 1472 } 1473 1474 void ScDrawLayer::CopyFromClip( ScDrawLayer* pClipModel, SCTAB nSourceTab, const Rectangle& rSourceRange, 1475 const ScAddress& rDestPos, const Rectangle& rDestRange ) 1476 { 1477 DBG_ASSERT( pDoc, "ScDrawLayer::CopyFromClip without document" ); 1478 if ( !pDoc ) 1479 return; 1480 1481 if (!pClipModel) 1482 return; 1483 1484 if (bDrawIsInUndo) //! can this happen? 1485 { 1486 DBG_ERROR("CopyFromClip, bDrawIsInUndo"); 1487 return; 1488 } 1489 1490 sal_Bool bMirrorObj = ( rSourceRange.Left() < 0 && rSourceRange.Right() < 0 && 1491 rDestRange.Left() > 0 && rDestRange.Right() > 0 ) || 1492 ( rSourceRange.Left() > 0 && rSourceRange.Right() > 0 && 1493 rDestRange.Left() < 0 && rDestRange.Right() < 0 ); 1494 Rectangle aMirroredSource = rSourceRange; 1495 if ( bMirrorObj ) 1496 MirrorRectRTL( aMirroredSource ); 1497 1498 SCTAB nDestTab = rDestPos.Tab(); 1499 1500 SdrPage* pSrcPage = pClipModel->GetPage(static_cast<sal_uInt16>(nSourceTab)); 1501 SdrPage* pDestPage = GetPage(static_cast<sal_uInt16>(nDestTab)); 1502 DBG_ASSERT( pSrcPage && pDestPage, "draw page missing" ); 1503 if ( !pSrcPage || !pDestPage ) 1504 return; 1505 1506 SdrObjListIter aIter( *pSrcPage, IM_FLAT ); 1507 SdrObject* pOldObject = aIter.Next(); 1508 1509 ScDocument* pClipDoc = pClipModel->GetDocument(); 1510 // a clipboard document and its source share the same document item pool, 1511 // so the pointers can be compared to see if this is copy&paste within 1512 // the same document 1513 sal_Bool bSameDoc = pDoc && pClipDoc && pDoc->GetPool() == pClipDoc->GetPool(); 1514 sal_Bool bDestClip = pDoc && pDoc->IsClipboard(); 1515 1516 //#i110034# charts need correct sheet names for xml range conversion during load 1517 //so the target sheet name is temporarily renamed (if we have any SdrObjects) 1518 String aDestTabName; 1519 sal_Bool bRestoreDestTabName = sal_False; 1520 if( pOldObject && !bSameDoc && !bDestClip ) 1521 { 1522 if( pDoc && pClipDoc ) 1523 { 1524 String aSourceTabName; 1525 if( pClipDoc->GetName( nSourceTab, aSourceTabName ) 1526 && pDoc->GetName( nDestTab, aDestTabName ) ) 1527 { 1528 if( !(aSourceTabName==aDestTabName) && 1529 pDoc->ValidNewTabName(aSourceTabName) ) 1530 { 1531 bRestoreDestTabName = pDoc->RenameTab( nDestTab, aSourceTabName ); //sal_Bool bUpdateRef = sal_True, sal_Bool bExternalDocument = sal_False 1532 } 1533 } 1534 } 1535 } 1536 1537 // first mirror, then move 1538 Size aMove( rDestRange.Left() - aMirroredSource.Left(), rDestRange.Top() - aMirroredSource.Top() ); 1539 1540 long nDestWidth = rDestRange.GetWidth(); 1541 long nDestHeight = rDestRange.GetHeight(); 1542 long nSourceWidth = rSourceRange.GetWidth(); 1543 long nSourceHeight = rSourceRange.GetHeight(); 1544 1545 long nWidthDiff = nDestWidth - nSourceWidth; 1546 long nHeightDiff = nDestHeight - nSourceHeight; 1547 1548 Fraction aHorFract(1,1); 1549 Fraction aVerFract(1,1); 1550 sal_Bool bResize = sal_False; 1551 // sizes can differ by 1 from twips->1/100mm conversion for equal cell sizes, 1552 // don't resize to empty size when pasting into hidden columns or rows 1553 if ( Abs(nWidthDiff) > 1 && nDestWidth > 1 && nSourceWidth > 1 ) 1554 { 1555 aHorFract = Fraction( nDestWidth, nSourceWidth ); 1556 bResize = sal_True; 1557 } 1558 if ( Abs(nHeightDiff) > 1 && nDestHeight > 1 && nSourceHeight > 1 ) 1559 { 1560 aVerFract = Fraction( nDestHeight, nSourceHeight ); 1561 bResize = sal_True; 1562 } 1563 Point aRefPos = rDestRange.TopLeft(); // for resizing (after moving) 1564 1565 while (pOldObject) 1566 { 1567 Rectangle aObjRect = pOldObject->GetCurrentBoundRect(); 1568 // do not copy internal objects (detective) and note captions 1569 if ( rSourceRange.IsInside( aObjRect ) && (pOldObject->GetLayer() != SC_LAYER_INTERN) && !IsNoteCaption( pOldObject ) ) 1570 { 1571 // #116235# 1572 SdrObject* pNewObject = pOldObject->Clone(); 1573 //SdrObject* pNewObject = pOldObject->Clone( pDestPage, this ); 1574 pNewObject->SetModel(this); 1575 pNewObject->SetPage(pDestPage); 1576 1577 if ( bMirrorObj ) 1578 MirrorRTL( pNewObject ); // first mirror, then move 1579 1580 pNewObject->NbcMove( aMove ); 1581 if ( bResize ) 1582 pNewObject->NbcResize( aRefPos, aHorFract, aVerFract ); 1583 1584 pDestPage->InsertObject( pNewObject ); 1585 if (bRecording) 1586 AddCalcUndo< SdrUndoInsertObj >( *pNewObject ); 1587 1588 //#i110034# handle chart data references (after InsertObject) 1589 1590 if ( pNewObject->GetObjIdentifier() == OBJ_OLE2 ) 1591 { 1592 uno::Reference< embed::XEmbeddedObject > xIPObj = ((SdrOle2Obj*)pNewObject)->GetObjRef(); 1593 uno::Reference< embed::XClassifiedObject > xClassified( xIPObj, uno::UNO_QUERY ); 1594 SvGlobalName aObjectClassName; 1595 if ( xClassified.is() ) 1596 { 1597 try { 1598 aObjectClassName = SvGlobalName( xClassified->getClassID() ); 1599 } catch( uno::Exception& ) 1600 { 1601 // TODO: handle error? 1602 } 1603 } 1604 1605 if ( xIPObj.is() && SotExchange::IsChart( aObjectClassName ) ) 1606 { 1607 uno::Reference< chart2::XChartDocument > xNewChart( ScChartHelper::GetChartFromSdrObject( pNewObject ) ); 1608 if( xNewChart.is() && !xNewChart->hasInternalDataProvider() ) 1609 { 1610 String aChartName = ((SdrOle2Obj*)pNewObject)->GetPersistName(); 1611 ::std::vector< ScRangeList > aRangesVector; 1612 pDoc->GetChartRanges( aChartName, aRangesVector, pDoc ); 1613 if( !aRangesVector.empty() ) 1614 { 1615 sal_Bool bInSourceRange = sal_False; 1616 ScRange aClipRange; 1617 if ( pClipDoc ) 1618 { 1619 SCCOL nClipStartX; 1620 SCROW nClipStartY; 1621 SCCOL nClipEndX; 1622 SCROW nClipEndY; 1623 pClipDoc->GetClipStart( nClipStartX, nClipStartY ); 1624 pClipDoc->GetClipArea( nClipEndX, nClipEndY, sal_True ); 1625 nClipEndX = nClipEndX + nClipStartX; 1626 nClipEndY += nClipStartY; // GetClipArea returns the difference 1627 1628 SCTAB nClipTab = bRestoreDestTabName ? nDestTab : nSourceTab; 1629 aClipRange = ScRange( nClipStartX, nClipStartY, nClipTab, 1630 nClipEndX, nClipEndY, nClipTab ); 1631 1632 bInSourceRange = lcl_IsAllInRange( aRangesVector, aClipRange ); 1633 } 1634 1635 // always lose references when pasting into a clipboard document (transpose) 1636 if ( ( bInSourceRange || bSameDoc ) && !bDestClip ) 1637 { 1638 if ( bInSourceRange ) 1639 { 1640 if ( rDestPos != aClipRange.aStart ) 1641 { 1642 // update the data ranges to the new (copied) position 1643 if ( lcl_MoveRanges( aRangesVector, aClipRange, rDestPos ) ) 1644 pDoc->SetChartRanges( aChartName, aRangesVector ); 1645 } 1646 } 1647 else 1648 { 1649 // leave the ranges unchanged 1650 } 1651 } 1652 else 1653 { 1654 // pasting into a new document without the complete source data 1655 // -> break connection to source data and switch to own data 1656 1657 uno::Reference< chart::XChartDocument > xOldChartDoc( ScChartHelper::GetChartFromSdrObject( pOldObject ), uno::UNO_QUERY ); 1658 uno::Reference< chart::XChartDocument > xNewChartDoc( xNewChart, uno::UNO_QUERY ); 1659 if( xOldChartDoc.is() && xNewChartDoc.is() ) 1660 xNewChartDoc->attachData( xOldChartDoc->getData() ); 1661 1662 // (see ScDocument::UpdateChartListenerCollection, PastingDrawFromOtherDoc) 1663 } 1664 } 1665 } 1666 } 1667 } 1668 } 1669 1670 pOldObject = aIter.Next(); 1671 } 1672 1673 if( bRestoreDestTabName ) 1674 pDoc->RenameTab( nDestTab, aDestTabName ); 1675 } 1676 1677 void ScDrawLayer::MirrorRTL( SdrObject* pObj ) 1678 { 1679 sal_uInt16 nIdent = pObj->GetObjIdentifier(); 1680 1681 // don't mirror OLE or graphics, otherwise ask the object 1682 // if it can be mirrored 1683 sal_Bool bCanMirror = ( nIdent != OBJ_GRAF && nIdent != OBJ_OLE2 ); 1684 if (bCanMirror) 1685 { 1686 SdrObjTransformInfoRec aInfo; 1687 pObj->TakeObjInfo( aInfo ); 1688 bCanMirror = aInfo.bMirror90Allowed; 1689 } 1690 1691 if (bCanMirror) 1692 { 1693 Point aRef1( 0, 0 ); 1694 Point aRef2( 0, 1 ); 1695 if (bRecording) 1696 AddCalcUndo< SdrUndoGeoObj >( *pObj ); 1697 pObj->Mirror( aRef1, aRef2 ); 1698 } 1699 else 1700 { 1701 // Move instead of mirroring: 1702 // New start position is negative of old end position 1703 // -> move by sum of start and end position 1704 Rectangle aObjRect = pObj->GetLogicRect(); 1705 Size aMoveSize( -(aObjRect.Left() + aObjRect.Right()), 0 ); 1706 if (bRecording) 1707 AddCalcUndo< SdrUndoMoveObj >( *pObj, aMoveSize ); 1708 pObj->Move( aMoveSize ); 1709 } 1710 } 1711 1712 // static 1713 void ScDrawLayer::MirrorRectRTL( Rectangle& rRect ) 1714 { 1715 // mirror and swap left/right 1716 long nTemp = rRect.Left(); 1717 rRect.Left() = -rRect.Right(); 1718 rRect.Right() = -nTemp; 1719 } 1720 1721 Rectangle ScDrawLayer::GetCellRect( ScDocument& rDoc, const ScAddress& rPos, bool bMergedCell ) 1722 { 1723 Rectangle aCellRect; 1724 DBG_ASSERT( ValidColRowTab( rPos.Col(), rPos.Row(), rPos.Tab() ), "ScDrawLayer::GetCellRect - invalid cell address" ); 1725 if( ValidColRowTab( rPos.Col(), rPos.Row(), rPos.Tab() ) ) 1726 { 1727 // find top left position of passed cell address 1728 Point aTopLeft; 1729 for( SCCOL nCol = 0; nCol < rPos.Col(); ++nCol ) 1730 aTopLeft.X() += rDoc.GetColWidth( nCol, rPos.Tab() ); 1731 if( rPos.Row() > 0 ) 1732 aTopLeft.Y() += rDoc.GetRowHeight( 0, rPos.Row() - 1, rPos.Tab() ); 1733 1734 // find bottom-right position of passed cell address 1735 ScAddress aEndPos = rPos; 1736 if( bMergedCell ) 1737 { 1738 const ScMergeAttr* pMerge = static_cast< const ScMergeAttr* >( rDoc.GetAttr( rPos.Col(), rPos.Row(), rPos.Tab(), ATTR_MERGE ) ); 1739 if( pMerge->GetColMerge() > 1 ) 1740 aEndPos.IncCol( pMerge->GetColMerge() - 1 ); 1741 if( pMerge->GetRowMerge() > 1 ) 1742 aEndPos.IncRow( pMerge->GetRowMerge() - 1 ); 1743 } 1744 Point aBotRight = aTopLeft; 1745 for( SCCOL nCol = rPos.Col(); nCol <= aEndPos.Col(); ++nCol ) 1746 aBotRight.X() += rDoc.GetColWidth( nCol, rPos.Tab() ); 1747 aBotRight.Y() += rDoc.GetRowHeight( rPos.Row(), aEndPos.Row(), rPos.Tab() ); 1748 1749 // twips -> 1/100 mm 1750 aTopLeft.X() = static_cast< long >( aTopLeft.X() * HMM_PER_TWIPS ); 1751 aTopLeft.Y() = static_cast< long >( aTopLeft.Y() * HMM_PER_TWIPS ); 1752 aBotRight.X() = static_cast< long >( aBotRight.X() * HMM_PER_TWIPS ); 1753 aBotRight.Y() = static_cast< long >( aBotRight.Y() * HMM_PER_TWIPS ); 1754 1755 aCellRect = Rectangle( aTopLeft, aBotRight ); 1756 if( rDoc.IsNegativePage( rPos.Tab() ) ) 1757 MirrorRectRTL( aCellRect ); 1758 } 1759 return aCellRect; 1760 } 1761 1762 // static 1763 String ScDrawLayer::GetVisibleName( SdrObject* pObj ) 1764 { 1765 String aName = pObj->GetName(); 1766 if ( pObj->GetObjIdentifier() == OBJ_OLE2 ) 1767 { 1768 // #95575# For OLE, the user defined name (GetName) is used 1769 // if it's not empty (accepting possibly duplicate names), 1770 // otherwise the persist name is used so every object appears 1771 // in the Navigator at all. 1772 1773 if ( !aName.Len() ) 1774 aName = static_cast<SdrOle2Obj*>(pObj)->GetPersistName(); 1775 } 1776 return aName; 1777 } 1778 1779 inline sal_Bool IsNamedObject( SdrObject* pObj, const String& rName ) 1780 { 1781 // sal_True if rName is the object's Name or PersistName 1782 // (used to find a named object) 1783 1784 return ( pObj->GetName() == rName || 1785 ( pObj->GetObjIdentifier() == OBJ_OLE2 && 1786 static_cast<SdrOle2Obj*>(pObj)->GetPersistName() == rName ) ); 1787 } 1788 1789 SdrObject* ScDrawLayer::GetNamedObject( const String& rName, sal_uInt16 nId, SCTAB& rFoundTab ) const 1790 { 1791 sal_uInt16 nTabCount = GetPageCount(); 1792 for (sal_uInt16 nTab=0; nTab<nTabCount; nTab++) 1793 { 1794 const SdrPage* pPage = GetPage(nTab); 1795 DBG_ASSERT(pPage,"Page ?"); 1796 if (pPage) 1797 { 1798 SdrObjListIter aIter( *pPage, IM_DEEPWITHGROUPS ); 1799 SdrObject* pObject = aIter.Next(); 1800 while (pObject) 1801 { 1802 if ( nId == 0 || pObject->GetObjIdentifier() == nId ) 1803 if ( IsNamedObject( pObject, rName ) ) 1804 { 1805 rFoundTab = static_cast<SCTAB>(nTab); 1806 return pObject; 1807 } 1808 1809 pObject = aIter.Next(); 1810 } 1811 } 1812 } 1813 1814 return NULL; 1815 } 1816 1817 String ScDrawLayer::GetNewGraphicName( long* pnCounter ) const 1818 { 1819 String aBase = ScGlobal::GetRscString(STR_GRAPHICNAME); 1820 aBase += ' '; 1821 1822 sal_Bool bThere = sal_True; 1823 String aGraphicName; 1824 SCTAB nDummy; 1825 long nId = pnCounter ? *pnCounter : 0; 1826 while (bThere) 1827 { 1828 ++nId; 1829 aGraphicName = aBase; 1830 aGraphicName += String::CreateFromInt32( nId ); 1831 bThere = ( GetNamedObject( aGraphicName, 0, nDummy ) != NULL ); 1832 } 1833 1834 if ( pnCounter ) 1835 *pnCounter = nId; 1836 1837 return aGraphicName; 1838 } 1839 1840 void ScDrawLayer::EnsureGraphicNames() 1841 { 1842 // make sure all graphic objects have names (after Excel import etc.) 1843 1844 sal_uInt16 nTabCount = GetPageCount(); 1845 for (sal_uInt16 nTab=0; nTab<nTabCount; nTab++) 1846 { 1847 SdrPage* pPage = GetPage(nTab); 1848 DBG_ASSERT(pPage,"Page ?"); 1849 if (pPage) 1850 { 1851 SdrObjListIter aIter( *pPage, IM_DEEPWITHGROUPS ); 1852 SdrObject* pObject = aIter.Next(); 1853 1854 /* #101799# The index passed to GetNewGraphicName() will be set to 1855 the used index in each call. This prevents the repeated search 1856 for all names from 1 to current index. */ 1857 long nCounter = 0; 1858 1859 while (pObject) 1860 { 1861 if ( pObject->GetObjIdentifier() == OBJ_GRAF && pObject->GetName().Len() == 0 ) 1862 pObject->SetName( GetNewGraphicName( &nCounter ) ); 1863 1864 pObject = aIter.Next(); 1865 } 1866 } 1867 } 1868 } 1869 1870 void ScDrawLayer::SetAnchor( SdrObject* pObj, ScAnchorType eType ) 1871 { 1872 ScAnchorType eOldAnchorType = GetAnchor( pObj ); 1873 1874 // Ein an der Seite verankertes Objekt zeichnet sich durch eine Anker-Pos 1875 // von (0,1) aus. Das ist ein shabby Trick, der aber funktioniert! 1876 Point aAnchor( 0, eType == SCA_PAGE ? 1 : 0 ); 1877 pObj->SetAnchorPos( aAnchor ); 1878 1879 if ( eOldAnchorType != eType ) 1880 pObj->notifyShapePropertyChange( ::svx::eSpreadsheetAnchor ); 1881 } 1882 1883 ScAnchorType ScDrawLayer::GetAnchor( const SdrObject* pObj ) 1884 { 1885 Point aAnchor( pObj->GetAnchorPos() ); 1886 return ( aAnchor.Y() != 0 ) ? SCA_PAGE : SCA_CELL; 1887 } 1888 1889 ScDrawObjData* ScDrawLayer::GetObjData( SdrObject* pObj, sal_Bool bCreate ) // static 1890 { 1891 sal_uInt16 nCount = pObj ? pObj->GetUserDataCount() : 0; 1892 for( sal_uInt16 i = 0; i < nCount; i++ ) 1893 { 1894 SdrObjUserData* pData = pObj->GetUserData( i ); 1895 if( pData && pData->GetInventor() == SC_DRAWLAYER 1896 && pData->GetId() == SC_UD_OBJDATA ) 1897 return (ScDrawObjData*) pData; 1898 } 1899 if( pObj && bCreate ) 1900 { 1901 ScDrawObjData* pData = new ScDrawObjData; 1902 pObj->InsertUserData( pData, 0 ); 1903 return pData; 1904 } 1905 return 0; 1906 } 1907 1908 ScDrawObjData* ScDrawLayer::GetObjDataTab( SdrObject* pObj, SCTAB nTab ) // static 1909 { 1910 ScDrawObjData* pData = GetObjData( pObj ); 1911 if ( pData ) 1912 { 1913 if ( pData->maStart.IsValid() ) 1914 pData->maStart.SetTab( nTab ); 1915 if ( pData->maEnd.IsValid() ) 1916 pData->maEnd.SetTab( nTab ); 1917 } 1918 return pData; 1919 } 1920 1921 bool ScDrawLayer::IsNoteCaption( SdrObject* pObj ) 1922 { 1923 ScDrawObjData* pData = pObj ? GetObjData( pObj ) : 0; 1924 return pData && pData->mbNote; 1925 } 1926 1927 ScDrawObjData* ScDrawLayer::GetNoteCaptionData( SdrObject* pObj, SCTAB nTab ) 1928 { 1929 ScDrawObjData* pData = pObj ? GetObjDataTab( pObj, nTab ) : 0; 1930 return (pData && pData->mbNote) ? pData : 0; 1931 } 1932 1933 ScIMapInfo* ScDrawLayer::GetIMapInfo( SdrObject* pObj ) // static 1934 { 1935 sal_uInt16 nCount = pObj->GetUserDataCount(); 1936 for( sal_uInt16 i = 0; i < nCount; i++ ) 1937 { 1938 SdrObjUserData* pData = pObj->GetUserData( i ); 1939 if( pData && pData->GetInventor() == SC_DRAWLAYER 1940 && pData->GetId() == SC_UD_IMAPDATA ) 1941 return (ScIMapInfo*) pData; 1942 } 1943 return NULL; 1944 } 1945 1946 // static: 1947 IMapObject* ScDrawLayer::GetHitIMapObject( SdrObject* pObj, 1948 const Point& rWinPoint, const Window& rCmpWnd ) 1949 { 1950 const MapMode aMap100( MAP_100TH_MM ); 1951 MapMode aWndMode = rCmpWnd.GetMapMode(); 1952 Point aRelPoint( rCmpWnd.LogicToLogic( rWinPoint, &aWndMode, &aMap100 ) ); 1953 Rectangle aLogRect = rCmpWnd.LogicToLogic( pObj->GetLogicRect(), &aWndMode, &aMap100 ); 1954 ScIMapInfo* pIMapInfo = GetIMapInfo( pObj ); 1955 IMapObject* pIMapObj = NULL; 1956 1957 if ( pIMapInfo ) 1958 { 1959 Size aGraphSize; 1960 ImageMap& rImageMap = (ImageMap&) pIMapInfo->GetImageMap(); 1961 Graphic aGraphic; 1962 sal_Bool bObjSupported = sal_False; 1963 1964 if ( pObj->ISA( SdrGrafObj ) ) // einfaches Grafik-Objekt 1965 { 1966 const SdrGrafObj* pGrafObj = (const SdrGrafObj*) pObj; 1967 const GeoStat& rGeo = pGrafObj->GetGeoStat(); 1968 const Graphic& rGraphic = pGrafObj->GetGraphic(); 1969 1970 // Drehung rueckgaengig 1971 if ( rGeo.nDrehWink ) 1972 RotatePoint( aRelPoint, aLogRect.TopLeft(), -rGeo.nSin, rGeo.nCos ); 1973 1974 // Spiegelung rueckgaengig 1975 if ( ( (const SdrGrafObjGeoData*) pGrafObj->GetGeoData() )->bMirrored ) 1976 aRelPoint.X() = aLogRect.Right() + aLogRect.Left() - aRelPoint.X(); 1977 1978 // ggf. Unshear: 1979 if ( rGeo.nShearWink ) 1980 ShearPoint( aRelPoint, aLogRect.TopLeft(), -rGeo.nTan ); 1981 1982 1983 if ( rGraphic.GetPrefMapMode().GetMapUnit() == MAP_PIXEL ) 1984 aGraphSize = rCmpWnd.PixelToLogic( rGraphic.GetPrefSize(), 1985 aMap100 ); 1986 else 1987 aGraphSize = OutputDevice::LogicToLogic( rGraphic.GetPrefSize(), 1988 rGraphic.GetPrefMapMode(), 1989 aMap100 ); 1990 1991 bObjSupported = sal_True; 1992 } 1993 else if ( pObj->ISA( SdrOle2Obj ) ) // OLE-Objekt 1994 { 1995 // TODO/LEAN: working with visual area needs running state 1996 aGraphSize = ((SdrOle2Obj*)pObj)->GetOrigObjSize(); 1997 bObjSupported = sal_True; 1998 } 1999 2000 // hat alles geklappt, dann HitTest ausfuehren 2001 if ( bObjSupported ) 2002 { 2003 // relativen Mauspunkt berechnen 2004 aRelPoint -= aLogRect.TopLeft(); 2005 pIMapObj = rImageMap.GetHitIMapObject( aGraphSize, aLogRect.GetSize(), aRelPoint ); 2006 } 2007 } 2008 2009 return pIMapObj; 2010 } 2011 2012 ScMacroInfo* ScDrawLayer::GetMacroInfo( SdrObject* pObj, sal_Bool bCreate ) // static 2013 { 2014 sal_uInt16 nCount = pObj->GetUserDataCount(); 2015 for( sal_uInt16 i = 0; i < nCount; i++ ) 2016 { 2017 SdrObjUserData* pData = pObj->GetUserData( i ); 2018 if( pData && pData->GetInventor() == SC_DRAWLAYER 2019 && pData->GetId() == SC_UD_MACRODATA ) 2020 return (ScMacroInfo*) pData; 2021 } 2022 if ( bCreate ) 2023 { 2024 ScMacroInfo* pData = new ScMacroInfo; 2025 pObj->InsertUserData( pData, 0 ); 2026 return pData; 2027 } 2028 return 0; 2029 } 2030 ImageMap* ScDrawLayer::GetImageMapForObject(SdrObject* pObj) 2031 { 2032 ScIMapInfo* pIMapInfo = const_cast<ScIMapInfo*>( GetIMapInfo( pObj ) ); 2033 if ( pIMapInfo ) 2034 { 2035 return const_cast<ImageMap*>( &(pIMapInfo->GetImageMap()) ); 2036 } 2037 return NULL; 2038 } 2039 2040 sal_Int32 ScDrawLayer::GetHyperlinkCount(SdrObject* pObj) 2041 { 2042 sal_Int32 nHLCount = 0; 2043 ScMacroInfo* pMacroInfo = GetMacroInfo(pObj, sal_False); 2044 if (pMacroInfo) 2045 // MT IA2: GetHlink*( doesn|t exist in DEV300 anymore... 2046 nHLCount = 0; // pMacroInfo->GetHlink().getLength() > 0 ? 1 : 0; 2047 return nHLCount; 2048 } 2049 void ScDrawLayer::SetGlobalDrawPersist(SfxObjectShell* pPersist) // static 2050 { 2051 DBG_ASSERT(!pGlobalDrawPersist,"SetGlobalDrawPersist mehrfach"); 2052 pGlobalDrawPersist = pPersist; 2053 } 2054 2055 void __EXPORT ScDrawLayer::SetChanged( sal_Bool bFlg /* = sal_True */ ) 2056 { 2057 if ( bFlg && pDoc ) 2058 pDoc->SetChartListenerCollectionNeedsUpdate( sal_True ); 2059 FmFormModel::SetChanged( bFlg ); 2060 } 2061 2062 SvStream* __EXPORT ScDrawLayer::GetDocumentStream(SdrDocumentStreamInfo& rStreamInfo) const 2063 { 2064 DBG_ASSERT( pDoc, "ScDrawLayer::GetDocumentStream without document" ); 2065 if ( !pDoc ) 2066 return NULL; 2067 2068 uno::Reference< embed::XStorage > xStorage = pDoc->GetDocumentShell() ? 2069 pDoc->GetDocumentShell()->GetStorage() : 2070 NULL; 2071 SvStream* pRet = NULL; 2072 2073 if( xStorage.is() ) 2074 { 2075 if( rStreamInfo.maUserData.Len() && 2076 ( rStreamInfo.maUserData.GetToken( 0, ':' ) == 2077 String( RTL_CONSTASCII_USTRINGPARAM( "vnd.sun.star.Package" ) ) ) ) 2078 { 2079 const String aPicturePath( rStreamInfo.maUserData.GetToken( 1, ':' ) ); 2080 2081 // graphic from picture stream in picture storage in XML package 2082 if( aPicturePath.GetTokenCount( '/' ) == 2 ) 2083 { 2084 const String aPictureStreamName( aPicturePath.GetToken( 1, '/' ) ); 2085 const String aPictureStorageName( aPicturePath.GetToken( 0, '/' ) ); 2086 2087 try { 2088 if ( xStorage->isStorageElement( aPictureStorageName ) ) 2089 { 2090 uno::Reference< embed::XStorage > xPictureStorage = 2091 xStorage->openStorageElement( aPictureStorageName, embed::ElementModes::READ ); 2092 2093 if( xPictureStorage.is() && 2094 xPictureStorage->isStreamElement( aPictureStreamName ) ) 2095 { 2096 uno::Reference< io::XStream > xStream = 2097 xPictureStorage->openStreamElement( aPictureStreamName, embed::ElementModes::READ ); 2098 if ( xStream.is() ) 2099 pRet = ::utl::UcbStreamHelper::CreateStream( xStream ); 2100 } 2101 } 2102 } 2103 catch( uno::Exception& ) 2104 { 2105 // TODO: error handling 2106 } 2107 } 2108 } 2109 // the following code seems to be related to binary format 2110 //REMOVE else 2111 //REMOVE { 2112 //REMOVE pRet = pStor->OpenStream( String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM(STRING_SCSTREAM)), 2113 //REMOVE STREAM_READ | STREAM_WRITE | STREAM_TRUNC ); 2114 //REMOVE 2115 //REMOVE if( pRet ) 2116 //REMOVE { 2117 //REMOVE pRet->SetVersion( pStor->GetVersion() ); 2118 //REMOVE pRet->SetKey( pStor->GetKey() ); 2119 //REMOVE } 2120 //REMOVE } 2121 2122 rStreamInfo.mbDeleteAfterUse = ( pRet != NULL ); 2123 } 2124 2125 return pRet; 2126 } 2127 2128 //REMOVE void ScDrawLayer::ReleasePictureStorage() 2129 //REMOVE { 2130 //REMOVE xPictureStorage.Clear(); 2131 //REMOVE } 2132 2133 SdrLayerID __EXPORT ScDrawLayer::GetControlExportLayerId( const SdrObject & ) const 2134 { 2135 // Layer fuer Export von Form-Controls in Versionen vor 5.0 - immer SC_LAYER_FRONT 2136 return SC_LAYER_FRONT; 2137 } 2138 2139 ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > ScDrawLayer::createUnoModel() 2140 { 2141 ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > xRet; 2142 if( pDoc && pDoc->GetDocumentShell() ) 2143 xRet = pDoc->GetDocumentShell()->GetModel(); 2144 2145 return xRet; 2146 } 2147