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 sal_True ), // bUseExtColorTable (is set below) 211 aName( rName ), 212 pDoc( pDocument ), 213 pUndoGroup( NULL ), 214 bRecording( sal_False ), 215 bAdjustEnabled( sal_True ), 216 bHyphenatorSet( sal_False ), 217 mbUndoAllowed( sal_True ) 218 { 219 pGlobalDrawPersist = NULL; // nur einmal benutzen 220 221 SfxObjectShell* pObjSh = pDocument ? pDocument->GetDocumentShell() : NULL; 222 if ( pObjSh ) 223 { 224 SetObjectShell( pObjSh ); 225 226 // set color table 227 SvxColorTableItem* pColItem = (SvxColorTableItem*) pObjSh->GetItem( SID_COLOR_TABLE ); 228 XColorTable* pXCol = pColItem ? pColItem->GetColorTable() : XColorTable::GetStdColorTable(); 229 SetColorTable( pXCol ); 230 } 231 else 232 SetColorTable( XColorTable::GetStdColorTable() ); 233 234 SetSwapGraphics(sal_True); 235 // SetSwapAsynchron(sal_True); // an der View 236 237 SetScaleUnit(MAP_100TH_MM); 238 SfxItemPool& rPool = GetItemPool(); 239 rPool.SetDefaultMetric(SFX_MAPUNIT_100TH_MM); 240 SvxFrameDirectionItem aModeItem( FRMDIR_ENVIRONMENT, EE_PARA_WRITINGDIR ); 241 rPool.SetPoolDefaultItem( aModeItem ); 242 243 // #i33700# 244 // Set shadow distance defaults as PoolDefaultItems. Details see bug. 245 rPool.SetPoolDefaultItem(SdrShadowXDistItem(300)); 246 rPool.SetPoolDefaultItem(SdrShadowYDistItem(300)); 247 248 // #111216# default for script spacing depends on locale, see SdDrawDocument ctor in sd 249 LanguageType eOfficeLanguage = Application::GetSettings().GetLanguage(); 250 if ( eOfficeLanguage == LANGUAGE_KOREAN || eOfficeLanguage == LANGUAGE_KOREAN_JOHAB || 251 eOfficeLanguage == LANGUAGE_JAPANESE ) 252 { 253 // secondary is edit engine pool 254 rPool.GetSecondaryPool()->SetPoolDefaultItem( SvxScriptSpaceItem( sal_False, EE_PARA_ASIANCJKSPACING ) ); 255 } 256 257 rPool.FreezeIdRanges(); // the pool is also used directly 258 259 SdrLayerAdmin& rAdmin = GetLayerAdmin(); 260 rAdmin.NewLayer(String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("vorne")), SC_LAYER_FRONT); 261 rAdmin.NewLayer(String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("hinten")), SC_LAYER_BACK); 262 rAdmin.NewLayer(String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("intern")), SC_LAYER_INTERN); 263 rAdmin.NewLayer(String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("Controls")), SC_LAYER_CONTROLS); 264 rAdmin.NewLayer(String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("hidden")), SC_LAYER_HIDDEN); 265 // "Controls" is new - must also be created when loading 266 267 // Link fuer URL-Fields setzen 268 ScModule* pScMod = SC_MOD(); 269 Outliner& rOutliner = GetDrawOutliner(); 270 rOutliner.SetCalcFieldValueHdl( LINK( pScMod, ScModule, CalcFieldValueHdl ) ); 271 272 Outliner& rHitOutliner = GetHitTestOutliner(); 273 rHitOutliner.SetCalcFieldValueHdl( LINK( pScMod, ScModule, CalcFieldValueHdl ) ); 274 275 // #95129# SJ: set FontHeight pool defaults without changing static SdrEngineDefaults 276 SfxItemPool* pOutlinerPool = rOutliner.GetEditTextObjectPool(); 277 if ( pOutlinerPool ) 278 pItemPool->SetPoolDefaultItem(SvxFontHeightItem( 423, 100, EE_CHAR_FONTHEIGHT )); // 12Pt 279 SfxItemPool* pHitOutlinerPool = rHitOutliner.GetEditTextObjectPool(); 280 if ( pHitOutlinerPool ) 281 pHitOutlinerPool->SetPoolDefaultItem(SvxFontHeightItem( 423, 100, EE_CHAR_FONTHEIGHT )); // 12Pt 282 283 // initial undo mode as in Calc document 284 if( pDoc ) 285 EnableUndo( pDoc->IsUndoEnabled() ); 286 287 // URL-Buttons haben keinen Handler mehr, machen alles selber 288 289 if( !nInst++ ) 290 { 291 pFac = new ScDrawObjFactory; 292 pF3d = new E3dObjFactory; 293 } 294 } 295 296 __EXPORT ScDrawLayer::~ScDrawLayer() 297 { 298 Broadcast(SdrHint(HINT_MODELCLEARED)); 299 300 // #116168# 301 //Clear(); 302 ClearModel(sal_True); 303 304 delete pUndoGroup; 305 if( !--nInst ) 306 { 307 delete pFac, pFac = NULL; 308 delete pF3d, pF3d = NULL; 309 } 310 } 311 312 void ScDrawLayer::UseHyphenator() 313 { 314 if (!bHyphenatorSet) 315 { 316 com::sun::star::uno::Reference< com::sun::star::linguistic2::XHyphenator > 317 xHyphenator = LinguMgr::GetHyphenator(); 318 319 GetDrawOutliner().SetHyphenator( xHyphenator ); 320 GetHitTestOutliner().SetHyphenator( xHyphenator ); 321 322 bHyphenatorSet = sal_True; 323 } 324 } 325 326 SdrPage* __EXPORT ScDrawLayer::AllocPage(FASTBOOL bMasterPage) 327 { 328 // don't create basic until it is needed 329 StarBASIC* pBasic = NULL; 330 ScDrawPage* pPage = new ScDrawPage( *this, pBasic, sal::static_int_cast<sal_Bool>(bMasterPage) ); 331 return pPage; 332 } 333 334 sal_Bool ScDrawLayer::HasObjects() const 335 { 336 sal_Bool bFound = sal_False; 337 338 sal_uInt16 nCount = GetPageCount(); 339 for (sal_uInt16 i=0; i<nCount && !bFound; i++) 340 if (GetPage(i)->GetObjCount()) 341 bFound = sal_True; 342 343 return bFound; 344 } 345 346 void ScDrawLayer::UpdateBasic() 347 { 348 // don't create basic until it is needed 349 //! remove this method? 350 } 351 352 SdrModel* __EXPORT ScDrawLayer::AllocModel() const 353 { 354 // #103849# Allocated model (for clipboard etc) must not have a pointer 355 // to the original model's document, pass NULL as document: 356 357 return new ScDrawLayer( NULL, aName ); 358 } 359 360 Window* __EXPORT ScDrawLayer::GetCurDocViewWin() 361 { 362 DBG_ASSERT( pDoc, "ScDrawLayer::GetCurDocViewWin without document" ); 363 if ( !pDoc ) 364 return NULL; 365 366 SfxViewShell* pViewSh = SfxViewShell::Current(); 367 SfxObjectShell* pObjSh = pDoc->GetDocumentShell(); 368 369 if (pViewSh && pViewSh->GetObjectShell() == pObjSh) 370 return pViewSh->GetWindow(); 371 372 return NULL; 373 } 374 375 sal_Bool ScDrawLayer::ScAddPage( SCTAB nTab ) 376 { 377 if (bDrawIsInUndo) 378 return sal_False; // not inserted 379 380 ScDrawPage* pPage = (ScDrawPage*)AllocPage( sal_False ); 381 InsertPage(pPage, static_cast<sal_uInt16>(nTab)); 382 if (bRecording) 383 AddCalcUndo< SdrUndoNewPage >(*pPage); 384 385 return sal_True; // inserted 386 } 387 388 void ScDrawLayer::ScRemovePage( SCTAB nTab ) 389 { 390 if (bDrawIsInUndo) 391 return; 392 393 Broadcast( ScTabDeletedHint( nTab ) ); 394 if (bRecording) 395 { 396 SdrPage* pPage = GetPage(static_cast<sal_uInt16>(nTab)); 397 AddCalcUndo< SdrUndoDelPage >(*pPage); // Undo-Action wird Owner der Page 398 RemovePage( static_cast<sal_uInt16>(nTab) ); // nur austragen, nicht loeschen 399 } 400 else 401 DeletePage( static_cast<sal_uInt16>(nTab) ); // einfach weg damit 402 } 403 404 void ScDrawLayer::ScRenamePage( SCTAB nTab, const String& rNewName ) 405 { 406 ScDrawPage* pPage = (ScDrawPage*) GetPage(static_cast<sal_uInt16>(nTab)); 407 if (pPage) 408 pPage->SetName(rNewName); 409 } 410 411 void ScDrawLayer::ScMovePage( sal_uInt16 nOldPos, sal_uInt16 nNewPos ) 412 { 413 MovePage( nOldPos, nNewPos ); 414 } 415 416 void ScDrawLayer::ScCopyPage( sal_uInt16 nOldPos, sal_uInt16 nNewPos, sal_Bool bAlloc ) 417 { 418 //! remove argument bAlloc (always sal_False) 419 420 if (bDrawIsInUndo) 421 return; 422 423 SdrPage* pOldPage = GetPage(nOldPos); 424 SdrPage* pNewPage = bAlloc ? AllocPage(sal_False) : GetPage(nNewPos); 425 426 // kopieren 427 428 if (pOldPage && pNewPage) 429 { 430 SdrObjListIter aIter( *pOldPage, IM_FLAT ); 431 SdrObject* pOldObject = aIter.Next(); 432 while (pOldObject) 433 { 434 // #i112034# do not copy internal objects (detective) and note captions 435 if ( pOldObject->GetLayer() != SC_LAYER_INTERN && !IsNoteCaption( pOldObject ) ) 436 { 437 // #116235# 438 SdrObject* pNewObject = pOldObject->Clone(); 439 //SdrObject* pNewObject = pOldObject->Clone( pNewPage, this ); 440 pNewObject->SetModel(this); 441 pNewObject->SetPage(pNewPage); 442 443 pNewObject->NbcMove(Size(0,0)); 444 pNewPage->InsertObject( pNewObject ); 445 if (bRecording) 446 AddCalcUndo< SdrUndoInsertObj >( *pNewObject ); 447 } 448 449 pOldObject = aIter.Next(); 450 } 451 } 452 453 if (bAlloc) 454 InsertPage(pNewPage, nNewPos); 455 } 456 457 inline sal_Bool IsInBlock( const ScAddress& rPos, SCCOL nCol1,SCROW nRow1, SCCOL nCol2,SCROW nRow2 ) 458 { 459 return rPos.Col() >= nCol1 && rPos.Col() <= nCol2 && 460 rPos.Row() >= nRow1 && rPos.Row() <= nRow2; 461 } 462 463 void ScDrawLayer::MoveCells( SCTAB nTab, SCCOL nCol1,SCROW nRow1, SCCOL nCol2,SCROW nRow2, 464 SCsCOL nDx,SCsROW nDy, bool bUpdateNoteCaptionPos ) 465 { 466 SdrPage* pPage = GetPage(static_cast<sal_uInt16>(nTab)); 467 DBG_ASSERT(pPage,"Page nicht gefunden"); 468 if (!pPage) 469 return; 470 471 sal_Bool bNegativePage = pDoc && pDoc->IsNegativePage( nTab ); 472 473 sal_uLong nCount = pPage->GetObjCount(); 474 for ( sal_uLong i = 0; i < nCount; i++ ) 475 { 476 SdrObject* pObj = pPage->GetObj( i ); 477 ScDrawObjData* pData = GetObjDataTab( pObj, nTab ); 478 if( pData ) 479 { 480 const ScAddress aOldStt = pData->maStart; 481 const ScAddress aOldEnd = pData->maEnd; 482 sal_Bool bChange = sal_False; 483 if ( aOldStt.IsValid() && IsInBlock( aOldStt, nCol1,nRow1, nCol2,nRow2 ) ) 484 { 485 pData->maStart.IncCol( nDx ); 486 pData->maStart.IncRow( nDy ); 487 bChange = sal_True; 488 } 489 if ( aOldEnd.IsValid() && IsInBlock( aOldEnd, nCol1,nRow1, nCol2,nRow2 ) ) 490 { 491 pData->maEnd.IncCol( nDx ); 492 pData->maEnd.IncRow( nDy ); 493 bChange = sal_True; 494 } 495 if (bChange) 496 { 497 if ( pObj->ISA( SdrRectObj ) && pData->maStart.IsValid() && pData->maEnd.IsValid() ) 498 pData->maStart.PutInOrder( pData->maEnd ); 499 AddCalcUndo< ScUndoObjData >( pObj, aOldStt, aOldEnd, pData->maStart, pData->maEnd ); 500 RecalcPos( pObj, *pData, bNegativePage, bUpdateNoteCaptionPos ); 501 } 502 } 503 } 504 } 505 506 void ScDrawLayer::SetPageSize( sal_uInt16 nPageNo, const Size& rSize, bool bUpdateNoteCaptionPos ) 507 { 508 SdrPage* pPage = GetPage(nPageNo); 509 if (pPage) 510 { 511 if ( rSize != pPage->GetSize() ) 512 { 513 pPage->SetSize( rSize ); 514 Broadcast( ScTabSizeChangedHint( static_cast<SCTAB>(nPageNo) ) ); // SetWorkArea() an den Views 515 } 516 517 // Detektivlinien umsetzen (an neue Hoehen/Breiten anpassen) 518 // auch wenn Groesse gleich geblieben ist 519 // (einzelne Zeilen/Spalten koennen geaendert sein) 520 521 sal_Bool bNegativePage = pDoc && pDoc->IsNegativePage( static_cast<SCTAB>(nPageNo) ); 522 523 sal_uLong nCount = pPage->GetObjCount(); 524 for ( sal_uLong i = 0; i < nCount; i++ ) 525 { 526 SdrObject* pObj = pPage->GetObj( i ); 527 ScDrawObjData* pData = GetObjDataTab( pObj, static_cast<SCTAB>(nPageNo) ); 528 if( pData ) 529 RecalcPos( pObj, *pData, bNegativePage, bUpdateNoteCaptionPos ); 530 } 531 } 532 } 533 534 void ScDrawLayer::RecalcPos( SdrObject* pObj, const ScDrawObjData& rData, bool bNegativePage, bool bUpdateNoteCaptionPos ) 535 { 536 DBG_ASSERT( pDoc, "ScDrawLayer::RecalcPos - missing document" ); 537 if( !pDoc ) 538 return; 539 540 if( rData.mbNote ) 541 { 542 DBG_ASSERT( rData.maStart.IsValid(), "ScDrawLayer::RecalcPos - invalid position for cell note" ); 543 /* #i109372# On insert/remove rows/columns/cells: Updating the caption 544 position must not be done, if the cell containing the note has not 545 been moved yet in the document. The calling code now passes an 546 additional boolean stating if the cells are already moved. */ 547 if( bUpdateNoteCaptionPos ) 548 /* When inside an undo action, there may be pending note captions 549 where cell note is already deleted (thus document cannot find 550 the note object anymore). The caption will be deleted later 551 with drawing undo. */ 552 if( ScPostIt* pNote = pDoc->GetNote( rData.maStart ) ) 553 pNote->UpdateCaptionPos( rData.maStart ); 554 return; 555 } 556 557 bool bValid1 = rData.maStart.IsValid(); 558 SCCOL nCol1 = rData.maStart.Col(); 559 SCROW nRow1 = rData.maStart.Row(); 560 SCTAB nTab1 = rData.maStart.Tab(); 561 bool bValid2 = rData.maEnd.IsValid(); 562 SCCOL nCol2 = rData.maEnd.Col(); 563 SCROW nRow2 = rData.maEnd.Row(); 564 SCTAB nTab2 = rData.maEnd.Tab(); 565 566 // validation circle 567 bool bCircle = pObj->ISA( SdrCircObj ); 568 // detective arrow 569 bool bArrow = pObj->IsPolyObj() && (pObj->GetPointCount() == 2); 570 571 if( bCircle ) 572 { 573 Point aPos( pDoc->GetColOffset( nCol1, nTab1 ), pDoc->GetRowOffset( nRow1, nTab1 ) ); 574 TwipsToMM( aPos.X() ); 575 TwipsToMM( aPos.Y() ); 576 577 // Berechnung und Werte wie in detfunc.cxx 578 579 Size aSize( (long)(pDoc->GetColWidth( nCol1, nTab1 ) * HMM_PER_TWIPS), 580 (long)(pDoc->GetRowHeight( nRow1, nTab1 ) * HMM_PER_TWIPS) ); 581 Rectangle aRect( aPos, aSize ); 582 aRect.Left() -= 250; 583 aRect.Right() += 250; 584 aRect.Top() -= 70; 585 aRect.Bottom() += 70; 586 if ( bNegativePage ) 587 MirrorRectRTL( aRect ); 588 589 if ( pObj->GetLogicRect() != aRect ) 590 { 591 if (bRecording) 592 AddCalcUndo<SdrUndoGeoObj>( *pObj ); 593 pObj->SetLogicRect(aRect); 594 } 595 } 596 else if( bArrow ) 597 { 598 //! nicht mehrere Undos fuer ein Objekt erzeugen (hinteres kann dann weggelassen werden) 599 600 SCCOL nLastCol; 601 SCROW nLastRow; 602 if( bValid1 ) 603 { 604 Point aPos( pDoc->GetColOffset( nCol1, nTab1 ), pDoc->GetRowOffset( nRow1, nTab1 ) ); 605 if (!pDoc->ColHidden(nCol1, nTab1, nLastCol)) 606 aPos.X() += pDoc->GetColWidth( nCol1, nTab1 ) / 4; 607 if (!pDoc->RowHidden(nRow1, nTab1, nLastRow)) 608 aPos.Y() += pDoc->GetRowHeight( nRow1, nTab1 ) / 2; 609 TwipsToMM( aPos.X() ); 610 TwipsToMM( aPos.Y() ); 611 Point aStartPos = aPos; 612 if ( bNegativePage ) 613 aStartPos.X() = -aStartPos.X(); // don't modify aPos - used below 614 if ( pObj->GetPoint( 0 ) != aStartPos ) 615 { 616 if (bRecording) 617 AddCalcUndo< SdrUndoGeoObj> ( *pObj ); 618 pObj->SetPoint( aStartPos, 0 ); 619 } 620 621 if( !bValid2 ) 622 { 623 Point aEndPos( aPos.X() + DET_ARROW_OFFSET, aPos.Y() - DET_ARROW_OFFSET ); 624 if (aEndPos.Y() < 0) 625 aEndPos.Y() += (2 * DET_ARROW_OFFSET); 626 if ( bNegativePage ) 627 aEndPos.X() = -aEndPos.X(); 628 if ( pObj->GetPoint( 1 ) != aEndPos ) 629 { 630 if (bRecording) 631 AddCalcUndo< SdrUndoGeoObj >( *pObj ); 632 pObj->SetPoint( aEndPos, 1 ); 633 } 634 } 635 } 636 if( bValid2 ) 637 { 638 Point aPos( pDoc->GetColOffset( nCol2, nTab2 ), pDoc->GetRowOffset( nRow2, nTab2 ) ); 639 if (!pDoc->ColHidden(nCol2, nTab2, nLastCol)) 640 aPos.X() += pDoc->GetColWidth( nCol2, nTab2 ) / 4; 641 if (!pDoc->RowHidden(nRow2, nTab2, nLastRow)) 642 aPos.Y() += pDoc->GetRowHeight( nRow2, nTab2 ) / 2; 643 TwipsToMM( aPos.X() ); 644 TwipsToMM( aPos.Y() ); 645 Point aEndPos = aPos; 646 if ( bNegativePage ) 647 aEndPos.X() = -aEndPos.X(); // don't modify aPos - used below 648 if ( pObj->GetPoint( 1 ) != aEndPos ) 649 { 650 if (bRecording) 651 AddCalcUndo< SdrUndoGeoObj> ( *pObj ); 652 pObj->SetPoint( aEndPos, 1 ); 653 } 654 655 if( !bValid1 ) 656 { 657 Point aStartPos( aPos.X() - DET_ARROW_OFFSET, aPos.Y() - DET_ARROW_OFFSET ); 658 if (aStartPos.X() < 0) 659 aStartPos.X() += (2 * DET_ARROW_OFFSET); 660 if (aStartPos.Y() < 0) 661 aStartPos.Y() += (2 * DET_ARROW_OFFSET); 662 if ( bNegativePage ) 663 aStartPos.X() = -aStartPos.X(); 664 if ( pObj->GetPoint( 0 ) != aStartPos ) 665 { 666 if (bRecording) 667 AddCalcUndo< SdrUndoGeoObj >( *pObj ); 668 pObj->SetPoint( aStartPos, 0 ); 669 } 670 } 671 } 672 } 673 else // Referenz-Rahmen 674 { 675 DBG_ASSERT( bValid1, "ScDrawLayer::RecalcPos - invalid start position" ); 676 Point aPos( pDoc->GetColOffset( nCol1, nTab1 ), pDoc->GetRowOffset( nRow1, nTab1 ) ); 677 TwipsToMM( aPos.X() ); 678 TwipsToMM( aPos.Y() ); 679 680 if( bValid2 ) 681 { 682 Point aEnd( pDoc->GetColOffset( nCol2 + 1, nTab2 ), pDoc->GetRowOffset( nRow2 + 1, nTab2 ) ); 683 TwipsToMM( aEnd.X() ); 684 TwipsToMM( aEnd.Y() ); 685 686 Rectangle aNew( aPos, aEnd ); 687 if ( bNegativePage ) 688 MirrorRectRTL( aNew ); 689 if ( pObj->GetLogicRect() != aNew ) 690 { 691 if (bRecording) 692 AddCalcUndo< SdrUndoGeoObj >( *pObj ); 693 pObj->SetLogicRect(aNew); 694 } 695 } 696 else 697 { 698 if ( bNegativePage ) 699 aPos.X() = -aPos.X(); 700 if ( pObj->GetRelativePos() != aPos ) 701 { 702 if (bRecording) 703 AddCalcUndo< SdrUndoGeoObj >( *pObj ); 704 pObj->SetRelativePos( aPos ); 705 } 706 } 707 } 708 } 709 710 sal_Bool ScDrawLayer::GetPrintArea( ScRange& rRange, sal_Bool bSetHor, sal_Bool bSetVer ) const 711 { 712 DBG_ASSERT( pDoc, "ScDrawLayer::GetPrintArea without document" ); 713 if ( !pDoc ) 714 return sal_False; 715 716 SCTAB nTab = rRange.aStart.Tab(); 717 DBG_ASSERT( rRange.aEnd.Tab() == nTab, "GetPrintArea: Tab unterschiedlich" ); 718 719 sal_Bool bNegativePage = pDoc->IsNegativePage( nTab ); 720 721 sal_Bool bAny = sal_False; 722 long nEndX = 0; 723 long nEndY = 0; 724 long nStartX = LONG_MAX; 725 long nStartY = LONG_MAX; 726 727 // Grenzen ausrechnen 728 729 if (!bSetHor) 730 { 731 nStartX = 0; 732 SCCOL nStartCol = rRange.aStart.Col(); 733 SCCOL i; 734 for (i=0; i<nStartCol; i++) 735 nStartX +=pDoc->GetColWidth(i,nTab); 736 nEndX = nStartX; 737 SCCOL nEndCol = rRange.aEnd.Col(); 738 for (i=nStartCol; i<=nEndCol; i++) 739 nEndX += pDoc->GetColWidth(i,nTab); 740 nStartX = (long)(nStartX * HMM_PER_TWIPS); 741 nEndX = (long)(nEndX * HMM_PER_TWIPS); 742 } 743 if (!bSetVer) 744 { 745 nStartY = pDoc->GetRowHeight( 0, rRange.aStart.Row()-1, nTab); 746 nEndY = nStartY + pDoc->GetRowHeight( rRange.aStart.Row(), 747 rRange.aEnd.Row(), nTab); 748 nStartY = (long)(nStartY * HMM_PER_TWIPS); 749 nEndY = (long)(nEndY * HMM_PER_TWIPS); 750 } 751 752 if ( bNegativePage ) 753 { 754 nStartX = -nStartX; // positions are negative, swap start/end so the same comparisons work 755 nEndX = -nEndX; 756 ::std::swap( nStartX, nEndX ); 757 } 758 759 const SdrPage* pPage = GetPage(static_cast<sal_uInt16>(nTab)); 760 DBG_ASSERT(pPage,"Page nicht gefunden"); 761 if (pPage) 762 { 763 SdrObjListIter aIter( *pPage, IM_FLAT ); 764 SdrObject* pObject = aIter.Next(); 765 while (pObject) 766 { 767 //! Flags (ausgeblendet?) testen 768 769 Rectangle aObjRect = pObject->GetCurrentBoundRect(); 770 sal_Bool bFit = sal_True; 771 if ( !bSetHor && ( aObjRect.Right() < nStartX || aObjRect.Left() > nEndX ) ) 772 bFit = sal_False; 773 if ( !bSetVer && ( aObjRect.Bottom() < nStartY || aObjRect.Top() > nEndY ) ) 774 bFit = sal_False; 775 // #i104716# don't include hidden note objects 776 if ( bFit && pObject->GetLayer() != SC_LAYER_HIDDEN ) 777 { 778 if (bSetHor) 779 { 780 if (aObjRect.Left() < nStartX) nStartX = aObjRect.Left(); 781 if (aObjRect.Right() > nEndX) nEndX = aObjRect.Right(); 782 } 783 if (bSetVer) 784 { 785 if (aObjRect.Top() < nStartY) nStartY = aObjRect.Top(); 786 if (aObjRect.Bottom() > nEndY) nEndY = aObjRect.Bottom(); 787 } 788 bAny = sal_True; 789 } 790 791 pObject = aIter.Next(); 792 } 793 } 794 795 if ( bNegativePage ) 796 { 797 nStartX = -nStartX; // reverse transformation, so the same cell address calculation works 798 nEndX = -nEndX; 799 ::std::swap( nStartX, nEndX ); 800 } 801 802 if (bAny) 803 { 804 DBG_ASSERT( nStartX<=nEndX && nStartY<=nEndY, "Start/End falsch in ScDrawLayer::GetPrintArea" ); 805 806 if (bSetHor) 807 { 808 nStartX = (long) (nStartX / HMM_PER_TWIPS); 809 nEndX = (long) (nEndX / HMM_PER_TWIPS); 810 long nWidth; 811 SCCOL i; 812 813 nWidth = 0; 814 for (i=0; i<=MAXCOL && nWidth<=nStartX; i++) 815 nWidth += pDoc->GetColWidth(i,nTab); 816 rRange.aStart.SetCol( i>0 ? (i-1) : 0 ); 817 818 nWidth = 0; 819 for (i=0; i<=MAXCOL && nWidth<=nEndX; i++) //! bei Start anfangen 820 nWidth += pDoc->GetColWidth(i,nTab); 821 rRange.aEnd.SetCol( i>0 ? (i-1) : 0 ); 822 } 823 824 if (bSetVer) 825 { 826 nStartY = (long) (nStartY / HMM_PER_TWIPS); 827 nEndY = (long) (nEndY / HMM_PER_TWIPS); 828 SCROW nRow = pDoc->GetRowForHeight( nTab, nStartY); 829 rRange.aStart.SetRow( nRow>0 ? (nRow-1) : 0); 830 nRow = pDoc->GetRowForHeight( nTab, nEndY); 831 rRange.aEnd.SetRow( nRow == MAXROW ? MAXROW : 832 (nRow>0 ? (nRow-1) : 0)); 833 } 834 } 835 else 836 { 837 if (bSetHor) 838 { 839 rRange.aStart.SetCol(0); 840 rRange.aEnd.SetCol(0); 841 } 842 if (bSetVer) 843 { 844 rRange.aStart.SetRow(0); 845 rRange.aEnd.SetRow(0); 846 } 847 } 848 return bAny; 849 } 850 851 void ScDrawLayer::AddCalcUndo( SdrUndoAction* pUndo ) 852 { 853 if (bRecording) 854 { 855 if (!pUndoGroup) 856 pUndoGroup = new SdrUndoGroup(*this); 857 858 pUndoGroup->AddAction( pUndo ); 859 } 860 else 861 delete pUndo; 862 } 863 864 void ScDrawLayer::BeginCalcUndo() 865 { 866 //! DBG_ASSERT( !bRecording, "BeginCalcUndo ohne GetCalcUndo" ); 867 868 DELETEZ(pUndoGroup); 869 bRecording = sal_True; 870 } 871 872 SdrUndoGroup* ScDrawLayer::GetCalcUndo() 873 { 874 //! DBG_ASSERT( bRecording, "GetCalcUndo ohne BeginCalcUndo" ); 875 876 SdrUndoGroup* pRet = pUndoGroup; 877 pUndoGroup = NULL; 878 bRecording = sal_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 2031 void ScDrawLayer::SetGlobalDrawPersist(SfxObjectShell* pPersist) // static 2032 { 2033 DBG_ASSERT(!pGlobalDrawPersist,"SetGlobalDrawPersist mehrfach"); 2034 pGlobalDrawPersist = pPersist; 2035 } 2036 2037 void __EXPORT ScDrawLayer::SetChanged( sal_Bool bFlg /* = sal_True */ ) 2038 { 2039 if ( bFlg && pDoc ) 2040 pDoc->SetChartListenerCollectionNeedsUpdate( sal_True ); 2041 FmFormModel::SetChanged( bFlg ); 2042 } 2043 2044 SvStream* __EXPORT ScDrawLayer::GetDocumentStream(SdrDocumentStreamInfo& rStreamInfo) const 2045 { 2046 DBG_ASSERT( pDoc, "ScDrawLayer::GetDocumentStream without document" ); 2047 if ( !pDoc ) 2048 return NULL; 2049 2050 uno::Reference< embed::XStorage > xStorage = pDoc->GetDocumentShell() ? 2051 pDoc->GetDocumentShell()->GetStorage() : 2052 NULL; 2053 SvStream* pRet = NULL; 2054 2055 if( xStorage.is() ) 2056 { 2057 if( rStreamInfo.maUserData.Len() && 2058 ( rStreamInfo.maUserData.GetToken( 0, ':' ) == 2059 String( RTL_CONSTASCII_USTRINGPARAM( "vnd.sun.star.Package" ) ) ) ) 2060 { 2061 const String aPicturePath( rStreamInfo.maUserData.GetToken( 1, ':' ) ); 2062 2063 // graphic from picture stream in picture storage in XML package 2064 if( aPicturePath.GetTokenCount( '/' ) == 2 ) 2065 { 2066 const String aPictureStreamName( aPicturePath.GetToken( 1, '/' ) ); 2067 const String aPictureStorageName( aPicturePath.GetToken( 0, '/' ) ); 2068 2069 try { 2070 if ( xStorage->isStorageElement( aPictureStorageName ) ) 2071 { 2072 uno::Reference< embed::XStorage > xPictureStorage = 2073 xStorage->openStorageElement( aPictureStorageName, embed::ElementModes::READ ); 2074 2075 if( xPictureStorage.is() && 2076 xPictureStorage->isStreamElement( aPictureStreamName ) ) 2077 { 2078 uno::Reference< io::XStream > xStream = 2079 xPictureStorage->openStreamElement( aPictureStreamName, embed::ElementModes::READ ); 2080 if ( xStream.is() ) 2081 pRet = ::utl::UcbStreamHelper::CreateStream( xStream ); 2082 } 2083 } 2084 } 2085 catch( uno::Exception& ) 2086 { 2087 // TODO: error handling 2088 } 2089 } 2090 } 2091 // the following code seems to be related to binary format 2092 //REMOVE else 2093 //REMOVE { 2094 //REMOVE pRet = pStor->OpenStream( String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM(STRING_SCSTREAM)), 2095 //REMOVE STREAM_READ | STREAM_WRITE | STREAM_TRUNC ); 2096 //REMOVE 2097 //REMOVE if( pRet ) 2098 //REMOVE { 2099 //REMOVE pRet->SetVersion( pStor->GetVersion() ); 2100 //REMOVE pRet->SetKey( pStor->GetKey() ); 2101 //REMOVE } 2102 //REMOVE } 2103 2104 rStreamInfo.mbDeleteAfterUse = ( pRet != NULL ); 2105 } 2106 2107 return pRet; 2108 } 2109 2110 //REMOVE void ScDrawLayer::ReleasePictureStorage() 2111 //REMOVE { 2112 //REMOVE xPictureStorage.Clear(); 2113 //REMOVE } 2114 2115 SdrLayerID __EXPORT ScDrawLayer::GetControlExportLayerId( const SdrObject & ) const 2116 { 2117 // Layer fuer Export von Form-Controls in Versionen vor 5.0 - immer SC_LAYER_FRONT 2118 return SC_LAYER_FRONT; 2119 } 2120 2121 ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > ScDrawLayer::createUnoModel() 2122 { 2123 ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > xRet; 2124 if( pDoc && pDoc->GetDocumentShell() ) 2125 xRet = pDoc->GetDocumentShell()->GetModel(); 2126 2127 return xRet; 2128 } 2129