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