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