1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <osl/mutex.hxx>
21 #include <unotools/ucbstreamhelper.hxx>
22 #include <sot/exchange.hxx>
23 #include <sot/storage.hxx>
24 #include <vcl/bitmap.hxx>
25 #include <vcl/gdimtf.hxx>
26 #include <vcl/graph.hxx>
27 #include <vcl/svapp.hxx>
28 #include <vcl/window.hxx>
29 #include <comphelper/processfactory.hxx>
30 #include <com/sun/star/datatransfer/dnd/XDropTargetDragContext.hpp>
31 #include <svl/urlbmk.hxx>
32 #include <svtools/inetimg.hxx>
33 #include <svtools/imap.hxx>
34 #include <svtools/transfer.hxx>
40 using namespace ::com::sun::star::uno
;
41 using namespace ::com::sun::star::lang
;
42 using namespace ::com::sun::star::io
;
43 using namespace ::com::sun::star::datatransfer
;
44 using namespace ::com::sun::star::datatransfer::clipboard
;
45 using namespace ::com::sun::star::datatransfer::dnd
;
48 // - DragSourceHelper::DragGestureListener -
51 DragSourceHelper::DragGestureListener::DragGestureListener( DragSourceHelper
& rDragSourceHelper
) :
52 mrParent( rDragSourceHelper
)
58 DragSourceHelper::DragGestureListener::~DragGestureListener()
64 void SAL_CALL
DragSourceHelper::DragGestureListener::disposing( const EventObject
& ) throw( RuntimeException
, std::exception
)
70 void SAL_CALL
DragSourceHelper::DragGestureListener::dragGestureRecognized( const DragGestureEvent
& rDGE
) throw( RuntimeException
, std::exception
)
72 const SolarMutexGuard aGuard
;
74 const Point
aPtPixel( rDGE
.DragOriginX
, rDGE
.DragOriginY
);
75 mrParent
.StartDrag( rDGE
.DragAction
, aPtPixel
);
79 // - DragSourceHelper -
82 DragSourceHelper::DragSourceHelper( vcl::Window
* pWindow
) :
83 mxDragGestureRecognizer( pWindow
->GetDragGestureRecognizer() )
85 if( mxDragGestureRecognizer
.is() )
87 mxDragGestureListener
= new DragSourceHelper::DragGestureListener( *this );
88 mxDragGestureRecognizer
->addDragGestureListener( mxDragGestureListener
);
94 DragSourceHelper::~DragSourceHelper()
96 if( mxDragGestureRecognizer
.is() )
97 mxDragGestureRecognizer
->removeDragGestureListener( mxDragGestureListener
);
102 void DragSourceHelper::StartDrag( sal_Int8
, const Point
& )
107 // - DropTargetHelper::DropTargetListener -
110 DropTargetHelper::DropTargetListener::DropTargetListener( DropTargetHelper
& rDropTargetHelper
) :
111 mrParent( rDropTargetHelper
),
112 mpLastDragOverEvent( NULL
)
118 DropTargetHelper::DropTargetListener::~DropTargetListener()
120 delete mpLastDragOverEvent
;
125 void SAL_CALL
DropTargetHelper::DropTargetListener::disposing( const EventObject
& ) throw( RuntimeException
, std::exception
)
131 void SAL_CALL
DropTargetHelper::DropTargetListener::drop( const DropTargetDropEvent
& rDTDE
) throw( RuntimeException
, std::exception
)
133 const SolarMutexGuard aGuard
;
137 AcceptDropEvent aAcceptEvent
;
138 ExecuteDropEvent
aExecuteEvt( rDTDE
.DropAction
& ~DNDConstants::ACTION_DEFAULT
, Point( rDTDE
.LocationX
, rDTDE
.LocationY
), rDTDE
);
140 aExecuteEvt
.mbDefault
= ( ( rDTDE
.DropAction
& DNDConstants::ACTION_DEFAULT
) != 0 );
142 // in case of a default action, call ::AcceptDrop first and use the returned
143 // accepted action as the execute action in the call to ::ExecuteDrop
144 aAcceptEvent
.mnAction
= aExecuteEvt
.mnAction
;
145 aAcceptEvent
.maPosPixel
= aExecuteEvt
.maPosPixel
;
146 (DropTargetEvent
&)( aAcceptEvent
.maDragEvent
) = (DropTargetEvent
&) rDTDE
;
147 ( (DropTargetDragEvent
&)( aAcceptEvent
.maDragEvent
) ).DropAction
= rDTDE
.DropAction
;
148 ( (DropTargetDragEvent
&)( aAcceptEvent
.maDragEvent
) ).LocationX
= rDTDE
.LocationX
;
149 ( (DropTargetDragEvent
&)( aAcceptEvent
.maDragEvent
) ).LocationY
= rDTDE
.LocationY
;
150 ( (DropTargetDragEvent
&)( aAcceptEvent
.maDragEvent
) ).SourceActions
= rDTDE
.SourceActions
;
151 aAcceptEvent
.mbLeaving
= false;
152 aAcceptEvent
.mbDefault
= aExecuteEvt
.mbDefault
;
154 sal_Int8 nRet
= mrParent
.AcceptDrop( aAcceptEvent
);
156 if( DNDConstants::ACTION_NONE
!= nRet
)
158 rDTDE
.Context
->acceptDrop( nRet
);
160 if( aExecuteEvt
.mbDefault
)
161 aExecuteEvt
.mnAction
= nRet
;
163 nRet
= mrParent
.ExecuteDrop( aExecuteEvt
);
166 rDTDE
.Context
->dropComplete( DNDConstants::ACTION_NONE
!= nRet
);
168 if( mpLastDragOverEvent
)
170 delete mpLastDragOverEvent
;
171 mpLastDragOverEvent
= NULL
;
174 catch( const ::com::sun::star::uno::Exception
& )
181 void SAL_CALL
DropTargetHelper::DropTargetListener::dragEnter( const DropTargetDragEnterEvent
& rDTDEE
) throw( RuntimeException
, std::exception
)
183 const SolarMutexGuard aGuard
;
187 mrParent
.ImplBeginDrag( rDTDEE
.SupportedDataFlavors
);
189 catch( const ::com::sun::star::uno::Exception
& )
198 void SAL_CALL
DropTargetHelper::DropTargetListener::dragOver( const DropTargetDragEvent
& rDTDE
) throw( RuntimeException
, std::exception
)
200 const SolarMutexGuard aGuard
;
204 if( mpLastDragOverEvent
)
205 delete mpLastDragOverEvent
;
207 mpLastDragOverEvent
= new AcceptDropEvent( rDTDE
.DropAction
& ~DNDConstants::ACTION_DEFAULT
, Point( rDTDE
.LocationX
, rDTDE
.LocationY
), rDTDE
);
208 mpLastDragOverEvent
->mbDefault
= ( ( rDTDE
.DropAction
& DNDConstants::ACTION_DEFAULT
) != 0 );
210 const sal_Int8 nRet
= mrParent
.AcceptDrop( *mpLastDragOverEvent
);
212 if( DNDConstants::ACTION_NONE
== nRet
)
213 rDTDE
.Context
->rejectDrag();
215 rDTDE
.Context
->acceptDrag( nRet
);
217 catch( const ::com::sun::star::uno::Exception
& )
224 void SAL_CALL
DropTargetHelper::DropTargetListener::dragExit( const DropTargetEvent
& ) throw( RuntimeException
, std::exception
)
226 const SolarMutexGuard aGuard
;
230 if( mpLastDragOverEvent
)
232 mpLastDragOverEvent
->mbLeaving
= true;
233 mrParent
.AcceptDrop( *mpLastDragOverEvent
);
234 delete mpLastDragOverEvent
;
235 mpLastDragOverEvent
= NULL
;
238 mrParent
.ImplEndDrag();
240 catch( const ::com::sun::star::uno::Exception
& )
248 void SAL_CALL
DropTargetHelper::DropTargetListener::dropActionChanged( const DropTargetDragEvent
& ) throw( RuntimeException
, std::exception
)
253 // - DropTargetHelper -
256 DropTargetHelper::DropTargetHelper( vcl::Window
* pWindow
) :
257 mxDropTarget( pWindow
->GetDropTarget() ),
258 mpFormats( new DataFlavorExVector
)
265 DropTargetHelper::DropTargetHelper( const Reference
< XDropTarget
>& rxDropTarget
) :
266 mxDropTarget( rxDropTarget
),
267 mpFormats( new DataFlavorExVector
)
274 DropTargetHelper::~DropTargetHelper()
276 if( mxDropTarget
.is() )
277 mxDropTarget
->removeDropTargetListener( mxDropTargetListener
);
284 void DropTargetHelper::ImplConstruct()
286 if( mxDropTarget
.is() )
288 mxDropTargetListener
= new DropTargetHelper::DropTargetListener( *this );
289 mxDropTarget
->addDropTargetListener( mxDropTargetListener
);
290 mxDropTarget
->setActive( sal_True
);
296 void DropTargetHelper::ImplBeginDrag( const Sequence
< DataFlavor
>& rSupportedDataFlavors
)
299 TransferableDataHelper::FillDataFlavorExVector( rSupportedDataFlavors
, *mpFormats
);
304 void DropTargetHelper::ImplEndDrag()
311 sal_Int8
DropTargetHelper::AcceptDrop( const AcceptDropEvent
& )
313 return( DNDConstants::ACTION_NONE
);
318 sal_Int8
DropTargetHelper::ExecuteDrop( const ExecuteDropEvent
& )
320 return( DNDConstants::ACTION_NONE
);
325 bool DropTargetHelper::IsDropFormatSupported( SotClipboardFormatId nFormat
)
327 DataFlavorExVector::iterator
aIter( mpFormats
->begin() ), aEnd( mpFormats
->end() );
330 while( aIter
!= aEnd
)
332 if( nFormat
== (*aIter
++).mnSotId
)
344 bool DropTargetHelper::IsDropFormatSupported( const DataFlavor
& rFlavor
)
346 DataFlavorExVector::iterator
aIter( mpFormats
->begin() ), aEnd( mpFormats
->end() );
349 while( aIter
!= aEnd
)
351 if( TransferableDataHelper::IsEqual( rFlavor
, *aIter
++ ) )
362 // TransferDataContainer
365 struct TDataCntnrEntry_Impl
367 ::com::sun::star::uno::Any aAny
;
368 SotClipboardFormatId nId
;
373 typedef ::std::list
< TDataCntnrEntry_Impl
> TDataCntnrEntryList
;
377 struct TransferDataContainer_Impl
379 TDataCntnrEntryList aFmtList
;
381 INetBookmark
* pBookmk
;
384 TransferDataContainer_Impl()
385 : pBookmk( 0 ), pGrf( 0 )
389 ~TransferDataContainer_Impl()
398 TransferDataContainer::TransferDataContainer()
399 : pImpl( new TransferDataContainer_Impl
)
405 TransferDataContainer::~TransferDataContainer()
412 void TransferDataContainer::AddSupportedFormats()
418 bool TransferDataContainer::GetData(
419 const css::datatransfer::DataFlavor
& rFlavor
, const OUString
& /*rDestDoc*/ )
421 TDataCntnrEntryList::iterator
aIter( pImpl
->aFmtList
.begin() ),
422 aEnd( pImpl
->aFmtList
.end() );
424 SotClipboardFormatId nFmtId
= SotExchange::GetFormat( rFlavor
);
426 // test first the list
427 for( ; aIter
!= aEnd
; ++aIter
)
429 TDataCntnrEntry_Impl
& rEntry
= (TDataCntnrEntry_Impl
&)*aIter
;
430 if( nFmtId
== rEntry
.nId
)
432 bFnd
= SetAny( rEntry
.aAny
, rFlavor
);
437 // test second the bookmark pointer
441 case SotClipboardFormatId::STRING
:
442 case SotClipboardFormatId::SOLK
:
443 case SotClipboardFormatId::NETSCAPE_BOOKMARK
:
444 case SotClipboardFormatId::FILECONTENT
:
445 case SotClipboardFormatId::FILEGRPDESCRIPTOR
:
446 case SotClipboardFormatId::UNIFORMRESOURCELOCATOR
:
448 bFnd
= SetINetBookmark( *pImpl
->pBookmk
, rFlavor
);
451 case SotClipboardFormatId::SVXB
:
452 case SotClipboardFormatId::PNG
:
453 case SotClipboardFormatId::BITMAP
:
454 case SotClipboardFormatId::GDIMETAFILE
:
456 bFnd
= SetGraphic( *pImpl
->pGrf
, rFlavor
);
466 void TransferDataContainer::CopyINetBookmark( const INetBookmark
& rBkmk
)
468 if( !pImpl
->pBookmk
)
469 pImpl
->pBookmk
= new INetBookmark( rBkmk
);
471 *pImpl
->pBookmk
= rBkmk
;
473 AddFormat( SotClipboardFormatId::STRING
);
474 AddFormat( SotClipboardFormatId::SOLK
);
475 AddFormat( SotClipboardFormatId::NETSCAPE_BOOKMARK
);
476 AddFormat( SotClipboardFormatId::FILECONTENT
);
477 AddFormat( SotClipboardFormatId::FILEGRPDESCRIPTOR
);
478 AddFormat( SotClipboardFormatId::UNIFORMRESOURCELOCATOR
);
483 void TransferDataContainer::CopyAnyData( SotClipboardFormatId nFormatId
,
484 const sal_Char
* pData
, sal_uLong nLen
)
488 TDataCntnrEntry_Impl aEntry
;
489 aEntry
.nId
= nFormatId
;
491 Sequence
< sal_Int8
> aSeq( nLen
);
492 memcpy( aSeq
.getArray(), pData
, nLen
);
493 aEntry
.aAny
<<= aSeq
;
494 pImpl
->aFmtList
.push_back( aEntry
);
495 AddFormat( nFormatId
);
501 void TransferDataContainer::CopyByteString( SotClipboardFormatId nFormatId
,
502 const OString
& rStr
)
504 CopyAnyData( nFormatId
, rStr
.getStr(), rStr
.getLength() );
509 void TransferDataContainer::CopyINetImage( const INetImage
& rINtImg
)
511 SvMemoryStream
aMemStm( 1024, 1024 );
512 aMemStm
.SetVersion( SOFFICE_FILEFORMAT_50
);
513 rINtImg
.Write( aMemStm
, SotClipboardFormatId::INET_IMAGE
);
514 CopyAnyData( SotClipboardFormatId::INET_IMAGE
, static_cast<sal_Char
const *>(aMemStm
.GetData()),
515 aMemStm
.Seek( STREAM_SEEK_TO_END
) );
520 void TransferDataContainer::CopyImageMap( const ImageMap
& rImgMap
)
522 SvMemoryStream
aMemStm( 8192, 8192 );
523 aMemStm
.SetVersion( SOFFICE_FILEFORMAT_50
);
524 rImgMap
.Write( aMemStm
, OUString() );
525 CopyAnyData( SotClipboardFormatId::SVIM
, static_cast<sal_Char
const *>(aMemStm
.GetData()),
526 aMemStm
.Seek( STREAM_SEEK_TO_END
) );
531 void TransferDataContainer::CopyGraphic( const Graphic
& rGrf
)
533 GraphicType nType
= rGrf
.GetType();
534 if( GRAPHIC_NONE
!= nType
)
537 pImpl
->pGrf
= new Graphic( rGrf
);
541 AddFormat( SotClipboardFormatId::SVXB
);
543 if( GRAPHIC_BITMAP
== nType
)
545 AddFormat( SotClipboardFormatId::PNG
);
546 AddFormat( SotClipboardFormatId::BITMAP
);
548 else if( GRAPHIC_GDIMETAFILE
== nType
)
550 AddFormat( SotClipboardFormatId::GDIMETAFILE
);
557 void TransferDataContainer::CopyString( SotClipboardFormatId nFmt
, const OUString
& rStr
)
559 if( !rStr
.isEmpty() )
561 TDataCntnrEntry_Impl aEntry
;
563 OUString
aStr( rStr
);
564 aEntry
.aAny
<<= aStr
;
565 pImpl
->aFmtList
.push_back( aEntry
);
566 AddFormat( aEntry
.nId
);
572 void TransferDataContainer::CopyString( const OUString
& rStr
)
574 CopyString( SotClipboardFormatId::STRING
, rStr
);
579 void TransferDataContainer::CopyAny( SotClipboardFormatId nFmt
,
580 const ::com::sun::star::uno::Any
& rAny
)
582 TDataCntnrEntry_Impl aEntry
;
585 pImpl
->aFmtList
.push_back( aEntry
);
586 AddFormat( aEntry
.nId
);
591 bool TransferDataContainer::HasAnyData() const
593 return pImpl
->aFmtList
.begin() != pImpl
->aFmtList
.end() ||
599 void TransferDataContainer::StartDrag(
600 vcl::Window
* pWindow
, sal_Int8 nDragSourceActions
,
601 const Link
<>& rLnk
, sal_Int32 nDragPointer
, sal_Int32 nDragImage
)
603 pImpl
->aFinshedLnk
= rLnk
;
604 TransferableHelper::StartDrag( pWindow
, nDragSourceActions
,
605 nDragPointer
, nDragImage
);
610 void TransferDataContainer::DragFinished( sal_Int8 nDropAction
)
612 if( pImpl
->aFinshedLnk
.IsSet() )
613 pImpl
->aFinshedLnk
.Call( &nDropAction
);
616 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */