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
lcl_AdjustInsertPos(ScViewData * pData,Point & rPos,Size & rSize)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
PasteDraw(const Point & rLogicPos,SdrModel * pModel,sal_Bool bGroup,sal_Bool bSameDocClipboard)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
PasteObject(const Point & rPos,const uno::Reference<embed::XEmbeddedObject> & xObj,const Size * pDescSize,const Graphic * pReplGraph,const::rtl::OUString & aMediaType,sal_Int64 nAspect)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
PasteBitmapEx(const Point & rPos,const BitmapEx & rBmpEx)373 sal_Bool ScViewFunc::PasteBitmapEx( const Point& rPos, const BitmapEx& rBmpEx )
374 {
375 String aEmpty;
376 Graphic aGraphic(rBmpEx);
377 return PasteGraphic( rPos, aGraphic, aEmpty, aEmpty );
378 }
379
PasteMetaFile(const Point & rPos,const GDIMetaFile & rMtf)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
PasteGraphic(const Point & rPos,const Graphic & rGraphic,const String & rFile,const String & rFilter)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 // #123922# check if the drop was over an existing object; if yes, evtl. replace
394 // the graphic for a SdrGraphObj (including link state updates) or adapt the fill
395 // style for other objects
396 if(pScDrawView)
397 {
398 SdrObject* pPickObj = 0;
399 SdrPageView* pPageView = pScDrawView->GetSdrPageView();
400
401 if(pPageView)
402 {
403 pScDrawView->PickObj(rPos, pScDrawView->getHitTolLog(), pPickObj, pPageView);
404 }
405
406 if(pPickObj)
407 {
408 const String aBeginUndo(ScGlobal::GetRscString(STR_UNDO_DRAGDROP));
409 SdrObject* pResult = pScDrawView->ApplyGraphicToObject(
410 *pPickObj,
411 rGraphic,
412 aBeginUndo,
413 rFile,
414 rFilter);
415
416 if(pResult)
417 {
418 // we are done; mark the modified/new object
419 pScDrawView->MarkObj(pResult, pScDrawView->GetSdrPageView());
420 return sal_True;
421 }
422 }
423 }
424
425 Point aPos( rPos );
426 Window* pWin = GetActiveWin();
427 MapMode aSourceMap = rGraphic.GetPrefMapMode();
428 MapMode aDestMap( MAP_100TH_MM );
429
430 if (aSourceMap.GetMapUnit() == MAP_PIXEL)
431 {
432 // Pixel-Korrektur beruecksichtigen, damit Bitmap auf dem Bildschirm stimmt
433
434 Fraction aScaleX, aScaleY;
435 pScDrawView->CalcNormScale( aScaleX, aScaleY );
436 aDestMap.SetScaleX(aScaleX);
437 aDestMap.SetScaleY(aScaleY);
438 }
439
440 Size aSize = pWin->LogicToLogic( rGraphic.GetPrefSize(), &aSourceMap, &aDestMap );
441 // lcl_AdjustInsertPos( GetViewData(), aPos, aSize );
442 if ( GetViewData()->GetDocument()->IsNegativePage( GetViewData()->GetTabNo() ) )
443 aPos.X() -= aSize.Width();
444
445 GetViewData()->GetViewShell()->SetDrawShell( sal_True );
446 Rectangle aRect(aPos, aSize);
447 SdrGrafObj* pGrafObj = new SdrGrafObj(rGraphic, aRect);
448
449 // #118522# calling SetGraphicLink here doesn't work
450
451 // #49961# Pfad wird nicht mehr als Name der Grafik gesetzt
452
453 ScDrawLayer* pLayer = (ScDrawLayer*) pScDrawView->GetModel();
454 String aName = pLayer->GetNewGraphicName(); // "Grafik x"
455 pGrafObj->SetName(aName);
456
457 // nicht markieren wenn Ole
458 pScDrawView->InsertObjectSafe(pGrafObj, *pScDrawView->GetSdrPageView());
459
460 // #118522# SetGraphicLink has to be used after inserting the object,
461 // otherwise an empty graphic is swapped in and the contact stuff crashes.
462 // See #i37444#.
463 if (rFile.Len())
464 pGrafObj->SetGraphicLink( rFile, rFilter );
465
466 return sal_True;
467 }
468
469