xref: /aoo42x/main/sc/source/ui/view/viewfun7.cxx (revision 70d3707a)
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