1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <com/sun/star/embed/NoVisualAreaSizeException.hpp>
22 #include <svx/svditer.hxx>
23 #include <svx/svdograf.hxx>
24 #include <svx/svdoole2.hxx>
25 #include <svx/svdouno.hxx>
26 #include <svx/svdpage.hxx>
27 #include <svx/svdpagv.hxx>
28 #include <svx/svdundo.hxx>
29 #include <svx/xbtmpit.hxx>
30 #include <svx/xoutbmp.hxx>
31 #include <sfx2/objsh.hxx>
32 #include <sfx2/viewfrm.hxx>
33 #include <toolkit/helper/vclunohelper.hxx>
34 #include <com/sun/star/embed/Aspects.hpp>
36 #include "document.hxx"
37 #include "viewfunc.hxx"
38 #include "tabvwsh.hxx"
39 #include "drawview.hxx"
41 #include "drwlayer.hxx"
42 #include "drwtrans.hxx"
43 #include "globstr.hrc"
44 #include "chartlis.hxx"
47 #include "convuno.hxx"
48 #include "dragdata.hxx"
50 extern Point aDragStartDiff
;
52 sal_Bool bPasteIsMove
= false;
54 using namespace com::sun::star
;
57 static void lcl_AdjustInsertPos( ScViewData
* pData
, Point
& rPos
, Size
& rSize
)
59 SdrPage
* pPage
= pData
->GetScDrawView()->GetModel()->GetPage( static_cast<sal_uInt16
>(pData
->GetTabNo()) );
60 OSL_ENSURE(pPage
,"pPage ???");
61 Size
aPgSize( pPage
->GetSize() );
62 if (aPgSize
.Width() < 0)
63 aPgSize
.Width() = -aPgSize
.Width();
64 long x
= aPgSize
.Width() - rPos
.X() - rSize
.Width();
65 long y
= aPgSize
.Height() - rPos
.Y() - rSize
.Height();
66 // if necessary: adjustments (80/200) for pixel approx. errors
71 rPos
.X() += rSize
.Width() / 2; // position at paste is center
72 rPos
.Y() += rSize
.Height() / 2;
75 void ScViewFunc::PasteDraw( const Point
& rLogicPos
, SdrModel
* pModel
,
76 sal_Bool bGroup
, sal_Bool bSameDocClipboard
)
79 Point
aPos( rLogicPos
);
81 // MapMode at Outliner-RefDevice has to be right (as in FuText::MakeOutliner)
82 //! merge with FuText::MakeOutliner?
84 OutputDevice
* pRef
= GetViewData()->GetDocument()->GetDrawLayer()->GetRefDevice();
87 aOldMapMode
= pRef
->GetMapMode();
88 pRef
->SetMapMode( MapMode(MAP_100TH_MM
) );
91 sal_Bool bNegativePage
= GetViewData()->GetDocument()->IsNegativePage( GetViewData()->GetTabNo() );
93 SdrView
* pDragEditView
= NULL
;
94 ScModule
* pScMod
= SC_MOD();
95 const ScDragData
& rData
= pScMod
->GetDragData();
96 ScDrawTransferObj
* pDrawTrans
= rData
.pDrawTransfer
;
99 pDragEditView
= pDrawTrans
->GetDragSourceView();
101 aPos
-= aDragStartDiff
;
104 if (aPos
.X() > 0) aPos
.X() = 0;
108 if (aPos
.X() < 0) aPos
.X() = 0;
110 if (aPos
.Y() < 0) aPos
.Y() = 0;
113 ScDrawView
* pScDrawView
= GetScDrawView();
115 pScDrawView
->BegUndo( ScGlobal::GetRscString( STR_UNDO_PASTE
) );
117 sal_Bool bSameDoc
= ( pDragEditView
&& pDragEditView
->GetModel() == pScDrawView
->GetModel() );
120 // copy locally - incl. charts
122 Point aSourceStart
= pDragEditView
->GetAllMarkedRect().TopLeft();
123 long nDiffX
= aPos
.X() - aSourceStart
.X();
124 long nDiffY
= aPos
.Y() - aSourceStart
.Y();
126 // move within a page?
129 pScDrawView
->GetSdrPageView()->GetPage() ==
130 pDragEditView
->GetSdrPageView()->GetPage() )
132 if ( nDiffX
!= 0 || nDiffY
!= 0 )
133 pDragEditView
->MoveAllMarked(Size(nDiffX
,nDiffY
), false);
137 SdrModel
* pDrawModel
= pDragEditView
->GetModel();
138 SCTAB nTab
= GetViewData()->GetTabNo();
139 SdrPage
* pDestPage
= pDrawModel
->GetPage( static_cast< sal_uInt16
>( nTab
) );
140 OSL_ENSURE(pDestPage
,"who is this, Page?");
142 ::std::vector
< OUString
> aExcludedChartNames
;
145 ScChartHelper::GetChartNames( aExcludedChartNames
, pDestPage
);
148 SdrMarkList aMark
= pDragEditView
->GetMarkedObjectList();
150 sal_uLong nMarkAnz
=aMark
.GetMarkCount();
151 for (sal_uLong nm
=0; nm
<nMarkAnz
; nm
++) {
152 const SdrMark
* pM
=aMark
.GetMark(nm
);
153 const SdrObject
* pObj
=pM
->GetMarkedSdrObj();
155 SdrObject
* pNeuObj
=pObj
->Clone();
159 pNeuObj
->SetModel(pDrawModel
);
160 pNeuObj
->SetPage(pDestPage
);
162 // copy graphics within the same model - always needs new name
163 if ( pNeuObj
->ISA(SdrGrafObj
) && !bPasteIsMove
)
164 pNeuObj
->SetName(((ScDrawLayer
*)pDrawModel
)->GetNewGraphicName());
166 if (nDiffX
!=0 || nDiffY
!=0)
167 pNeuObj
->NbcMove(Size(nDiffX
,nDiffY
));
168 pDestPage
->InsertObject( pNeuObj
);
169 pScDrawView
->AddUndo(new SdrUndoInsertObj( *pNeuObj
));
171 if (ScDrawLayer::IsCellAnchored(*pNeuObj
))
172 ScDrawLayer::SetCellAnchoredFromPosition(*pNeuObj
, *GetViewData()->GetDocument(), nTab
);
177 pDragEditView
->DeleteMarked();
179 ScDocument
* pDocument
= GetViewData()->GetDocument();
180 ScDocShell
* pDocShell
= GetViewData()->GetDocShell();
181 ScModelObj
* pModelObj
= ( pDocShell
? ScModelObj::getImplementation( pDocShell
->GetModel() ) : NULL
);
182 if ( pDocument
&& pDestPage
&& pModelObj
&& pDrawTrans
)
184 const ScRangeListVector
& rProtectedChartRangesVector( pDrawTrans
->GetProtectedChartRangesVector() );
185 ScChartHelper::CreateProtectedChartListenersAndNotify( pDocument
, pDestPage
, pModelObj
, nTab
,
186 rProtectedChartRangesVector
, aExcludedChartNames
, bSameDoc
);
192 bPasteIsMove
= false; // no internal move happened
194 SdrView
aView(pModel
); // #i71529# never create a base class of SdrView directly!
195 SdrPageView
* pPv
= aView
.ShowSdrPage(aView
.GetModel()->GetPage(0));
196 aView
.MarkAllObj(pPv
);
197 Size aSize
= aView
.GetAllMarkedRect().GetSize();
198 lcl_AdjustInsertPos( GetViewData(), aPos
, aSize
);
200 // don't change marking if OLE object is active
201 // (at Drop from OLE object it would be deactivated in the middle of ExecuteDrag!)
203 sal_uLong nOptions
= 0;
204 SfxInPlaceClient
* pClient
= GetViewData()->GetViewShell()->GetIPClient();
205 if ( pClient
&& pClient
->IsObjectInPlaceActive() )
206 nOptions
|= SDRINSERT_DONTMARK
;
208 ::std::vector
< OUString
> aExcludedChartNames
;
209 SCTAB nTab
= GetViewData()->GetTabNo();
210 SdrPage
* pPage
= pScDrawView
->GetModel()->GetPage( static_cast< sal_uInt16
>( nTab
) );
211 OSL_ENSURE( pPage
, "Page?" );
214 ScChartHelper::GetChartNames( aExcludedChartNames
, pPage
);
217 // #89247# Set flag for ScDocument::UpdateChartListeners() which is
218 // called during paste.
219 if ( !bSameDocClipboard
)
220 GetViewData()->GetDocument()->SetPastingDrawFromOtherDoc( sal_True
);
222 pScDrawView
->Paste( *pModel
, aPos
, NULL
, nOptions
);
224 if ( !bSameDocClipboard
)
225 GetViewData()->GetDocument()->SetPastingDrawFromOtherDoc( false );
227 // Paste puts all objects on the active (front) layer
228 // controls must be on SC_LAYER_CONTROLS
231 SdrObjListIter
aIter( *pPage
, IM_DEEPNOGROUPS
);
232 SdrObject
* pObject
= aIter
.Next();
235 if ( pObject
->ISA(SdrUnoObj
) && pObject
->GetLayer() != SC_LAYER_CONTROLS
)
236 pObject
->NbcSetLayer(SC_LAYER_CONTROLS
);
238 if (ScDrawLayer::IsCellAnchored(*pObject
))
239 ScDrawLayer::SetCellAnchoredFromPosition(*pObject
, *GetViewData()->GetDocument(), nTab
);
241 pObject
= aIter
.Next();
245 // all graphics objects must have names
246 GetViewData()->GetDocument()->EnsureGraphicNames();
248 ScDocument
* pDocument
= GetViewData()->GetDocument();
249 ScDocShell
* pDocShell
= GetViewData()->GetDocShell();
250 ScModelObj
* pModelObj
= ( pDocShell
? ScModelObj::getImplementation( pDocShell
->GetModel() ) : NULL
);
251 ScDrawTransferObj
* pTransferObj
= ScDrawTransferObj::GetOwnClipboard( NULL
);
252 if ( pDocument
&& pPage
&& pModelObj
&& ( pTransferObj
|| pDrawTrans
) )
254 const ScRangeListVector
& rProtectedChartRangesVector(
255 pTransferObj
? pTransferObj
->GetProtectedChartRangesVector() : pDrawTrans
->GetProtectedChartRangesVector() );
256 ScChartHelper::CreateProtectedChartListenersAndNotify( pDocument
, pPage
, pModelObj
, nTab
,
257 rProtectedChartRangesVector
, aExcludedChartNames
, bSameDocClipboard
);
263 pScDrawView
->GroupMarked();
264 pScDrawView
->EndUndo();
268 pRef
->SetMapMode( aOldMapMode
);
270 // GetViewData()->GetViewShell()->SetDrawShell( sal_True );
271 // It is not sufficient to just set the DrawShell if we pasted, for
272 // example, a chart. SetDrawShellOrSub() would only work for D&D in the
273 // same document but not if inserting from the clipboard, therefore
274 // MarkListHasChanged() is what we need.
275 pScDrawView
->MarkListHasChanged();
279 sal_Bool
ScViewFunc::PasteObject( const Point
& rPos
, const uno::Reference
< embed::XEmbeddedObject
>& xObj
,
280 const Size
* pDescSize
, const Graphic
* pReplGraph
, const OUString
& aMediaType
, sal_Int64 nAspect
)
286 //TODO/MBA: is that OK?
287 comphelper::EmbeddedObjectContainer
& aCnt
= GetViewData()->GetViewShell()->GetObjectShell()->GetEmbeddedObjectContainer();
288 if ( !aCnt
.HasEmbeddedObject( xObj
) )
289 aCnt
.InsertEmbeddedObject( xObj
, aName
);
291 aName
= aCnt
.GetEmbeddedObjectName( xObj
);
293 svt::EmbeddedObjectRef
aObjRef( xObj
, nAspect
);
295 aObjRef
.SetGraphic( *pReplGraph
, aMediaType
);
298 if ( nAspect
== embed::Aspects::MSOLE_ICON
)
300 MapMode
aMapMode( MAP_100TH_MM
);
301 aSize
= aObjRef
.GetSize( &aMapMode
);
305 // working with visual area can switch object to running state
306 MapUnit aMapObj
= VCLUnoHelper::UnoEmbed2VCLMapUnit( xObj
->getMapUnit( nAspect
) );
307 MapUnit aMap100
= MAP_100TH_MM
;
309 if ( pDescSize
&& pDescSize
->Width() && pDescSize
->Height() )
311 // use size from object descriptor if given
312 aSize
= OutputDevice::LogicToLogic( *pDescSize
, aMap100
, aMapObj
);
314 aSz
.Width
= aSize
.Width();
315 aSz
.Height
= aSize
.Height();
316 xObj
->setVisualAreaSize( nAspect
, aSz
);
322 aSz
= xObj
->getVisualAreaSize( nAspect
);
324 catch ( embed::NoVisualAreaSizeException
& )
326 // the default size will be set later
329 aSize
= Size( aSz
.Width
, aSz
.Height
);
330 aSize
= OutputDevice::LogicToLogic( aSize
, aMapObj
, aMap100
); // for SdrOle2Obj
332 if( aSize
.Height() == 0 || aSize
.Width() == 0 )
334 OSL_FAIL("SvObjectDescriptor::GetSize == 0");
335 aSize
.Width() = 5000;
336 aSize
.Height() = 5000;
337 aSize
= OutputDevice::LogicToLogic( aSize
, aMap100
, aMapObj
);
338 aSz
.Width
= aSize
.Width();
339 aSz
.Height
= aSize
.Height();
340 xObj
->setVisualAreaSize( nAspect
, aSz
);
344 // don't call AdjustInsertPos
345 Point aInsPos
= rPos
;
346 if ( GetViewData()->GetDocument()->IsNegativePage( GetViewData()->GetTabNo() ) )
347 aInsPos
.X() -= aSize
.Width();
348 Rectangle
aRect( aInsPos
, aSize
);
350 ScDrawView
* pDrView
= GetScDrawView();
351 SdrOle2Obj
* pSdrObj
= new SdrOle2Obj( aObjRef
, aName
, aRect
);
353 SdrPageView
* pPV
= pDrView
->GetSdrPageView();
354 pDrView
->InsertObjectSafe( pSdrObj
, *pPV
); // don't mark if OLE
355 GetViewData()->GetViewShell()->SetDrawShell( sal_True
);
362 sal_Bool
ScViewFunc::PasteBitmapEx( const Point
& rPos
, const BitmapEx
& rBmpEx
)
365 Graphic
aGraphic(rBmpEx
);
366 return PasteGraphic( rPos
, aGraphic
, aEmpty
, aEmpty
);
369 sal_Bool
ScViewFunc::PasteMetaFile( const Point
& rPos
, const GDIMetaFile
& rMtf
)
372 Graphic
aGraphic(rMtf
);
373 return PasteGraphic( rPos
, aGraphic
, aEmpty
, aEmpty
);
376 sal_Bool
ScViewFunc::PasteGraphic( const Point
& rPos
, const Graphic
& rGraphic
,
377 const OUString
& rFile
, const OUString
& rFilter
)
380 ScDrawView
* pScDrawView
= GetScDrawView();
383 Window
* pWin
= GetActiveWin();
384 MapMode aSourceMap
= rGraphic
.GetPrefMapMode();
385 MapMode
aDestMap( MAP_100TH_MM
);
387 if (aSourceMap
.GetMapUnit() == MAP_PIXEL
)
389 // consider pixel correction, so bitmap fits to screen
390 Fraction aScaleX
, aScaleY
;
391 pScDrawView
->CalcNormScale( aScaleX
, aScaleY
);
392 aDestMap
.SetScaleX(aScaleX
);
393 aDestMap
.SetScaleY(aScaleY
);
396 Size aSize
= pWin
->LogicToLogic( rGraphic
.GetPrefSize(), &aSourceMap
, &aDestMap
);
398 if ( GetViewData()->GetDocument()->IsNegativePage( GetViewData()->GetTabNo() ) )
399 aPos
.X() -= aSize
.Width();
401 GetViewData()->GetViewShell()->SetDrawShell( sal_True
);
403 Rectangle
aRect(aPos
, aSize
);
404 SdrGrafObj
* pGrafObj
= new SdrGrafObj(rGraphic
, aRect
);
406 // path was the name of the graphic in history
408 ScDrawLayer
* pLayer
= (ScDrawLayer
*) pScDrawView
->GetModel();
409 OUString aName
= pLayer
->GetNewGraphicName(); // "Graphics"
410 pGrafObj
->SetName(aName
);
413 pScDrawView
->InsertObjectSafe(pGrafObj
, *pScDrawView
->GetSdrPageView());
415 // SetGraphicLink has to be used after inserting the object,
416 // otherwise an empty graphic is swapped in and the contact stuff crashes.
418 if (!rFile
.isEmpty())
419 pGrafObj
->SetGraphicLink( rFile
, ""/*TODO?*/, rFilter
);
424 sal_Bool
ScViewFunc::ApplyGraphicToObject( SdrObject
* pPickObj
, const Graphic
& rGraphic
)
426 sal_Bool bRet
= false;
428 ScDrawView
* pScDrawView
= GetScDrawView();
429 if ( pScDrawView
&& pPickObj
)
431 /**********************************************************************
432 * New attributes for object
433 **********************************************************************/
434 SdrPageView
* pPV
= pScDrawView
->GetSdrPageView();
435 if (pPickObj
->ISA(SdrGrafObj
))
437 /******************************************************************
438 * Graphic object gets a new graphic
439 ******************************************************************/
440 SdrGrafObj
* pNewGrafObj
= (SdrGrafObj
*) pPickObj
->Clone();
441 pNewGrafObj
->SetGraphic(rGraphic
);
443 pScDrawView
->BegUndo(ScGlobal::GetRscString(STR_UNDO_DRAGDROP
));
444 pScDrawView
->ReplaceObjectAtView(pPickObj
, *pPV
, pNewGrafObj
);
445 pScDrawView
->EndUndo();
449 else if (pPickObj
->IsClosedObj() && !pPickObj
->ISA(SdrOle2Obj
))
451 /******************************************************************
452 * Object gets filled with the graphic
453 ******************************************************************/
454 pScDrawView
->AddUndo(new SdrUndoAttrObj(*pPickObj
));
456 SfxItemSet
aSet( pScDrawView
->GetModel()->GetItemPool(),
457 XATTR_FILLSTYLE
, XATTR_FILLBITMAP
);
458 aSet
.Put(XFillStyleItem(XFILL_BITMAP
));
459 aSet
.Put(XFillBitmapItem(OUString(), rGraphic
));
461 pPickObj
->SetMergedItemSetAndBroadcast(aSet
);
470 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */