1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_sc.hxx" 30 #include <com/sun/star/embed/NoVisualAreaSizeException.hpp> 31 32 33 34 // INCLUDE --------------------------------------------------------------- 35 36 #include <svx/svditer.hxx> 37 #include <svx/svdograf.hxx> 38 #include <svx/svdoole2.hxx> 39 #include <svx/svdouno.hxx> 40 #include <svx/svdpage.hxx> 41 #include <svx/svdpagv.hxx> 42 #include <svx/svdundo.hxx> 43 #include <svx/xbitmap.hxx> 44 #include <svx/xbtmpit.hxx> 45 #include <svx/xoutbmp.hxx> 46 #include <sfx2/objsh.hxx> 47 #include <sfx2/viewfrm.hxx> 48 #include <toolkit/helper/vclunohelper.hxx> 49 #include <com/sun/star/embed/Aspects.hpp> 50 51 #include "document.hxx" // fuer MapMode Initialisierung in PasteDraw 52 #include "viewfunc.hxx" 53 #include "tabvwsh.hxx" 54 #include "drawview.hxx" 55 #include "scmod.hxx" 56 #include "drwlayer.hxx" 57 #include "drwtrans.hxx" 58 #include "globstr.hrc" 59 #include "chartlis.hxx" 60 #include "docuno.hxx" 61 #include "docsh.hxx" 62 #include "convuno.hxx" 63 64 extern Point aDragStartDiff; 65 66 // STATIC DATA ----------------------------------------------------------- 67 68 sal_Bool bPasteIsMove = sal_False; 69 70 using namespace com::sun::star; 71 72 //================================================================== 73 74 void lcl_AdjustInsertPos( ScViewData* pData, Point& rPos, Size& rSize ) 75 { 76 // SdrPage* pPage = pData->GetDocument()->GetDrawLayer()->GetPage( pData->GetTabNo() ); 77 SdrPage* pPage = pData->GetScDrawView()->GetModel()->GetPage( static_cast<sal_uInt16>(pData->GetTabNo()) ); 78 DBG_ASSERT(pPage,"pPage ???"); 79 Size aPgSize( pPage->GetSize() ); 80 if (aPgSize.Width() < 0) 81 aPgSize.Width() = -aPgSize.Width(); 82 long x = aPgSize.Width() - rPos.X() - rSize.Width(); 83 long y = aPgSize.Height() - rPos.Y() - rSize.Height(); 84 // ggf. Ajustments (80/200) fuer Pixel-Rundungsfehler 85 if( x < 0 ) 86 rPos.X() += x + 80; 87 if( y < 0 ) 88 rPos.Y() += y + 200; 89 rPos.X() += rSize.Width() / 2; // Position bei Paste gibt Mittelpunkt an 90 rPos.Y() += rSize.Height() / 2; 91 } 92 93 void ScViewFunc::PasteDraw( const Point& rLogicPos, SdrModel* pModel, 94 sal_Bool bGroup, sal_Bool bSameDocClipboard ) 95 { 96 MakeDrawLayer(); 97 Point aPos( rLogicPos ); 98 99 // #64184# MapMode am Outliner-RefDevice muss stimmen (wie in FuText::MakeOutliner) 100 //! mit FuText::MakeOutliner zusammenfassen? 101 MapMode aOldMapMode; 102 OutputDevice* pRef = GetViewData()->GetDocument()->GetDrawLayer()->GetRefDevice(); 103 if (pRef) 104 { 105 aOldMapMode = pRef->GetMapMode(); 106 pRef->SetMapMode( MapMode(MAP_100TH_MM) ); 107 } 108 109 sal_Bool bNegativePage = GetViewData()->GetDocument()->IsNegativePage( GetViewData()->GetTabNo() ); 110 111 SdrView* pDragEditView = NULL; 112 ScModule* pScMod = SC_MOD(); 113 const ScDragData& rData = pScMod->GetDragData(); 114 ScDrawTransferObj* pDrawTrans = rData.pDrawTransfer; 115 if (pDrawTrans) 116 { 117 pDragEditView = pDrawTrans->GetDragSourceView(); 118 119 aPos -= aDragStartDiff; 120 if ( bNegativePage ) 121 { 122 if (aPos.X() > 0) aPos.X() = 0; 123 } 124 else 125 { 126 if (aPos.X() < 0) aPos.X() = 0; 127 } 128 if (aPos.Y() < 0) aPos.Y() = 0; 129 } 130 131 ScDrawView* pScDrawView = GetScDrawView(); 132 if (bGroup) 133 pScDrawView->BegUndo( ScGlobal::GetRscString( STR_UNDO_PASTE ) ); 134 135 sal_Bool bSameDoc = ( pDragEditView && pDragEditView->GetModel() == pScDrawView->GetModel() ); 136 if (bSameDoc) 137 { 138 // lokal kopieren - incl. Charts 139 140 Point aSourceStart = pDragEditView->GetAllMarkedRect().TopLeft(); 141 long nDiffX = aPos.X() - aSourceStart.X(); 142 long nDiffY = aPos.Y() - aSourceStart.Y(); 143 144 // innerhalb einer Page verschieben? 145 146 if ( bPasteIsMove && 147 pScDrawView->GetSdrPageView()->GetPage() == 148 pDragEditView->GetSdrPageView()->GetPage() ) 149 { 150 if ( nDiffX != 0 || nDiffY != 0 ) 151 pDragEditView->MoveAllMarked(Size(nDiffX,nDiffY), sal_False); 152 } 153 else 154 { 155 SdrModel* pDrawModel = pDragEditView->GetModel(); 156 SCTAB nTab = GetViewData()->GetTabNo(); 157 SdrPage* pDestPage = pDrawModel->GetPage( static_cast< sal_uInt16 >( nTab ) ); 158 DBG_ASSERT(pDestPage,"nanu, Page?"); 159 160 ::std::vector< ::rtl::OUString > aExcludedChartNames; 161 if ( pDestPage ) 162 { 163 ScChartHelper::GetChartNames( aExcludedChartNames, pDestPage ); 164 } 165 166 SdrMarkList aMark = pDragEditView->GetMarkedObjectList(); 167 aMark.ForceSort(); 168 sal_uLong nMarkAnz=aMark.GetMarkCount(); 169 for (sal_uLong nm=0; nm<nMarkAnz; nm++) { 170 const SdrMark* pM=aMark.GetMark(nm); 171 const SdrObject* pObj=pM->GetMarkedSdrObj(); 172 173 // #116235# 174 SdrObject* pNeuObj=pObj->Clone(); 175 //SdrObject* pNeuObj=pObj->Clone(pDestPage,pDrawModel); 176 177 if (pNeuObj!=NULL) 178 { 179 pNeuObj->SetModel(pDrawModel); 180 pNeuObj->SetPage(pDestPage); 181 182 // #68787# copy graphics within the same model - always needs new name 183 if ( pNeuObj->ISA(SdrGrafObj) && !bPasteIsMove ) 184 pNeuObj->SetName(((ScDrawLayer*)pDrawModel)->GetNewGraphicName()); 185 186 if (nDiffX!=0 || nDiffY!=0) 187 pNeuObj->NbcMove(Size(nDiffX,nDiffY)); 188 pDestPage->InsertObject( pNeuObj ); 189 pScDrawView->AddUndo(new SdrUndoInsertObj( *pNeuObj )); 190 191 // Chart braucht nicht mehr getrennt behandelt zu werden, 192 // weil es seine Daten jetzt selber hat 193 } 194 } 195 196 if (bPasteIsMove) 197 pDragEditView->DeleteMarked(); 198 199 ScDocument* pDocument = GetViewData()->GetDocument(); 200 ScDocShell* pDocShell = GetViewData()->GetDocShell(); 201 ScModelObj* pModelObj = ( pDocShell ? ScModelObj::getImplementation( pDocShell->GetModel() ) : NULL ); 202 if ( pDocument && pDestPage && pModelObj && pDrawTrans ) 203 { 204 const ScRangeListVector& rProtectedChartRangesVector( pDrawTrans->GetProtectedChartRangesVector() ); 205 ScChartHelper::CreateProtectedChartListenersAndNotify( pDocument, pDestPage, pModelObj, nTab, 206 rProtectedChartRangesVector, aExcludedChartNames, bSameDoc ); 207 } 208 } 209 } 210 else 211 { 212 bPasteIsMove = sal_False; // kein internes Verschieben passiert 213 214 SdrView aView(pModel); // #i71529# never create a base class of SdrView directly! 215 SdrPageView* pPv = aView.ShowSdrPage(aView.GetModel()->GetPage(0)); 216 aView.MarkAllObj(pPv); 217 Size aSize = aView.GetAllMarkedRect().GetSize(); 218 lcl_AdjustInsertPos( GetViewData(), aPos, aSize ); 219 220 // #41333# Markierung nicht aendern, wenn Ole-Objekt aktiv 221 // (bei Drop aus Ole-Objekt wuerde sonst mitten im ExecuteDrag deaktiviert!) 222 223 sal_uLong nOptions = 0; 224 SfxInPlaceClient* pClient = GetViewData()->GetViewShell()->GetIPClient(); 225 if ( pClient && pClient->IsObjectInPlaceActive() ) 226 nOptions |= SDRINSERT_DONTMARK; 227 228 ::std::vector< ::rtl::OUString > aExcludedChartNames; 229 SCTAB nTab = GetViewData()->GetTabNo(); 230 SdrPage* pPage = pScDrawView->GetModel()->GetPage( static_cast< sal_uInt16 >( nTab ) ); 231 DBG_ASSERT( pPage, "Page?" ); 232 if ( pPage ) 233 { 234 ScChartHelper::GetChartNames( aExcludedChartNames, pPage ); 235 } 236 237 // #89247# Set flag for ScDocument::UpdateChartListeners() which is 238 // called during paste. 239 if ( !bSameDocClipboard ) 240 GetViewData()->GetDocument()->SetPastingDrawFromOtherDoc( sal_True ); 241 242 pScDrawView->Paste( *pModel, aPos, NULL, nOptions ); 243 244 if ( !bSameDocClipboard ) 245 GetViewData()->GetDocument()->SetPastingDrawFromOtherDoc( sal_False ); 246 247 // #68991# Paste puts all objects on the active (front) layer 248 // controls must be on SC_LAYER_CONTROLS 249 if (pPage) 250 { 251 SdrObjListIter aIter( *pPage, IM_DEEPNOGROUPS ); 252 SdrObject* pObject = aIter.Next(); 253 while (pObject) 254 { 255 if ( pObject->ISA(SdrUnoObj) && pObject->GetLayer() != SC_LAYER_CONTROLS ) 256 pObject->NbcSetLayer(SC_LAYER_CONTROLS); 257 pObject = aIter.Next(); 258 } 259 } 260 261 // #75299# all graphics objects must have names 262 GetViewData()->GetDocument()->EnsureGraphicNames(); 263 264 ScDocument* pDocument = GetViewData()->GetDocument(); 265 ScDocShell* pDocShell = GetViewData()->GetDocShell(); 266 ScModelObj* pModelObj = ( pDocShell ? ScModelObj::getImplementation( pDocShell->GetModel() ) : NULL ); 267 ScDrawTransferObj* pTransferObj = ScDrawTransferObj::GetOwnClipboard( NULL ); 268 if ( pDocument && pPage && pModelObj && ( pTransferObj || pDrawTrans ) ) 269 { 270 const ScRangeListVector& rProtectedChartRangesVector( 271 pTransferObj ? pTransferObj->GetProtectedChartRangesVector() : pDrawTrans->GetProtectedChartRangesVector() ); 272 ScChartHelper::CreateProtectedChartListenersAndNotify( pDocument, pPage, pModelObj, nTab, 273 rProtectedChartRangesVector, aExcludedChartNames, bSameDocClipboard ); 274 } 275 } 276 277 if (bGroup) 278 { 279 pScDrawView->GroupMarked(); 280 pScDrawView->EndUndo(); 281 } 282 283 if (pRef) 284 pRef->SetMapMode( aOldMapMode ); 285 286 // GetViewData()->GetViewShell()->SetDrawShell( sal_True ); 287 // #99759# It is not sufficient to just set the DrawShell if we pasted, for 288 // example, a chart. SetDrawShellOrSub() would only work for D&D in the 289 // same document but not if inserting from the clipboard, therefore 290 // MarkListHasChanged() is what we need. 291 pScDrawView->MarkListHasChanged(); 292 293 } 294 295 sal_Bool ScViewFunc::PasteObject( const Point& rPos, const uno::Reference < embed::XEmbeddedObject >& xObj, 296 const Size* pDescSize, const Graphic* pReplGraph, const ::rtl::OUString& aMediaType, sal_Int64 nAspect ) 297 { 298 MakeDrawLayer(); 299 if ( xObj.is() ) 300 { 301 ::rtl::OUString aName; 302 //TODO/MBA: is that OK? 303 comphelper::EmbeddedObjectContainer& aCnt = GetViewData()->GetViewShell()->GetObjectShell()->GetEmbeddedObjectContainer(); 304 if ( !aCnt.HasEmbeddedObject( xObj ) ) 305 aCnt.InsertEmbeddedObject( xObj, aName ); 306 else 307 aName = aCnt.GetEmbeddedObjectName( xObj ); 308 309 svt::EmbeddedObjectRef aObjRef( xObj, nAspect ); 310 if ( pReplGraph ) 311 aObjRef.SetGraphic( *pReplGraph, aMediaType ); 312 313 Size aSize; 314 if ( nAspect == embed::Aspects::MSOLE_ICON ) 315 { 316 MapMode aMapMode( MAP_100TH_MM ); 317 aSize = aObjRef.GetSize( &aMapMode ); 318 } 319 else 320 { 321 // working with visual area can switch object to running state 322 MapUnit aMapObj = VCLUnoHelper::UnoEmbed2VCLMapUnit( xObj->getMapUnit( nAspect ) ); 323 MapUnit aMap100 = MAP_100TH_MM; 324 325 if ( pDescSize && pDescSize->Width() && pDescSize->Height() ) 326 { 327 // use size from object descriptor if given 328 aSize = OutputDevice::LogicToLogic( *pDescSize, aMap100, aMapObj ); 329 awt::Size aSz; 330 aSz.Width = aSize.Width(); 331 aSz.Height = aSize.Height(); 332 xObj->setVisualAreaSize( nAspect, aSz ); 333 } 334 335 awt::Size aSz; 336 try 337 { 338 aSz = xObj->getVisualAreaSize( nAspect ); 339 } 340 catch ( embed::NoVisualAreaSizeException& ) 341 { 342 // the default size will be set later 343 } 344 345 aSize = Size( aSz.Width, aSz.Height ); 346 aSize = OutputDevice::LogicToLogic( aSize, aMapObj, aMap100 ); // fuer SdrOle2Obj 347 348 if( aSize.Height() == 0 || aSize.Width() == 0 ) 349 { 350 DBG_ERROR("SvObjectDescriptor::GetSize == 0"); 351 aSize.Width() = 5000; 352 aSize.Height() = 5000; 353 aSize = OutputDevice::LogicToLogic( aSize, aMap100, aMapObj ); 354 aSz.Width = aSize.Width(); 355 aSz.Height = aSize.Height(); 356 xObj->setVisualAreaSize( nAspect, aSz ); 357 } 358 } 359 360 // don't call AdjustInsertPos 361 Point aInsPos = rPos; 362 if ( GetViewData()->GetDocument()->IsNegativePage( GetViewData()->GetTabNo() ) ) 363 aInsPos.X() -= aSize.Width(); 364 Rectangle aRect( aInsPos, aSize ); 365 366 ScDrawView* pDrView = GetScDrawView(); 367 SdrOle2Obj* pSdrObj = new SdrOle2Obj( aObjRef, aName, aRect ); 368 369 SdrPageView* pPV = pDrView->GetSdrPageView(); 370 pDrView->InsertObjectSafe( pSdrObj, *pPV ); // nicht markieren wenn Ole 371 GetViewData()->GetViewShell()->SetDrawShell( sal_True ); 372 return sal_True; 373 } 374 else 375 return sal_False; 376 } 377 378 sal_Bool ScViewFunc::PasteBitmap( const Point& rPos, const Bitmap& rBmp ) 379 { 380 String aEmpty; 381 Graphic aGraphic(rBmp); 382 return PasteGraphic( rPos, aGraphic, aEmpty, aEmpty ); 383 } 384 385 sal_Bool ScViewFunc::PasteMetaFile( const Point& rPos, const GDIMetaFile& rMtf ) 386 { 387 String aEmpty; 388 Graphic aGraphic(rMtf); 389 return PasteGraphic( rPos, aGraphic, aEmpty, aEmpty ); 390 } 391 392 sal_Bool ScViewFunc::PasteGraphic( const Point& rPos, const Graphic& rGraphic, 393 const String& rFile, const String& rFilter ) 394 { 395 MakeDrawLayer(); 396 ScDrawView* pScDrawView = GetScDrawView(); 397 398 Point aPos( rPos ); 399 Window* pWin = GetActiveWin(); 400 MapMode aSourceMap = rGraphic.GetPrefMapMode(); 401 MapMode aDestMap( MAP_100TH_MM ); 402 403 if (aSourceMap.GetMapUnit() == MAP_PIXEL) 404 { 405 // Pixel-Korrektur beruecksichtigen, damit Bitmap auf dem Bildschirm stimmt 406 407 Fraction aScaleX, aScaleY; 408 pScDrawView->CalcNormScale( aScaleX, aScaleY ); 409 aDestMap.SetScaleX(aScaleX); 410 aDestMap.SetScaleY(aScaleY); 411 } 412 413 Size aSize = pWin->LogicToLogic( rGraphic.GetPrefSize(), &aSourceMap, &aDestMap ); 414 // lcl_AdjustInsertPos( GetViewData(), aPos, aSize ); 415 if ( GetViewData()->GetDocument()->IsNegativePage( GetViewData()->GetTabNo() ) ) 416 aPos.X() -= aSize.Width(); 417 418 GetViewData()->GetViewShell()->SetDrawShell( sal_True ); 419 420 Rectangle aRect(aPos, aSize); 421 SdrGrafObj* pGrafObj = new SdrGrafObj(rGraphic, aRect); 422 423 // #118522# calling SetGraphicLink here doesn't work 424 425 // #49961# Pfad wird nicht mehr als Name der Grafik gesetzt 426 427 ScDrawLayer* pLayer = (ScDrawLayer*) pScDrawView->GetModel(); 428 String aName = pLayer->GetNewGraphicName(); // "Grafik x" 429 pGrafObj->SetName(aName); 430 431 // nicht markieren wenn Ole 432 pScDrawView->InsertObjectSafe(pGrafObj, *pScDrawView->GetSdrPageView()); 433 434 // #118522# SetGraphicLink has to be used after inserting the object, 435 // otherwise an empty graphic is swapped in and the contact stuff crashes. 436 // See #i37444#. 437 if (rFile.Len()) 438 pGrafObj->SetGraphicLink( rFile, rFilter ); 439 440 return sal_True; 441 } 442 443 sal_Bool ScViewFunc::ApplyGraphicToObject( SdrObject* pPickObj, const Graphic& rGraphic ) 444 { 445 sal_Bool bRet = sal_False; 446 SdrGrafObj* pNewGrafObj = NULL; 447 448 ScDrawView* pScDrawView = GetScDrawView(); 449 if ( pScDrawView && pPickObj ) 450 { 451 /********************************************************************** 452 * Objekt neu attributieren 453 **********************************************************************/ 454 SdrPageView* pPV = pScDrawView->GetSdrPageView(); 455 if (pPickObj->ISA(SdrGrafObj)) 456 { 457 /****************************************************************** 458 * Das Graphik-Objekt bekommt eine neue Graphik 459 ******************************************************************/ 460 pNewGrafObj = (SdrGrafObj*) pPickObj->Clone(); 461 pNewGrafObj->SetGraphic(rGraphic); 462 463 pScDrawView->BegUndo(ScGlobal::GetRscString(STR_UNDO_DRAGDROP)); 464 pScDrawView->ReplaceObjectAtView(pPickObj, *pPV, pNewGrafObj); 465 pScDrawView->EndUndo(); 466 467 bRet = sal_True; 468 } 469 else if (pPickObj->IsClosedObj() && !pPickObj->ISA(SdrOle2Obj)) 470 { 471 /****************************************************************** 472 * Das Objekt wird mit der Graphik gefuellt 473 ******************************************************************/ 474 //pScDrawView->BegUndo(ScGlobal::GetRscString(STR_UNDO_DRAGDROP)); 475 pScDrawView->AddUndo(new SdrUndoAttrObj(*pPickObj)); 476 //pScDrawView->EndUndo(); 477 478 XOBitmap aXOBitmap( rGraphic.GetBitmap() ); 479 SfxItemSet aSet( pScDrawView->GetModel()->GetItemPool(), 480 XATTR_FILLSTYLE, XATTR_FILLBITMAP ); 481 aSet.Put(XFillStyleItem(XFILL_BITMAP)); 482 aSet.Put(XFillBitmapItem(String(), aXOBitmap)); 483 484 pPickObj->SetMergedItemSetAndBroadcast(aSet); 485 486 bRet = sal_True; 487 } 488 } 489 return bRet; 490 } 491 492 493