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