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