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