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