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