/************************************************************** * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * *************************************************************/ // MARKER(update_precomp.py): autogen include statement, do not remove #include "precompiled_sc.hxx" #include // INCLUDE --------------------------------------------------------------- #include #include #include #include #include #include #include #include #include #include #include #include #include #include "document.hxx" // fuer MapMode Initialisierung in PasteDraw #include "viewfunc.hxx" #include "tabvwsh.hxx" #include "drawview.hxx" #include "scmod.hxx" #include "drwlayer.hxx" #include "drwtrans.hxx" #include "globstr.hrc" #include "chartlis.hxx" #include "docuno.hxx" #include "docsh.hxx" #include "convuno.hxx" extern Point aDragStartDiff; // STATIC DATA ----------------------------------------------------------- sal_Bool bPasteIsMove = sal_False; using namespace com::sun::star; //================================================================== void lcl_AdjustInsertPos( ScViewData* pData, Point& rPos, Size& rSize ) { // SdrPage* pPage = pData->GetDocument()->GetDrawLayer()->GetPage( pData->GetTabNo() ); SdrPage* pPage = pData->GetScDrawView()->GetModel()->GetPage( static_cast(pData->GetTabNo()) ); DBG_ASSERT(pPage,"pPage ???"); Size aPgSize( pPage->GetSize() ); if (aPgSize.Width() < 0) aPgSize.Width() = -aPgSize.Width(); long x = aPgSize.Width() - rPos.X() - rSize.Width(); long y = aPgSize.Height() - rPos.Y() - rSize.Height(); // ggf. Ajustments (80/200) fuer Pixel-Rundungsfehler if( x < 0 ) rPos.X() += x + 80; if( y < 0 ) rPos.Y() += y + 200; rPos.X() += rSize.Width() / 2; // Position bei Paste gibt Mittelpunkt an rPos.Y() += rSize.Height() / 2; } void ScViewFunc::PasteDraw( const Point& rLogicPos, SdrModel* pModel, sal_Bool bGroup, sal_Bool bSameDocClipboard ) { MakeDrawLayer(); Point aPos( rLogicPos ); // #64184# MapMode am Outliner-RefDevice muss stimmen (wie in FuText::MakeOutliner) //! mit FuText::MakeOutliner zusammenfassen? MapMode aOldMapMode; OutputDevice* pRef = GetViewData()->GetDocument()->GetDrawLayer()->GetRefDevice(); if (pRef) { aOldMapMode = pRef->GetMapMode(); pRef->SetMapMode( MapMode(MAP_100TH_MM) ); } sal_Bool bNegativePage = GetViewData()->GetDocument()->IsNegativePage( GetViewData()->GetTabNo() ); SdrView* pDragEditView = NULL; ScModule* pScMod = SC_MOD(); const ScDragData& rData = pScMod->GetDragData(); ScDrawTransferObj* pDrawTrans = rData.pDrawTransfer; if (pDrawTrans) { pDragEditView = pDrawTrans->GetDragSourceView(); aPos -= aDragStartDiff; if ( bNegativePage ) { if (aPos.X() > 0) aPos.X() = 0; } else { if (aPos.X() < 0) aPos.X() = 0; } if (aPos.Y() < 0) aPos.Y() = 0; } ScDrawView* pScDrawView = GetScDrawView(); if (bGroup) pScDrawView->BegUndo( ScGlobal::GetRscString( STR_UNDO_PASTE ) ); sal_Bool bSameDoc = ( pDragEditView && pDragEditView->GetModel() == pScDrawView->GetModel() ); if (bSameDoc) { // lokal kopieren - incl. Charts Point aSourceStart = pDragEditView->GetAllMarkedRect().TopLeft(); long nDiffX = aPos.X() - aSourceStart.X(); long nDiffY = aPos.Y() - aSourceStart.Y(); // innerhalb einer Page verschieben? if ( bPasteIsMove && pScDrawView->GetSdrPageView()->GetPage() == pDragEditView->GetSdrPageView()->GetPage() ) { if ( nDiffX != 0 || nDiffY != 0 ) pDragEditView->MoveAllMarked(Size(nDiffX,nDiffY), sal_False); } else { SdrModel* pDrawModel = pDragEditView->GetModel(); SCTAB nTab = GetViewData()->GetTabNo(); SdrPage* pDestPage = pDrawModel->GetPage( static_cast< sal_uInt16 >( nTab ) ); DBG_ASSERT(pDestPage,"nanu, Page?"); ::std::vector< ::rtl::OUString > aExcludedChartNames; if ( pDestPage ) { ScChartHelper::GetChartNames( aExcludedChartNames, pDestPage ); } SdrMarkList aMark = pDragEditView->GetMarkedObjectList(); aMark.ForceSort(); sal_uLong nMarkAnz=aMark.GetMarkCount(); for (sal_uLong nm=0; nmGetMarkedSdrObj(); // #116235# SdrObject* pNeuObj=pObj->Clone(); //SdrObject* pNeuObj=pObj->Clone(pDestPage,pDrawModel); if (pNeuObj!=NULL) { pNeuObj->SetModel(pDrawModel); pNeuObj->SetPage(pDestPage); // #68787# copy graphics within the same model - always needs new name if ( pNeuObj->ISA(SdrGrafObj) && !bPasteIsMove ) pNeuObj->SetName(((ScDrawLayer*)pDrawModel)->GetNewGraphicName()); if (nDiffX!=0 || nDiffY!=0) pNeuObj->NbcMove(Size(nDiffX,nDiffY)); pDestPage->InsertObject( pNeuObj ); pScDrawView->AddUndo(new SdrUndoInsertObj( *pNeuObj )); // Chart braucht nicht mehr getrennt behandelt zu werden, // weil es seine Daten jetzt selber hat } } if (bPasteIsMove) pDragEditView->DeleteMarked(); ScDocument* pDocument = GetViewData()->GetDocument(); ScDocShell* pDocShell = GetViewData()->GetDocShell(); ScModelObj* pModelObj = ( pDocShell ? ScModelObj::getImplementation( pDocShell->GetModel() ) : NULL ); if ( pDocument && pDestPage && pModelObj && pDrawTrans ) { const ScRangeListVector& rProtectedChartRangesVector( pDrawTrans->GetProtectedChartRangesVector() ); ScChartHelper::CreateProtectedChartListenersAndNotify( pDocument, pDestPage, pModelObj, nTab, rProtectedChartRangesVector, aExcludedChartNames, bSameDoc ); } } } else { bPasteIsMove = sal_False; // kein internes Verschieben passiert SdrView aView(pModel); // #i71529# never create a base class of SdrView directly! SdrPageView* pPv = aView.ShowSdrPage(aView.GetModel()->GetPage(0)); aView.MarkAllObj(pPv); Size aSize = aView.GetAllMarkedRect().GetSize(); lcl_AdjustInsertPos( GetViewData(), aPos, aSize ); // #41333# Markierung nicht aendern, wenn Ole-Objekt aktiv // (bei Drop aus Ole-Objekt wuerde sonst mitten im ExecuteDrag deaktiviert!) sal_uLong nOptions = 0; SfxInPlaceClient* pClient = GetViewData()->GetViewShell()->GetIPClient(); if ( pClient && pClient->IsObjectInPlaceActive() ) nOptions |= SDRINSERT_DONTMARK; ::std::vector< ::rtl::OUString > aExcludedChartNames; SCTAB nTab = GetViewData()->GetTabNo(); SdrPage* pPage = pScDrawView->GetModel()->GetPage( static_cast< sal_uInt16 >( nTab ) ); DBG_ASSERT( pPage, "Page?" ); if ( pPage ) { ScChartHelper::GetChartNames( aExcludedChartNames, pPage ); } // #89247# Set flag for ScDocument::UpdateChartListeners() which is // called during paste. if ( !bSameDocClipboard ) GetViewData()->GetDocument()->SetPastingDrawFromOtherDoc( sal_True ); pScDrawView->Paste( *pModel, aPos, NULL, nOptions ); if ( !bSameDocClipboard ) GetViewData()->GetDocument()->SetPastingDrawFromOtherDoc( sal_False ); // #68991# Paste puts all objects on the active (front) layer // controls must be on SC_LAYER_CONTROLS if (pPage) { SdrObjListIter aIter( *pPage, IM_DEEPNOGROUPS ); SdrObject* pObject = aIter.Next(); while (pObject) { if ( pObject->ISA(SdrUnoObj) && pObject->GetLayer() != SC_LAYER_CONTROLS ) pObject->NbcSetLayer(SC_LAYER_CONTROLS); pObject = aIter.Next(); } } // #75299# all graphics objects must have names GetViewData()->GetDocument()->EnsureGraphicNames(); ScDocument* pDocument = GetViewData()->GetDocument(); ScDocShell* pDocShell = GetViewData()->GetDocShell(); ScModelObj* pModelObj = ( pDocShell ? ScModelObj::getImplementation( pDocShell->GetModel() ) : NULL ); ScDrawTransferObj* pTransferObj = ScDrawTransferObj::GetOwnClipboard( NULL ); if ( pDocument && pPage && pModelObj && ( pTransferObj || pDrawTrans ) ) { const ScRangeListVector& rProtectedChartRangesVector( pTransferObj ? pTransferObj->GetProtectedChartRangesVector() : pDrawTrans->GetProtectedChartRangesVector() ); ScChartHelper::CreateProtectedChartListenersAndNotify( pDocument, pPage, pModelObj, nTab, rProtectedChartRangesVector, aExcludedChartNames, bSameDocClipboard ); } } if (bGroup) { pScDrawView->GroupMarked(); pScDrawView->EndUndo(); } if (pRef) pRef->SetMapMode( aOldMapMode ); // GetViewData()->GetViewShell()->SetDrawShell( sal_True ); // #99759# It is not sufficient to just set the DrawShell if we pasted, for // example, a chart. SetDrawShellOrSub() would only work for D&D in the // same document but not if inserting from the clipboard, therefore // MarkListHasChanged() is what we need. pScDrawView->MarkListHasChanged(); } sal_Bool ScViewFunc::PasteObject( const Point& rPos, const uno::Reference < embed::XEmbeddedObject >& xObj, const Size* pDescSize, const Graphic* pReplGraph, const ::rtl::OUString& aMediaType, sal_Int64 nAspect ) { MakeDrawLayer(); if ( xObj.is() ) { ::rtl::OUString aName; //TODO/MBA: is that OK? comphelper::EmbeddedObjectContainer& aCnt = GetViewData()->GetViewShell()->GetObjectShell()->GetEmbeddedObjectContainer(); if ( !aCnt.HasEmbeddedObject( xObj ) ) aCnt.InsertEmbeddedObject( xObj, aName ); else aName = aCnt.GetEmbeddedObjectName( xObj ); svt::EmbeddedObjectRef aObjRef( xObj, nAspect ); if ( pReplGraph ) aObjRef.SetGraphic( *pReplGraph, aMediaType ); Size aSize; if ( nAspect == embed::Aspects::MSOLE_ICON ) { MapMode aMapMode( MAP_100TH_MM ); aSize = aObjRef.GetSize( &aMapMode ); } else { // working with visual area can switch object to running state MapUnit aMapObj = VCLUnoHelper::UnoEmbed2VCLMapUnit( xObj->getMapUnit( nAspect ) ); MapUnit aMap100 = MAP_100TH_MM; if ( pDescSize && pDescSize->Width() && pDescSize->Height() ) { // use size from object descriptor if given aSize = OutputDevice::LogicToLogic( *pDescSize, aMap100, aMapObj ); awt::Size aSz; aSz.Width = aSize.Width(); aSz.Height = aSize.Height(); xObj->setVisualAreaSize( nAspect, aSz ); } awt::Size aSz; try { aSz = xObj->getVisualAreaSize( nAspect ); } catch ( embed::NoVisualAreaSizeException& ) { // the default size will be set later } aSize = Size( aSz.Width, aSz.Height ); aSize = OutputDevice::LogicToLogic( aSize, aMapObj, aMap100 ); // fuer SdrOle2Obj if( aSize.Height() == 0 || aSize.Width() == 0 ) { DBG_ERROR("SvObjectDescriptor::GetSize == 0"); aSize.Width() = 5000; aSize.Height() = 5000; aSize = OutputDevice::LogicToLogic( aSize, aMap100, aMapObj ); aSz.Width = aSize.Width(); aSz.Height = aSize.Height(); xObj->setVisualAreaSize( nAspect, aSz ); } } // don't call AdjustInsertPos Point aInsPos = rPos; if ( GetViewData()->GetDocument()->IsNegativePage( GetViewData()->GetTabNo() ) ) aInsPos.X() -= aSize.Width(); Rectangle aRect( aInsPos, aSize ); ScDrawView* pDrView = GetScDrawView(); SdrOle2Obj* pSdrObj = new SdrOle2Obj( aObjRef, aName, aRect ); SdrPageView* pPV = pDrView->GetSdrPageView(); pDrView->InsertObjectSafe( pSdrObj, *pPV ); // nicht markieren wenn Ole GetViewData()->GetViewShell()->SetDrawShell( sal_True ); return sal_True; } else return sal_False; } sal_Bool ScViewFunc::PasteBitmapEx( const Point& rPos, const BitmapEx& rBmpEx ) { String aEmpty; Graphic aGraphic(rBmpEx); return PasteGraphic( rPos, aGraphic, aEmpty, aEmpty ); } sal_Bool ScViewFunc::PasteMetaFile( const Point& rPos, const GDIMetaFile& rMtf ) { String aEmpty; Graphic aGraphic(rMtf); return PasteGraphic( rPos, aGraphic, aEmpty, aEmpty ); } sal_Bool ScViewFunc::PasteGraphic( const Point& rPos, const Graphic& rGraphic, const String& rFile, const String& rFilter ) { MakeDrawLayer(); ScDrawView* pScDrawView = GetScDrawView(); // #123922# check if the drop was over an existing object; if yes, evtl. replace // the graphic for a SdrGraphObj (including link state updates) or adapt the fill // style for other objects if(pScDrawView) { SdrObject* pPickObj = 0; SdrPageView* pPageView = pScDrawView->GetSdrPageView(); if(pPageView) { pScDrawView->PickObj(rPos, pScDrawView->getHitTolLog(), pPickObj, pPageView); } if(pPickObj) { const String aBeginUndo(ScGlobal::GetRscString(STR_UNDO_DRAGDROP)); SdrObject* pResult = pScDrawView->ApplyGraphicToObject( *pPickObj, rGraphic, aBeginUndo, rFile, rFilter); if(pResult) { // we are done; mark the modified/new object pScDrawView->MarkObj(pResult, pScDrawView->GetSdrPageView()); return sal_True; } } } Point aPos( rPos ); Window* pWin = GetActiveWin(); MapMode aSourceMap = rGraphic.GetPrefMapMode(); MapMode aDestMap( MAP_100TH_MM ); if (aSourceMap.GetMapUnit() == MAP_PIXEL) { // Pixel-Korrektur beruecksichtigen, damit Bitmap auf dem Bildschirm stimmt Fraction aScaleX, aScaleY; pScDrawView->CalcNormScale( aScaleX, aScaleY ); aDestMap.SetScaleX(aScaleX); aDestMap.SetScaleY(aScaleY); } Size aSize = pWin->LogicToLogic( rGraphic.GetPrefSize(), &aSourceMap, &aDestMap ); // lcl_AdjustInsertPos( GetViewData(), aPos, aSize ); if ( GetViewData()->GetDocument()->IsNegativePage( GetViewData()->GetTabNo() ) ) aPos.X() -= aSize.Width(); GetViewData()->GetViewShell()->SetDrawShell( sal_True ); Rectangle aRect(aPos, aSize); SdrGrafObj* pGrafObj = new SdrGrafObj(rGraphic, aRect); // #118522# calling SetGraphicLink here doesn't work // #49961# Pfad wird nicht mehr als Name der Grafik gesetzt ScDrawLayer* pLayer = (ScDrawLayer*) pScDrawView->GetModel(); String aName = pLayer->GetNewGraphicName(); // "Grafik x" pGrafObj->SetName(aName); // nicht markieren wenn Ole pScDrawView->InsertObjectSafe(pGrafObj, *pScDrawView->GetSdrPageView()); // #118522# SetGraphicLink has to be used after inserting the object, // otherwise an empty graphic is swapped in and the contact stuff crashes. // See #i37444#. if (rFile.Len()) pGrafObj->SetGraphicLink( rFile, rFilter ); return sal_True; }