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