xref: /aoo41x/main/svtools/source/misc/transfer2.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_svtools.hxx"
30 #include <vos/mutex.hxx>
31 #include <tools/debug.hxx>
32 #include <tools/urlobj.hxx>
33 #include <unotools/ucbstreamhelper.hxx>
34 #include <sot/exchange.hxx>
35 #include <sot/storage.hxx>
36 #include <vcl/bitmap.hxx>
37 #include <vcl/gdimtf.hxx>
38 #include <vcl/graph.hxx>
39 #include <vcl/svapp.hxx>
40 #include <vcl/window.hxx>
41 #include <comphelper/processfactory.hxx>
42 #include <com/sun/star/datatransfer/dnd/XDropTargetDragContext.hpp>
43 #include "svl/urlbmk.hxx"
44 #include <svtools/inetimg.hxx>
45 #include <svtools/imap.hxx>
46 #include <svtools/transfer.hxx>
47 
48 // --------------
49 // - Namespaces -
50 // --------------
51 
52 using namespace ::com::sun::star::uno;
53 using namespace ::com::sun::star::lang;
54 using namespace ::com::sun::star::io;
55 using namespace ::com::sun::star::datatransfer;
56 using namespace ::com::sun::star::datatransfer::clipboard;
57 using namespace ::com::sun::star::datatransfer::dnd;
58 
59 // -----------------------------------------
60 // - DragSourceHelper::DragGestureListener -
61 // -----------------------------------------
62 
63 DragSourceHelper::DragGestureListener::DragGestureListener( DragSourceHelper& rDragSourceHelper ) :
64 	mrParent( rDragSourceHelper )
65 {
66 }
67 
68 // -----------------------------------------------------------------------------
69 
70 DragSourceHelper::DragGestureListener::~DragGestureListener()
71 {
72 }
73 
74 // -----------------------------------------------------------------------------
75 
76 void SAL_CALL DragSourceHelper::DragGestureListener::disposing( const EventObject& ) throw( RuntimeException )
77 {
78 }
79 
80 // -----------------------------------------------------------------------------
81 
82 void SAL_CALL DragSourceHelper::DragGestureListener::dragGestureRecognized( const DragGestureEvent& rDGE ) throw( RuntimeException )
83 {
84 	const ::vos::OGuard aGuard( Application::GetSolarMutex() );
85 
86 	const Point aPtPixel( rDGE.DragOriginX, rDGE.DragOriginY );
87 	mrParent.StartDrag( rDGE.DragAction, aPtPixel );
88 }
89 
90 // --------------------
91 // - DragSourceHelper -
92 // --------------------
93 
94 DragSourceHelper::DragSourceHelper( Window* pWindow ) :
95 	mxDragGestureRecognizer( pWindow->GetDragGestureRecognizer() )
96 {
97 	if( mxDragGestureRecognizer.is() )
98 	{
99 		mxDragGestureListener = new DragSourceHelper::DragGestureListener( *this );
100 		mxDragGestureRecognizer->addDragGestureListener( mxDragGestureListener );
101 	}
102 }
103 
104 // -----------------------------------------------------------------------------
105 
106 DragSourceHelper::~DragSourceHelper()
107 {
108 	if( mxDragGestureRecognizer.is()  )
109 		mxDragGestureRecognizer->removeDragGestureListener( mxDragGestureListener );
110 }
111 
112 // -----------------------------------------------------------------------------
113 
114 void DragSourceHelper::StartDrag( sal_Int8, const Point& )
115 {
116 }
117 
118 // ----------------------------------------
119 // - DropTargetHelper::DropTargetListener -
120 // ----------------------------------------
121 
122 DropTargetHelper::DropTargetListener::DropTargetListener( DropTargetHelper& rDropTargetHelper ) :
123 	mrParent( rDropTargetHelper ),
124     mpLastDragOverEvent( NULL )
125 {
126 }
127 
128 // -----------------------------------------------------------------------------
129 
130 DropTargetHelper::DropTargetListener::~DropTargetListener()
131 {
132     delete mpLastDragOverEvent;
133 }
134 
135 // -----------------------------------------------------------------------------
136 
137 void SAL_CALL DropTargetHelper::DropTargetListener::disposing( const EventObject& ) throw( RuntimeException )
138 {
139 }
140 
141 // -----------------------------------------------------------------------------
142 
143 void SAL_CALL DropTargetHelper::DropTargetListener::drop( const DropTargetDropEvent& rDTDE ) throw( RuntimeException )
144 {
145 	const ::vos::OGuard aGuard( Application::GetSolarMutex() );
146 
147 	try
148 	{
149         AcceptDropEvent  aAcceptEvent;
150         ExecuteDropEvent aExecuteEvt( rDTDE.DropAction & ~DNDConstants::ACTION_DEFAULT, Point( rDTDE.LocationX, rDTDE.LocationY ), rDTDE );
151         sal_Int8         nRet = DNDConstants::ACTION_NONE;
152 
153         aExecuteEvt.mbDefault = ( ( rDTDE.DropAction & DNDConstants::ACTION_DEFAULT ) != 0 );
154 
155         // in case of a default action, call ::AcceptDrop first and use the returned
156         // accepted action as the execute action in the call to ::ExecuteDrop
157         aAcceptEvent.mnAction = aExecuteEvt.mnAction;
158         aAcceptEvent.maPosPixel = aExecuteEvt.maPosPixel;
159         (DropTargetEvent&)( aAcceptEvent.maDragEvent ) = (DropTargetEvent&) rDTDE;
160         ( (DropTargetDragEvent&)( aAcceptEvent.maDragEvent ) ).DropAction = rDTDE.DropAction;
161         ( (DropTargetDragEvent&)( aAcceptEvent.maDragEvent ) ).LocationX = rDTDE.LocationX;
162         ( (DropTargetDragEvent&)( aAcceptEvent.maDragEvent ) ).LocationY = rDTDE.LocationY;
163         ( (DropTargetDragEvent&)( aAcceptEvent.maDragEvent ) ).SourceActions = rDTDE.SourceActions;
164         aAcceptEvent.mbLeaving = sal_False;
165         aAcceptEvent.mbDefault = aExecuteEvt.mbDefault;
166 
167         nRet = mrParent.AcceptDrop( aAcceptEvent );
168 
169 		if( DNDConstants::ACTION_NONE != nRet )
170         {
171 			rDTDE.Context->acceptDrop( nRet );
172 
173             if( aExecuteEvt.mbDefault )
174                 aExecuteEvt.mnAction = nRet;
175 
176     	    nRet = mrParent.ExecuteDrop( aExecuteEvt );
177         }
178 
179 		rDTDE.Context->dropComplete( DNDConstants::ACTION_NONE != nRet );
180 
181         if( mpLastDragOverEvent )
182         {
183             delete mpLastDragOverEvent;
184             mpLastDragOverEvent = NULL;
185         }
186 	}
187 	catch( const ::com::sun::star::uno::Exception& )
188 	{
189 	}
190 }
191 
192 // -----------------------------------------------------------------------------
193 
194 void SAL_CALL DropTargetHelper::DropTargetListener::dragEnter( const DropTargetDragEnterEvent& rDTDEE ) throw( RuntimeException )
195 {
196 	const ::vos::OGuard aGuard( Application::GetSolarMutex() );
197 
198 	try
199 	{
200 		mrParent.ImplBeginDrag( rDTDEE.SupportedDataFlavors );
201 	}
202 	catch( const ::com::sun::star::uno::Exception& )
203 	{
204 	}
205 
206 	dragOver( rDTDEE );
207 }
208 
209 // -----------------------------------------------------------------------------
210 
211 void SAL_CALL DropTargetHelper::DropTargetListener::dragOver( const DropTargetDragEvent& rDTDE ) throw( RuntimeException )
212 {
213 	const ::vos::OGuard aGuard( Application::GetSolarMutex() );
214 
215 	try
216 	{
217         if( mpLastDragOverEvent )
218             delete mpLastDragOverEvent;
219 
220         mpLastDragOverEvent = new AcceptDropEvent( rDTDE.DropAction & ~DNDConstants::ACTION_DEFAULT, Point( rDTDE.LocationX, rDTDE.LocationY ), rDTDE );
221         mpLastDragOverEvent->mbDefault = ( ( rDTDE.DropAction & DNDConstants::ACTION_DEFAULT ) != 0 );
222 
223 		const sal_Int8 nRet = mrParent.AcceptDrop( *mpLastDragOverEvent );
224 
225 		if( DNDConstants::ACTION_NONE == nRet )
226 			rDTDE.Context->rejectDrag();
227 		else
228 			rDTDE.Context->acceptDrag( nRet );
229 	}
230 	catch( const ::com::sun::star::uno::Exception& )
231 	{
232 	}
233 }
234 
235 // -----------------------------------------------------------------------------
236 
237 void SAL_CALL DropTargetHelper::DropTargetListener::dragExit( const DropTargetEvent& ) throw( RuntimeException )
238 {
239 	const ::vos::OGuard aGuard( Application::GetSolarMutex() );
240 
241 	try
242 	{
243         if( mpLastDragOverEvent )
244         {
245             mpLastDragOverEvent->mbLeaving = sal_True;
246     		mrParent.AcceptDrop( *mpLastDragOverEvent );
247             delete mpLastDragOverEvent;
248             mpLastDragOverEvent = NULL;
249         }
250 
251 		mrParent.ImplEndDrag();
252 	}
253 	catch( const ::com::sun::star::uno::Exception& )
254 	{
255 	}
256 }
257 
258 
259 // -----------------------------------------------------------------------------
260 
261 void SAL_CALL DropTargetHelper::DropTargetListener::dropActionChanged( const DropTargetDragEvent& ) throw( RuntimeException )
262 {
263 }
264 
265 // --------------------
266 // - DropTargetHelper -
267 // --------------------
268 
269 DropTargetHelper::DropTargetHelper( Window* pWindow ) :
270 	mxDropTarget( pWindow->GetDropTarget() ),
271 	mpFormats( new DataFlavorExVector )
272 {
273 	ImplConstruct();
274 }
275 
276 // -----------------------------------------------------------------------------
277 
278 DropTargetHelper::DropTargetHelper( const Reference< XDropTarget >& rxDropTarget ) :
279 	mxDropTarget( rxDropTarget ),
280 	mpFormats( new DataFlavorExVector )
281 {
282 	ImplConstruct();
283 }
284 
285 // -----------------------------------------------------------------------------
286 
287 DropTargetHelper::~DropTargetHelper()
288 {
289 	if( mxDropTarget.is() )
290 		mxDropTarget->removeDropTargetListener( mxDropTargetListener );
291 
292 	delete mpFormats;
293 }
294 
295 // -----------------------------------------------------------------------------
296 
297 void DropTargetHelper::ImplConstruct()
298 {
299 	if( mxDropTarget.is() )
300 	{
301 		mxDropTargetListener = new DropTargetHelper::DropTargetListener( *this );
302 		mxDropTarget->addDropTargetListener( mxDropTargetListener );
303 		mxDropTarget->setActive( sal_True );
304 	}
305 }
306 
307 // -----------------------------------------------------------------------------
308 
309 void DropTargetHelper::ImplBeginDrag( const Sequence< DataFlavor >& rSupportedDataFlavors )
310 {
311 	mpFormats->clear();
312     TransferableDataHelper::FillDataFlavorExVector( rSupportedDataFlavors, *mpFormats );
313 }
314 
315 // -----------------------------------------------------------------------------
316 
317 void DropTargetHelper::ImplEndDrag()
318 {
319 	mpFormats->clear();
320 }
321 
322 // -----------------------------------------------------------------------------
323 
324 sal_Int8 DropTargetHelper::AcceptDrop( const AcceptDropEvent& )
325 {
326 	return( DNDConstants::ACTION_NONE );
327 }
328 
329 // -----------------------------------------------------------------------------
330 
331 sal_Int8 DropTargetHelper::ExecuteDrop( const ExecuteDropEvent& )
332 {
333 	return( DNDConstants::ACTION_NONE );
334 }
335 
336 // -----------------------------------------------------------------------------
337 
338 sal_Bool DropTargetHelper::IsDropFormatSupported( SotFormatStringId nFormat )
339 {
340 	DataFlavorExVector::iterator	aIter( mpFormats->begin() ), aEnd( mpFormats->end() );
341 	sal_Bool						bRet = sal_False;
342 
343 	while( aIter != aEnd )
344 	{
345 		if( nFormat == (*aIter++).mnSotId )
346 		{
347 			bRet = sal_True;
348 			aIter = aEnd;
349 		}
350 	}
351 
352 	return bRet;
353 }
354 
355 // -----------------------------------------------------------------------------
356 
357 sal_Bool DropTargetHelper::IsDropFormatSupported( const DataFlavor& rFlavor )
358 {
359 	DataFlavorExVector::iterator	aIter( mpFormats->begin() ), aEnd( mpFormats->end() );
360 	sal_Bool						bRet = sal_False;
361 
362 	while( aIter != aEnd )
363 	{
364 		if( TransferableDataHelper::IsEqual( rFlavor, *aIter++ ) )
365 		{
366 			bRet = sal_True;
367 			aIter = aEnd;
368 		}
369 	}
370 
371 	return bRet;
372 }
373 
374 // -----------------------------------------------------------------------------
375 // TransferDataContainer
376 // -----------------------------------------------------------------------------
377 
378 struct TDataCntnrEntry_Impl
379 {
380 	::com::sun::star::uno::Any aAny;
381 	SotFormatStringId nId;
382 };
383 
384 // -----------------------------------------------------------------------------
385 
386 typedef ::std::list< TDataCntnrEntry_Impl > TDataCntnrEntryList;
387 
388 // -----------------------------------------------------------------------------
389 
390 struct TransferDataContainer_Impl
391 {
392 	TDataCntnrEntryList aFmtList;
393 	Link aFinshedLnk;
394 	INetBookmark* pBookmk;
395 	Graphic* pGrf;
396 
397 	TransferDataContainer_Impl()
398 		: pBookmk( 0 ), pGrf( 0 )
399 	{
400 	}
401 
402 	~TransferDataContainer_Impl()
403 	{
404 		delete pBookmk;
405 		delete pGrf;
406 	}
407 };
408 
409 // -----------------------------------------------------------------------------
410 
411 TransferDataContainer::TransferDataContainer()
412 	: pImpl( new TransferDataContainer_Impl )
413 {
414 }
415 
416 // -----------------------------------------------------------------------------
417 
418 TransferDataContainer::~TransferDataContainer()
419 {
420 	delete pImpl;
421 }
422 
423 // -----------------------------------------------------------------------------
424 
425 void TransferDataContainer::AddSupportedFormats()
426 {
427 }
428 
429 // -----------------------------------------------------------------------------
430 
431 sal_Bool TransferDataContainer::GetData( const
432 			::com::sun::star::datatransfer::DataFlavor& rFlavor )
433 {
434 	TDataCntnrEntryList::iterator	aIter( pImpl->aFmtList.begin() ),
435 									aEnd( pImpl->aFmtList.end() );
436 	sal_Bool bFnd = sal_False;
437 	sal_uLong nFmtId = SotExchange::GetFormat( rFlavor );
438 
439 	// test first the list
440 	for( ; aIter != aEnd; ++aIter )
441 	{
442 		TDataCntnrEntry_Impl& rEntry = (TDataCntnrEntry_Impl&)*aIter;
443 		if( nFmtId == rEntry.nId )
444 		{
445 			bFnd = SetAny( rEntry.aAny, rFlavor );
446 			break;
447 		}
448 	}
449 
450 	// test second the bookmark pointer
451 	if( !bFnd )
452 		switch( nFmtId )
453 		{
454  		case SOT_FORMAT_STRING:
455  		case SOT_FORMATSTR_ID_SOLK:
456  		case SOT_FORMATSTR_ID_NETSCAPE_BOOKMARK:
457  		case SOT_FORMATSTR_ID_FILECONTENT:
458  		case SOT_FORMATSTR_ID_FILEGRPDESCRIPTOR:
459  		case SOT_FORMATSTR_ID_UNIFORMRESOURCELOCATOR:
460 			if( pImpl->pBookmk )
461 				bFnd = SetINetBookmark( *pImpl->pBookmk, rFlavor );
462 			break;
463 
464 		case SOT_FORMATSTR_ID_SVXB:
465 		case SOT_FORMAT_BITMAP:
466 		case SOT_FORMAT_GDIMETAFILE:
467 			if( pImpl->pGrf )
468 				bFnd = SetGraphic( *pImpl->pGrf, rFlavor );
469 			break;
470 		}
471 
472 	return bFnd;
473 }
474 
475 // -----------------------------------------------------------------------------
476 
477 void TransferDataContainer::ClearData()
478 {
479 	delete pImpl;
480 	pImpl = new TransferDataContainer_Impl;
481 	ClearFormats();
482 }
483 
484 // -----------------------------------------------------------------------------
485 
486 void TransferDataContainer::CopyINetBookmark( const INetBookmark& rBkmk )
487 {
488 	if( !pImpl->pBookmk )
489 		pImpl->pBookmk = new INetBookmark( rBkmk );
490 	else
491 		*pImpl->pBookmk = rBkmk;
492 
493  	AddFormat( SOT_FORMAT_STRING );
494  	AddFormat( SOT_FORMATSTR_ID_SOLK );
495  	AddFormat( SOT_FORMATSTR_ID_NETSCAPE_BOOKMARK );
496  	AddFormat( SOT_FORMATSTR_ID_FILECONTENT );
497  	AddFormat( SOT_FORMATSTR_ID_FILEGRPDESCRIPTOR );
498  	AddFormat( SOT_FORMATSTR_ID_UNIFORMRESOURCELOCATOR );
499 }
500 
501 // -----------------------------------------------------------------------------
502 
503 void TransferDataContainer::CopyAnyData( sal_uLong nFormatId,
504 										const sal_Char* pData, sal_uLong nLen )
505 {
506 	if( nLen )
507 	{
508 		TDataCntnrEntry_Impl aEntry;
509 		aEntry.nId = nFormatId;
510 
511 		Sequence< sal_Int8 > aSeq( nLen  );
512 		memcpy( aSeq.getArray(), pData, nLen );
513 		aEntry.aAny <<= aSeq;
514 		pImpl->aFmtList.push_back( aEntry );
515  		AddFormat( nFormatId );
516 	}
517 }
518 
519 // -----------------------------------------------------------------------------
520 
521 void TransferDataContainer::CopyByteString( sal_uLong nFormatId,
522 											const ByteString& rStr )
523 {
524 	CopyAnyData( nFormatId, rStr.GetBuffer(), rStr.Len() );
525 }
526 
527 // -----------------------------------------------------------------------------
528 
529 void TransferDataContainer::CopyINetImage( const INetImage& rINtImg )
530 {
531 	SvMemoryStream aMemStm( 1024, 1024 );
532     aMemStm.SetVersion( SOFFICE_FILEFORMAT_50 );
533 	rINtImg.Write( aMemStm, SOT_FORMATSTR_ID_INET_IMAGE );
534 	CopyAnyData( SOT_FORMATSTR_ID_INET_IMAGE, (sal_Char*)aMemStm.GetData(),
535 					aMemStm.Seek( STREAM_SEEK_TO_END ) );
536 }
537 
538 // -----------------------------------------------------------------------------
539 
540 void TransferDataContainer::CopyImageMap( const ImageMap& rImgMap )
541 {
542 	SvMemoryStream aMemStm( 8192, 8192 );
543     aMemStm.SetVersion( SOFFICE_FILEFORMAT_50 );
544     rImgMap.Write( aMemStm, String() );
545 	CopyAnyData( SOT_FORMATSTR_ID_SVIM, (sal_Char*)aMemStm.GetData(),
546 					aMemStm.Seek( STREAM_SEEK_TO_END ) );
547 }
548 
549 // -----------------------------------------------------------------------------
550 
551 void TransferDataContainer::CopyGraphic( const Graphic& rGrf )
552 {
553 	GraphicType nType = rGrf.GetType();
554 	if( GRAPHIC_NONE != nType )
555 	{
556 		if( !pImpl->pGrf )
557 			pImpl->pGrf = new Graphic( rGrf );
558 		else
559 			*pImpl->pGrf = rGrf;
560 
561 		AddFormat( SOT_FORMATSTR_ID_SVXB );
562 		if( GRAPHIC_BITMAP == nType )
563 			AddFormat( SOT_FORMAT_BITMAP );
564 		else if( GRAPHIC_GDIMETAFILE == nType )
565 			AddFormat( SOT_FORMAT_GDIMETAFILE );
566 	}
567 }
568 
569 // -----------------------------------------------------------------------------
570 
571 void TransferDataContainer::CopyString( sal_uInt16 nFmt, const String& rStr )
572 {
573 	if( rStr.Len() )
574 	{
575 		TDataCntnrEntry_Impl aEntry;
576 		aEntry.nId = nFmt;
577 		rtl::OUString aStr( rStr );
578 		aEntry.aAny <<= aStr;
579 		pImpl->aFmtList.push_back( aEntry );
580  		AddFormat( aEntry.nId );
581 	}
582 }
583 
584 // -----------------------------------------------------------------------------
585 
586 void TransferDataContainer::CopyString( const String& rStr )
587 {
588 	CopyString( SOT_FORMAT_STRING, rStr );
589 }
590 
591 // -----------------------------------------------------------------------------
592 
593 void TransferDataContainer::CopyAny( sal_uInt16 nFmt,
594 									const ::com::sun::star::uno::Any& rAny )
595 {
596 	TDataCntnrEntry_Impl aEntry;
597 	aEntry.nId = nFmt;
598 	aEntry.aAny = rAny;
599 	pImpl->aFmtList.push_back( aEntry );
600 	AddFormat( aEntry.nId );
601 }
602 
603 // -----------------------------------------------------------------------------
604 
605 sal_Bool TransferDataContainer::HasAnyData() const
606 {
607 	return pImpl->aFmtList.begin() != pImpl->aFmtList.end() ||
608 			0 != pImpl->pBookmk;
609 }
610 
611 // -----------------------------------------------------------------------------
612 
613 void TransferDataContainer::StartDrag(
614 		Window* pWindow, sal_Int8 nDragSourceActions,
615 		const Link& rLnk, sal_Int32 nDragPointer, sal_Int32 nDragImage )
616 {
617 	pImpl->aFinshedLnk = rLnk;
618 	TransferableHelper::StartDrag( pWindow, nDragSourceActions,
619 									nDragPointer, nDragImage );
620 }
621 
622 // -----------------------------------------------------------------------------
623 
624 void TransferDataContainer::DragFinished( sal_Int8 nDropAction )
625 {
626 	if( pImpl->aFinshedLnk.IsSet() )
627 		pImpl->aFinshedLnk.Call( &nDropAction );
628 }
629