xref: /trunk/main/sc/source/ui/app/seltrans.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 
31 // INCLUDE ---------------------------------------------------------------
32 
33 
34 
35 #include <com/sun/star/beans/XPropertySet.hpp>
36 #include <com/sun/star/beans/XPropertySetInfo.hpp>
37 #include <com/sun/star/form/FormButtonType.hpp>
38 
39 #include <tools/urlobj.hxx>
40 #include <sfx2/docfile.hxx>
41 #include <svx/fmglob.hxx>
42 #include <svx/svdograf.hxx>
43 #include <svx/svdouno.hxx>
44 
45 #include "seltrans.hxx"
46 #include "transobj.hxx"
47 #include "drwtrans.hxx"
48 #include "scmod.hxx"
49 #include "dbfunc.hxx"	// for CopyToClip
50 #include "docsh.hxx"
51 #include "drawview.hxx"
52 #include "drwlayer.hxx"
53 
54 using namespace com::sun::star;
55 
56 // -----------------------------------------------------------------------
57 
58 sal_Bool lcl_IsURLButton( SdrObject* pObject )
59 {
60 	sal_Bool bRet = sal_False;
61 
62 	SdrUnoObj* pUnoCtrl = PTR_CAST(SdrUnoObj, pObject);
63 	if (pUnoCtrl && FmFormInventor == pUnoCtrl->GetObjInventor())
64    	{
65 		uno::Reference<awt::XControlModel> xControlModel = pUnoCtrl->GetUnoControlModel();
66 		DBG_ASSERT( xControlModel.is(), "uno control without model" );
67 		if ( xControlModel.is() )
68 		{
69 			uno::Reference< beans::XPropertySet > xPropSet( xControlModel, uno::UNO_QUERY );
70 			uno::Reference< beans::XPropertySetInfo > xInfo = xPropSet->getPropertySetInfo();
71 
72 			rtl::OUString sPropButtonType = rtl::OUString::createFromAscii( "ButtonType" );
73 			if(xInfo->hasPropertyByName( sPropButtonType ))
74 			{
75 				uno::Any aAny = xPropSet->getPropertyValue( sPropButtonType );
76 				form::FormButtonType eTmp;
77 				if ( (aAny >>= eTmp) && eTmp == form::FormButtonType_URL )
78 					bRet = sal_True;
79 			}
80  		}
81 	}
82 
83 	return bRet;
84 }
85 
86 // static
87 
88 ScSelectionTransferObj* ScSelectionTransferObj::CreateFromView( ScTabView* pView )
89 {
90 	ScSelectionTransferObj* pRet = NULL;
91 
92 	if ( pView )
93 	{
94 		ScSelectionTransferMode eMode = SC_SELTRANS_INVALID;
95 
96 		SdrView* pSdrView = pView->GetSdrView();
97 		if ( pSdrView )
98 		{
99 			//	handle selection on drawing layer
100 			const SdrMarkList& rMarkList = pSdrView->GetMarkedObjectList();
101 			sal_uLong nMarkCount = rMarkList.GetMarkCount();
102 			if ( nMarkCount )
103 			{
104 				if ( nMarkCount == 1 )
105 				{
106 					SdrObject* pObj = rMarkList.GetMark(0)->GetMarkedSdrObj();
107 					sal_uInt16 nSdrObjKind = pObj->GetObjIdentifier();
108 
109 					if ( nSdrObjKind == OBJ_GRAF )
110 					{
111 						if ( ((SdrGrafObj*)pObj)->GetGraphic().GetType() == GRAPHIC_BITMAP )
112 							eMode = SC_SELTRANS_DRAW_BITMAP;
113 						else
114 							eMode = SC_SELTRANS_DRAW_GRAPHIC;
115 					}
116 					else if ( nSdrObjKind == OBJ_OLE2 )
117 						eMode = SC_SELTRANS_DRAW_OLE;
118 					else if ( lcl_IsURLButton( pObj ) )
119 						eMode = SC_SELTRANS_DRAW_BOOKMARK;
120 				}
121 
122 				if ( eMode == SC_SELTRANS_INVALID )
123 					eMode = SC_SELTRANS_DRAW_OTHER;		// something selected but no special selection
124 			}
125 		}
126 		if ( eMode == SC_SELTRANS_INVALID )				// no drawing object selected
127 		{
128 			ScRange aRange;
129 			ScViewData* pViewData = pView->GetViewData();
130 			const ScMarkData& rMark = pViewData->GetMarkData();
131 			//	allow MultiMarked because GetSimpleArea may be able to merge into a simple range
132 			//	(GetSimpleArea modifies a local copy of MarkData)
133             // Also allow simple filtered area.
134             ScMarkType eMarkType;
135 			if ( ( rMark.IsMarked() || rMark.IsMultiMarked() ) &&
136                     (((eMarkType = pViewData->GetSimpleArea( aRange )) == SC_MARK_SIMPLE) ||
137                      (eMarkType == SC_MARK_SIMPLE_FILTERED)) )
138 			{
139 				//	only for "real" selection, cursor alone isn't used
140 				if ( aRange.aStart == aRange.aEnd )
141 					eMode = SC_SELTRANS_CELL;
142 				else
143 					eMode = SC_SELTRANS_CELLS;
144 			}
145 		}
146 
147 		if ( eMode != SC_SELTRANS_INVALID )
148 			pRet = new ScSelectionTransferObj( pView, eMode );
149 	}
150 
151 	return pRet;
152 }
153 
154 
155 ScSelectionTransferObj::ScSelectionTransferObj( ScTabView* pSource, ScSelectionTransferMode eNewMode ) :
156 	pView( pSource ),
157 	eMode( eNewMode ),
158 	pCellData( NULL ),
159 	pDrawData( NULL )
160 {
161 	//!	store range for StillValid
162 }
163 
164 ScSelectionTransferObj::~ScSelectionTransferObj()
165 {
166 	ScModule* pScMod = SC_MOD();
167 	if ( pScMod->GetSelectionTransfer() == this )
168 	{
169 		//	this is reached when the object wasn't really copied to the selection
170 		//	(CopyToSelection has no effect under Windows)
171 
172 		ForgetView();
173 		pScMod->SetSelectionTransfer( NULL );
174 	}
175 
176 	DBG_ASSERT( !pView, "ScSelectionTransferObj dtor: ForgetView not called" );
177 }
178 
179 sal_Bool ScSelectionTransferObj::StillValid()
180 {
181 	//!	check if view still has same cell selection
182 	//!	(but return sal_False if data has changed inbetween)
183 	return sal_False;
184 }
185 
186 void ScSelectionTransferObj::ForgetView()
187 {
188 	pView = NULL;
189 	eMode = SC_SELTRANS_INVALID;
190 
191 	if (pCellData)
192 	{
193 		pCellData->release();
194 		pCellData = NULL;
195 	}
196 	if (pDrawData)
197 	{
198 		pDrawData->release();
199 		pDrawData = NULL;
200 	}
201 }
202 
203 void ScSelectionTransferObj::AddSupportedFormats()
204 {
205 	//	AddSupportedFormats must work without actually creating the
206 	//	"real" transfer object
207 
208 	switch (eMode)
209 	{
210 		case SC_SELTRANS_CELL:
211 		case SC_SELTRANS_CELLS:
212 			//	same formats as in ScTransferObj::AddSupportedFormats
213 			AddFormat( SOT_FORMATSTR_ID_EMBED_SOURCE );
214 			AddFormat( SOT_FORMATSTR_ID_OBJECTDESCRIPTOR );
215 			AddFormat( SOT_FORMAT_GDIMETAFILE );
216 			AddFormat( SOT_FORMAT_BITMAP );
217 			AddFormat( SOT_FORMATSTR_ID_HTML );
218 			AddFormat( SOT_FORMATSTR_ID_SYLK );
219 			AddFormat( SOT_FORMATSTR_ID_LINK );
220 			AddFormat( SOT_FORMATSTR_ID_DIF );
221 			AddFormat( SOT_FORMAT_STRING );
222 			AddFormat( SOT_FORMAT_RTF );
223 			if ( eMode == SC_SELTRANS_CELL )
224 				AddFormat( SOT_FORMATSTR_ID_EDITENGINE );
225 			break;
226 
227 		// different graphic formats as in ScDrawTransferObj::AddSupportedFormats:
228 
229 		case SC_SELTRANS_DRAW_BITMAP:
230 			AddFormat( SOT_FORMATSTR_ID_OBJECTDESCRIPTOR );
231 			AddFormat( SOT_FORMATSTR_ID_SVXB );
232         	AddFormat( SOT_FORMAT_BITMAP );
233         	AddFormat( SOT_FORMAT_GDIMETAFILE );
234 			break;
235 
236 		case SC_SELTRANS_DRAW_GRAPHIC:
237 			AddFormat( SOT_FORMATSTR_ID_OBJECTDESCRIPTOR );
238         	AddFormat( SOT_FORMATSTR_ID_SVXB );
239         	AddFormat( SOT_FORMAT_GDIMETAFILE );
240         	AddFormat( SOT_FORMAT_BITMAP );
241  			break;
242 
243 		case SC_SELTRANS_DRAW_BOOKMARK:
244         	AddFormat( SOT_FORMATSTR_ID_OBJECTDESCRIPTOR );
245         	AddFormat( SOT_FORMATSTR_ID_SOLK );
246         	AddFormat( SOT_FORMAT_STRING );
247         	AddFormat( SOT_FORMATSTR_ID_UNIFORMRESOURCELOCATOR );
248         	AddFormat( SOT_FORMATSTR_ID_NETSCAPE_BOOKMARK );
249         	AddFormat( SOT_FORMATSTR_ID_DRAWING );
250 			break;
251 
252 		case SC_SELTRANS_DRAW_OLE:
253 			AddFormat( SOT_FORMATSTR_ID_EMBED_SOURCE );
254         	AddFormat( SOT_FORMATSTR_ID_OBJECTDESCRIPTOR );
255         	AddFormat( SOT_FORMAT_GDIMETAFILE );
256 			break;
257 
258 		case SC_SELTRANS_DRAW_OTHER:
259 			//	other drawing objects
260 	        AddFormat( SOT_FORMATSTR_ID_EMBED_SOURCE );
261         	AddFormat( SOT_FORMATSTR_ID_OBJECTDESCRIPTOR );
262         	AddFormat( SOT_FORMATSTR_ID_DRAWING );
263         	AddFormat( SOT_FORMAT_BITMAP );
264         	AddFormat( SOT_FORMAT_GDIMETAFILE );
265 			break;
266 
267         default:
268         {
269             // added to avoid warnings
270         }
271 	}
272 }
273 
274 void ScSelectionTransferObj::CreateCellData()
275 {
276 	DBG_ASSERT( !pCellData, "CreateCellData twice" );
277 	if ( pView )
278 	{
279 		ScViewData* pViewData = pView->GetViewData();
280 		ScMarkData aNewMark( pViewData->GetMarkData() );	// use local copy for MarkToSimple
281 		aNewMark.MarkToSimple();
282 
283 		//	similar to ScViewFunctionSet::BeginDrag
284 		if ( aNewMark.IsMarked() && !aNewMark.IsMultiMarked() )
285 		{
286 			ScDocShell* pDocSh = pViewData->GetDocShell();
287 
288 			ScRange aSelRange;
289 			aNewMark.GetMarkArea( aSelRange );
290 			ScDocShellRef aDragShellRef;
291 			if ( pDocSh->GetDocument()->HasOLEObjectsInArea( aSelRange, &aNewMark ) )
292 			{
293 				aDragShellRef = new ScDocShell;		// DocShell needs a Ref immediately
294 				aDragShellRef->DoInitNew(NULL);
295 			}
296 			ScDrawLayer::SetGlobalDrawPersist(aDragShellRef);
297 
298 			ScDocument* pClipDoc = new ScDocument( SCDOCMODE_CLIP );
299 			// bApi = sal_True -> no error mesages
300 			// #i18364# bStopEdit = sal_False -> don't end edit mode
301 			// (this may be called from pasting into the edit line)
302 			sal_Bool bCopied = pViewData->GetView()->CopyToClip( pClipDoc, sal_False, sal_True, sal_True, sal_False );
303 
304 			ScDrawLayer::SetGlobalDrawPersist(NULL);
305 
306 			if ( bCopied )
307 			{
308 				TransferableObjectDescriptor aObjDesc;
309 				pDocSh->FillTransferableObjectDescriptor( aObjDesc );
310 				aObjDesc.maDisplayName = pDocSh->GetMedium()->GetURLObject().GetURLNoPass();
311 				// maSize is set in ScTransferObj ctor
312 
313 				ScTransferObj* pTransferObj = new ScTransferObj( pClipDoc, aObjDesc );
314 				uno::Reference<datatransfer::XTransferable> xTransferable( pTransferObj );
315 
316 				// SetDragHandlePos is not used - there is no mouse position
317 				//? pTransferObj->SetVisibleTab( nTab );
318 
319                 SfxObjectShellRef aPersistRef( aDragShellRef );
320 				pTransferObj->SetDrawPersist( aPersistRef );	// keep persist for ole objects alive
321 
322 				pTransferObj->SetDragSource( pDocSh, aNewMark );
323 
324 				pCellData = pTransferObj;
325 				pCellData->acquire();		// keep ref count up - released in ForgetView
326 			}
327 			else
328 				delete pClipDoc;
329 		}
330 	}
331 	DBG_ASSERT( pCellData, "can't create CellData" );
332 }
333 
334 //!	make static member of ScDrawView
335 extern void lcl_CheckOle( const SdrMarkList& rMarkList, sal_Bool& rAnyOle, sal_Bool& rOneOle );
336 
337 void ScSelectionTransferObj::CreateDrawData()
338 {
339 	DBG_ASSERT( !pDrawData, "CreateDrawData twice" );
340 	if ( pView )
341 	{
342 		//	similar to ScDrawView::BeginDrag
343 
344 		ScDrawView* pDrawView = pView->GetScDrawView();
345 		if ( pDrawView )
346 		{
347 			sal_Bool bAnyOle, bOneOle;
348 			const SdrMarkList& rMarkList = pDrawView->GetMarkedObjectList();
349 			lcl_CheckOle( rMarkList, bAnyOle, bOneOle );
350 
351 			//---------------------------------------------------------
352 			ScDocShellRef aDragShellRef;
353 			if (bAnyOle)
354 			{
355 				aDragShellRef = new ScDocShell;		// ohne Ref lebt die DocShell nicht !!!
356 				aDragShellRef->DoInitNew(NULL);
357 			}
358 			//---------------------------------------------------------
359 
360 			ScDrawLayer::SetGlobalDrawPersist(aDragShellRef);
361 			SdrModel* pModel = pDrawView->GetAllMarkedModel();
362 			ScDrawLayer::SetGlobalDrawPersist(NULL);
363 
364 			ScViewData* pViewData = pView->GetViewData();
365 			ScDocShell* pDocSh = pViewData->GetDocShell();
366 
367 			TransferableObjectDescriptor aObjDesc;
368 			pDocSh->FillTransferableObjectDescriptor( aObjDesc );
369 			aObjDesc.maDisplayName = pDocSh->GetMedium()->GetURLObject().GetURLNoPass();
370 			// maSize is set in ScDrawTransferObj ctor
371 
372 			ScDrawTransferObj* pTransferObj = new ScDrawTransferObj( pModel, pDocSh, aObjDesc );
373 			uno::Reference<datatransfer::XTransferable> xTransferable( pTransferObj );
374 
375             SfxObjectShellRef aPersistRef( aDragShellRef );
376 			pTransferObj->SetDrawPersist( aPersistRef );	// keep persist for ole objects alive
377 			pTransferObj->SetDragSource( pDrawView );		// copies selection
378 
379 			pDrawData = pTransferObj;
380 			pDrawData->acquire();		// keep ref count up - released in ForgetView
381 		}
382 	}
383 	DBG_ASSERT( pDrawData, "can't create DrawData" );
384 }
385 
386 ScTransferObj* ScSelectionTransferObj::GetCellData()
387 {
388 	if ( !pCellData && ( eMode == SC_SELTRANS_CELL || eMode == SC_SELTRANS_CELLS ) )
389 		CreateCellData();
390 	return pCellData;
391 }
392 
393 ScDrawTransferObj* ScSelectionTransferObj::GetDrawData()
394 {
395 	if ( !pDrawData && ( eMode == SC_SELTRANS_DRAW_BITMAP || eMode == SC_SELTRANS_DRAW_GRAPHIC ||
396 						 eMode == SC_SELTRANS_DRAW_BOOKMARK || eMode == SC_SELTRANS_DRAW_OLE ||
397 						 eMode == SC_SELTRANS_DRAW_OTHER ) )
398 		CreateDrawData();
399 	return pDrawData;
400 }
401 
402 sal_Bool ScSelectionTransferObj::GetData( const ::com::sun::star::datatransfer::DataFlavor& rFlavor )
403 {
404 	sal_Bool bOK = sal_False;
405 
406 	uno::Reference<datatransfer::XTransferable> xSource;
407 	switch (eMode)
408 	{
409 		case SC_SELTRANS_CELL:
410 		case SC_SELTRANS_CELLS:
411 			xSource = GetCellData();
412 			break;
413 		case SC_SELTRANS_DRAW_BITMAP:
414 		case SC_SELTRANS_DRAW_GRAPHIC:
415 		case SC_SELTRANS_DRAW_BOOKMARK:
416 		case SC_SELTRANS_DRAW_OLE:
417 		case SC_SELTRANS_DRAW_OTHER:
418 			xSource = GetDrawData();
419 			break;
420         default:
421         {
422             // added to avoid warnings
423         }
424 	}
425 
426 	if ( xSource.is() )
427 	{
428 		TransferableDataHelper aHelper( xSource );
429 		uno::Any aAny = aHelper.GetAny( rFlavor );
430 		bOK = SetAny( aAny, rFlavor );
431 	}
432 
433 	return bOK;
434 }
435 
436 void ScSelectionTransferObj::ObjectReleased()
437 {
438 	//	called when another selection is set from outside
439 
440 	ForgetView();
441 
442 	ScModule* pScMod = SC_MOD();
443 	if ( pScMod->GetSelectionTransfer() == this )
444 		pScMod->SetSelectionTransfer( NULL );
445 
446 	TransferableHelper::ObjectReleased();
447 }
448 
449 
450