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