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