xref: /trunk/main/sc/source/ui/view/drawvie4.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 #include <svx/svditer.hxx>
36 #include <svx/svdograf.hxx>
37 #include <svx/svdogrp.hxx>
38 #include <svx/svdoole2.hxx>
39 #include <svx/svdpage.hxx>
40 #include <svx/svdundo.hxx>
41 #include <sfx2/docfile.hxx>
42 #include <tools/urlobj.hxx>
43 #include <toolkit/helper/vclunohelper.hxx>
44 
45 #include "drawview.hxx"
46 #include "global.hxx"
47 #include "drwlayer.hxx"
48 #include "viewdata.hxx"
49 #include "document.hxx"
50 #include "docsh.hxx"
51 #include "drwtrans.hxx"
52 #include "transobj.hxx"		// SetDrawClipDoc
53 #include "drawutil.hxx"
54 #include "scmod.hxx"
55 #include "globstr.hrc"
56 #include "chartarr.hxx"
57 
58 using namespace com::sun::star;
59 
60 // STATIC DATA -----------------------------------------------------------
61 
62 Point aDragStartDiff;
63 
64 // -----------------------------------------------------------------------
65 
66 //!	welche Funktionen aus drawview/drawvie4 muessen wirklich ohne Optimierung sein?
67 
68 #ifdef _MSC_VER
69 #pragma optimize ( "", off )
70 #endif
71 
72 // -----------------------------------------------------------------------
73 
74 void lcl_CheckOle( const SdrMarkList& rMarkList, sal_Bool& rAnyOle, sal_Bool& rOneOle )
75 {
76 	rAnyOle = rOneOle = sal_False;
77 	sal_uLong nCount = rMarkList.GetMarkCount();
78     for (sal_uLong i=0; i<nCount; i++)
79     {
80         SdrMark* pMark = rMarkList.GetMark(i);
81         SdrObject* pObj = pMark->GetMarkedSdrObj();
82         sal_uInt16 nSdrObjKind = pObj->GetObjIdentifier();
83         if (nSdrObjKind == OBJ_OLE2)
84         {
85             rAnyOle = sal_True;
86             rOneOle = (nCount == 1);
87             break;
88         }
89 		else if ( pObj->ISA(SdrObjGroup) )
90 		{
91 			SdrObjListIter aIter( *pObj, IM_DEEPNOGROUPS );
92 			SdrObject* pSubObj = aIter.Next();
93 			while (pSubObj)
94 			{
95 				if ( pSubObj->GetObjIdentifier() == OBJ_OLE2 )
96 				{
97 		            rAnyOle = sal_True;
98 		            // rOneOle remains sal_False - a group isn't treated like a single OLE object
99 		            return;
100 				}
101 				pSubObj = aIter.Next();
102 			}
103 		}
104     }
105 }
106 
107 #if 0
108 void lcl_RefreshChartData( SdrModel* pModel, ScDocument* pSourceDoc )
109 {
110 	sal_uInt16 nPages = pModel->GetPageCount();
111 	for (SCTAB nTab=0; nTab<nPages; nTab++)
112 	{
113 		SdrPage* pPage = pModel->GetPage(nTab);
114 		SdrObjListIter aIter( *pPage, IM_DEEPNOGROUPS );
115 		SdrObject* pObject = aIter.Next();
116 		while (pObject)
117 		{
118 			if ( pObject->GetObjIdentifier() == OBJ_OLE2 )
119 			{
120 				SvInPlaceObjectRef aIPObj = ((SdrOle2Obj*)pObject)->GetObjRef();
121 				if ( aIPObj.Is() && SotExchange::IsChart( aIPObj->GetStorage()->GetClassName() ) )
122 				{
123 					SchMemChart* pOldData = SchDLL::GetChartData(aIPObj);
124 					if ( pOldData )
125 					{
126 						//	create data from source document
127 						ScChartArray aArray( pSourceDoc, *pOldData );
128 						if ( aArray.IsValid() )
129 						{
130 							SchMemChart* pNewData = aArray.CreateMemChart();
131 							SchDLL::Update( aIPObj, pNewData );
132 							delete pNewData;
133                 			((SdrOle2Obj*)pObject)->GetNewReplacement();
134 						}
135 					}
136 				}
137 			}
138 			pObject = aIter.Next();
139 		}
140 	}
141 }
142 #endif
143 
144 
145 sal_Bool ScDrawView::BeginDrag( Window* pWindow, const Point& rStartPos )
146 {
147 	sal_Bool bReturn = sal_False;
148 
149 	if ( AreObjectsMarked() )
150 	{
151 		BrkAction();
152 
153 		Rectangle aMarkedRect = GetAllMarkedRect();
154 		Region aRegion( aMarkedRect );
155 
156 		aDragStartDiff = rStartPos - aMarkedRect.TopLeft();
157 
158 		sal_Bool bAnyOle, bOneOle;
159 		const SdrMarkList& rMarkList = GetMarkedObjectList();
160 		lcl_CheckOle( rMarkList, bAnyOle, bOneOle );
161 
162 		ScDocShellRef aDragShellRef;
163 		if (bAnyOle)
164 		{
165 			aDragShellRef = new ScDocShell;		// DocShell needs a Ref immediately
166 			aDragShellRef->DoInitNew(NULL);
167 		}
168 		ScDrawLayer::SetGlobalDrawPersist(aDragShellRef);
169 		SdrModel* pModel = GetAllMarkedModel();
170 		ScDrawLayer::SetGlobalDrawPersist(NULL);
171 
172 		//	Charts now always copy their data in addition to the source reference, so
173 		//	there's no need to call SchDLL::Update for the charts in the clipboard doc.
174 		//	Update with the data (including NumberFormatter) from the live document would
175 		//	also store the NumberFormatter in the clipboard chart (#88749#)
176 		// lcl_RefreshChartData( pModel, pViewData->GetDocument() );
177 
178 		ScDocShell* pDocSh = pViewData->GetDocShell();
179 
180 		TransferableObjectDescriptor aObjDesc;
181 		pDocSh->FillTransferableObjectDescriptor( aObjDesc );
182 		aObjDesc.maDisplayName = pDocSh->GetMedium()->GetURLObject().GetURLNoPass();
183 		// maSize is set in ScDrawTransferObj ctor
184 
185 		ScDrawTransferObj* pTransferObj = new ScDrawTransferObj( pModel, pDocSh, aObjDesc );
186 		uno::Reference<datatransfer::XTransferable> xTransferable( pTransferObj );
187 
188         pTransferObj->SetDrawPersist( &aDragShellRef );    // keep persist for ole objects alive
189 		pTransferObj->SetDragSource( this );			// copies selection
190 
191 		SC_MOD()->SetDragObject( NULL, pTransferObj );		// for internal D&D
192 		pTransferObj->StartDrag( pWindow, DND_ACTION_COPYMOVE | DND_ACTION_LINK );
193 	}
194 
195 	return bReturn;
196 }
197 
198 void ScDrawView::DoCopy()
199 {
200 	sal_Bool bAnyOle, bOneOle;
201 	const SdrMarkList& rMarkList = GetMarkedObjectList();
202 	lcl_CheckOle( rMarkList, bAnyOle, bOneOle );
203 
204 	// update ScGlobal::pDrawClipDocShellRef
205 	ScDrawLayer::SetGlobalDrawPersist( ScTransferObj::SetDrawClipDoc( bAnyOle ) );
206 	SdrModel* pModel = GetAllMarkedModel();
207 	ScDrawLayer::SetGlobalDrawPersist(NULL);
208 
209 	//	Charts now always copy their data in addition to the source reference, so
210 	//	there's no need to call SchDLL::Update for the charts in the clipboard doc.
211 	//	Update with the data (including NumberFormatter) from the live document would
212 	//	also store the NumberFormatter in the clipboard chart (#88749#)
213 	// lcl_RefreshChartData( pModel, pViewData->GetDocument() );
214 
215 	ScDocShell* pDocSh = pViewData->GetDocShell();
216 
217 	TransferableObjectDescriptor aObjDesc;
218 	pDocSh->FillTransferableObjectDescriptor( aObjDesc );
219 	aObjDesc.maDisplayName = pDocSh->GetMedium()->GetURLObject().GetURLNoPass();
220 	// maSize is set in ScDrawTransferObj ctor
221 
222 	ScDrawTransferObj* pTransferObj = new ScDrawTransferObj( pModel, pDocSh, aObjDesc );
223 	uno::Reference<datatransfer::XTransferable> xTransferable( pTransferObj );
224 
225 	if ( ScGlobal::pDrawClipDocShellRef )
226 	{
227         pTransferObj->SetDrawPersist( &(*ScGlobal::pDrawClipDocShellRef) );    // keep persist for ole objects alive
228 	}
229 
230 	pTransferObj->CopyToClipboard( pViewData->GetActiveWin() );		// system clipboard
231 	SC_MOD()->SetClipObject( NULL, pTransferObj );					// internal clipboard
232 }
233 
234 uno::Reference<datatransfer::XTransferable> ScDrawView::CopyToTransferable()
235 {
236 	sal_Bool bAnyOle, bOneOle;
237 	const SdrMarkList& rMarkList = GetMarkedObjectList();
238 	lcl_CheckOle( rMarkList, bAnyOle, bOneOle );
239 
240 	// update ScGlobal::pDrawClipDocShellRef
241 	ScDrawLayer::SetGlobalDrawPersist( ScTransferObj::SetDrawClipDoc( bAnyOle ) );
242 	SdrModel* pModel = GetAllMarkedModel();
243 	ScDrawLayer::SetGlobalDrawPersist(NULL);
244 
245 	//	Charts now always copy their data in addition to the source reference, so
246 	//	there's no need to call SchDLL::Update for the charts in the clipboard doc.
247 	//	Update with the data (including NumberFormatter) from the live document would
248 	//	also store the NumberFormatter in the clipboard chart (#88749#)
249 	// lcl_RefreshChartData( pModel, pViewData->GetDocument() );
250 
251 	ScDocShell* pDocSh = pViewData->GetDocShell();
252 
253 	TransferableObjectDescriptor aObjDesc;
254 	pDocSh->FillTransferableObjectDescriptor( aObjDesc );
255 	aObjDesc.maDisplayName = pDocSh->GetMedium()->GetURLObject().GetURLNoPass();
256 	// maSize is set in ScDrawTransferObj ctor
257 
258 	ScDrawTransferObj* pTransferObj = new ScDrawTransferObj( pModel, pDocSh, aObjDesc );
259 	uno::Reference<datatransfer::XTransferable> xTransferable( pTransferObj );
260 
261 	if ( ScGlobal::pDrawClipDocShellRef )
262 	{
263         pTransferObj->SetDrawPersist( &(*ScGlobal::pDrawClipDocShellRef) );    // keep persist for ole objects alive
264 	}
265 
266     return xTransferable;
267 }
268 
269 //	Korrektur fuer 100% berechnen, unabhaengig von momentanen Einstellungen
270 
271 void ScDrawView::CalcNormScale( Fraction& rFractX, Fraction& rFractY ) const
272 {
273 	Point aLogic = pDev->LogicToPixel( Point(1000,1000), MAP_TWIP );
274 	double nPPTX = ScGlobal::nScreenPPTX;
275 	double nPPTY = ScGlobal::nScreenPPTY;
276 
277 	if (pViewData)
278 		nPPTX /= pViewData->GetDocShell()->GetOutputFactor();
279 
280 	SCCOL nEndCol = 0;
281 	SCROW nEndRow = 0;
282 	pDoc->GetTableArea( nTab, nEndCol, nEndRow );
283 	if (nEndCol<20)
284 		nEndCol = 20;
285 	if (nEndRow<20)
286         nEndRow = 20;
287 
288 	Fraction aZoom(1,1);
289 	ScDrawUtil::CalcScale( pDoc, nTab, 0,0, nEndCol,nEndRow, pDev, aZoom,aZoom,
290 							nPPTX, nPPTY, rFractX,rFractY );
291 }
292 
293 void ScDrawView::SetMarkedOriginalSize()
294 {
295 	SdrUndoGroup* pUndoGroup = new SdrUndoGroup(*GetModel());
296 
297 	const SdrMarkList& rMarkList = GetMarkedObjectList();
298 	long nDone = 0;
299 	sal_uLong nCount = rMarkList.GetMarkCount();
300 	for (sal_uLong i=0; i<nCount; i++)
301 	{
302 		SdrObject* pObj = rMarkList.GetMark(i)->GetMarkedSdrObj();
303 		sal_uInt16 nIdent = pObj->GetObjIdentifier();
304 		sal_Bool bDo = sal_False;
305 		Size aOriginalSize;
306 		if (nIdent == OBJ_OLE2)
307 		{
308             // TODO/LEAN: working with visual area can switch object to running state
309             uno::Reference < embed::XEmbeddedObject > xObj( ((SdrOle2Obj*)pObj)->GetObjRef(), uno::UNO_QUERY );
310             if ( xObj.is() )    // #121612# NULL for an invalid object that couldn't be loaded
311             {
312 				sal_Int64 nAspect = ((SdrOle2Obj*)pObj)->GetAspect();
313 
314 				if ( nAspect == embed::Aspects::MSOLE_ICON )
315 				{
316 					MapMode aMapMode( MAP_100TH_MM );
317 					aOriginalSize = ((SdrOle2Obj*)pObj)->GetOrigObjSize( &aMapMode );
318 					bDo = sal_True;
319 				}
320 				else
321 				{
322 					MapUnit aUnit = VCLUnoHelper::UnoEmbed2VCLMapUnit( xObj->getMapUnit( ((SdrOle2Obj*)pObj)->GetAspect() ) );
323 					awt::Size aSz;
324 					try
325 					{
326 						aSz = xObj->getVisualAreaSize( ((SdrOle2Obj*)pObj)->GetAspect() );
327 						aOriginalSize = OutputDevice::LogicToLogic(
328 											Size( aSz.Width, aSz.Height ),
329 											aUnit, MAP_100TH_MM );
330 						bDo = sal_True;
331 					} catch( embed::NoVisualAreaSizeException& )
332 					{
333 						OSL_ENSURE( sal_False, "Can't get the original size of the object!" );
334 					}
335 				}
336             }
337 		}
338 		else if (nIdent == OBJ_GRAF)
339 		{
340 			const Graphic& rGraphic = ((SdrGrafObj*)pObj)->GetGraphic();
341 
342 			MapMode aSourceMap = rGraphic.GetPrefMapMode();
343 			MapMode aDestMap( MAP_100TH_MM );
344 			if (aSourceMap.GetMapUnit() == MAP_PIXEL)
345 			{
346 				//	Pixel-Korrektur beruecksichtigen, damit Bitmap auf dem Bildschirm stimmt
347 
348 				Fraction aNormScaleX, aNormScaleY;
349 				CalcNormScale( aNormScaleX, aNormScaleY );
350 				aDestMap.SetScaleX(aNormScaleX);
351 				aDestMap.SetScaleY(aNormScaleY);
352 			}
353 			if (pViewData)
354 			{
355 				Window* pActWin = pViewData->GetActiveWin();
356 				if (pActWin)
357 				{
358 					aOriginalSize = pActWin->LogicToLogic(
359 									rGraphic.GetPrefSize(), &aSourceMap, &aDestMap );
360 					bDo = sal_True;
361 				}
362 			}
363 		}
364 
365 		if ( bDo )
366 		{
367 			Rectangle aDrawRect = pObj->GetLogicRect();
368 
369 			pUndoGroup->AddAction( new SdrUndoGeoObj( *pObj ) );
370 			pObj->Resize( aDrawRect.TopLeft(), Fraction( aOriginalSize.Width(), aDrawRect.GetWidth() ),
371 												 Fraction( aOriginalSize.Height(), aDrawRect.GetHeight() ) );
372 			++nDone;
373 		}
374 	}
375 
376 	if (nDone)
377 	{
378 		pUndoGroup->SetComment(ScGlobal::GetRscString( STR_UNDO_ORIGINALSIZE ));
379         ScDocShell* pDocSh = pViewData->GetDocShell();
380         pDocSh->GetUndoManager()->AddUndoAction(pUndoGroup);
381         pDocSh->SetDrawModified();
382 	}
383 	else
384 		delete pUndoGroup;
385 }
386 
387 
388 #ifdef _MSC_VER
389 #pragma optimize ( "", on )
390 #endif
391 
392 
393 
394 
395