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
;
47 // -----------------------------------------
48 // - DragSourceHelper::DragGestureListener -
49 // -----------------------------------------
51 DragSourceHelper::DragGestureListener::DragGestureListener( DragSourceHelper
& rDragSourceHelper
) :
52 mrParent( rDragSourceHelper
)
56 // -----------------------------------------------------------------------------
58 DragSourceHelper::DragGestureListener::~DragGestureListener()
62 // -----------------------------------------------------------------------------
64 void SAL_CALL
DragSourceHelper::DragGestureListener::disposing( const EventObject
& ) throw( RuntimeException
)
68 // -----------------------------------------------------------------------------
70 void SAL_CALL
DragSourceHelper::DragGestureListener::dragGestureRecognized( const DragGestureEvent
& rDGE
) throw( RuntimeException
)
72 const SolarMutexGuard aGuard
;
74 const Point
aPtPixel( rDGE
.DragOriginX
, rDGE
.DragOriginY
);
75 mrParent
.StartDrag( rDGE
.DragAction
, aPtPixel
);
78 // --------------------
79 // - DragSourceHelper -
80 // --------------------
82 DragSourceHelper::DragSourceHelper( Window
* pWindow
) :
83 mxDragGestureRecognizer( pWindow
->GetDragGestureRecognizer() )
85 if( mxDragGestureRecognizer
.is() )
87 mxDragGestureListener
= new DragSourceHelper::DragGestureListener( *this );
88 mxDragGestureRecognizer
->addDragGestureListener( mxDragGestureListener
);
92 // -----------------------------------------------------------------------------
94 DragSourceHelper::~DragSourceHelper()
96 if( mxDragGestureRecognizer
.is() )
97 mxDragGestureRecognizer
->removeDragGestureListener( mxDragGestureListener
);
100 // -----------------------------------------------------------------------------
102 void DragSourceHelper::StartDrag( sal_Int8
, const Point
& )
106 // ----------------------------------------
107 // - DropTargetHelper::DropTargetListener -
108 // ----------------------------------------
110 DropTargetHelper::DropTargetListener::DropTargetListener( DropTargetHelper
& rDropTargetHelper
) :
111 mrParent( rDropTargetHelper
),
112 mpLastDragOverEvent( NULL
)
116 // -----------------------------------------------------------------------------
118 DropTargetHelper::DropTargetListener::~DropTargetListener()
120 delete mpLastDragOverEvent
;
123 // -----------------------------------------------------------------------------
125 void SAL_CALL
DropTargetHelper::DropTargetListener::disposing( const EventObject
& ) throw( RuntimeException
)
129 // -----------------------------------------------------------------------------
131 void SAL_CALL
DropTargetHelper::DropTargetListener::drop( const DropTargetDropEvent
& rDTDE
) throw( RuntimeException
)
133 const SolarMutexGuard aGuard
;
137 AcceptDropEvent aAcceptEvent
;
138 ExecuteDropEvent
aExecuteEvt( rDTDE
.DropAction
& ~DNDConstants::ACTION_DEFAULT
, Point( rDTDE
.LocationX
, rDTDE
.LocationY
), rDTDE
);
139 sal_Int8 nRet
= DNDConstants::ACTION_NONE
;
141 aExecuteEvt
.mbDefault
= ( ( rDTDE
.DropAction
& DNDConstants::ACTION_DEFAULT
) != 0 );
143 // in case of a default action, call ::AcceptDrop first and use the returned
144 // accepted action as the execute action in the call to ::ExecuteDrop
145 aAcceptEvent
.mnAction
= aExecuteEvt
.mnAction
;
146 aAcceptEvent
.maPosPixel
= aExecuteEvt
.maPosPixel
;
147 (DropTargetEvent
&)( aAcceptEvent
.maDragEvent
) = (DropTargetEvent
&) rDTDE
;
148 ( (DropTargetDragEvent
&)( aAcceptEvent
.maDragEvent
) ).DropAction
= rDTDE
.DropAction
;
149 ( (DropTargetDragEvent
&)( aAcceptEvent
.maDragEvent
) ).LocationX
= rDTDE
.LocationX
;
150 ( (DropTargetDragEvent
&)( aAcceptEvent
.maDragEvent
) ).LocationY
= rDTDE
.LocationY
;
151 ( (DropTargetDragEvent
&)( aAcceptEvent
.maDragEvent
) ).SourceActions
= rDTDE
.SourceActions
;
152 aAcceptEvent
.mbLeaving
= sal_False
;
153 aAcceptEvent
.mbDefault
= aExecuteEvt
.mbDefault
;
155 nRet
= mrParent
.AcceptDrop( aAcceptEvent
);
157 if( DNDConstants::ACTION_NONE
!= nRet
)
159 rDTDE
.Context
->acceptDrop( nRet
);
161 if( aExecuteEvt
.mbDefault
)
162 aExecuteEvt
.mnAction
= nRet
;
164 nRet
= mrParent
.ExecuteDrop( aExecuteEvt
);
167 rDTDE
.Context
->dropComplete( DNDConstants::ACTION_NONE
!= nRet
);
169 if( mpLastDragOverEvent
)
171 delete mpLastDragOverEvent
;
172 mpLastDragOverEvent
= NULL
;
175 catch( const ::com::sun::star::uno::Exception
& )
180 // -----------------------------------------------------------------------------
182 void SAL_CALL
DropTargetHelper::DropTargetListener::dragEnter( const DropTargetDragEnterEvent
& rDTDEE
) throw( RuntimeException
)
184 const SolarMutexGuard aGuard
;
188 mrParent
.ImplBeginDrag( rDTDEE
.SupportedDataFlavors
);
190 catch( const ::com::sun::star::uno::Exception
& )
197 // -----------------------------------------------------------------------------
199 void SAL_CALL
DropTargetHelper::DropTargetListener::dragOver( const DropTargetDragEvent
& rDTDE
) throw( RuntimeException
)
201 const SolarMutexGuard aGuard
;
205 if( mpLastDragOverEvent
)
206 delete mpLastDragOverEvent
;
208 mpLastDragOverEvent
= new AcceptDropEvent( rDTDE
.DropAction
& ~DNDConstants::ACTION_DEFAULT
, Point( rDTDE
.LocationX
, rDTDE
.LocationY
), rDTDE
);
209 mpLastDragOverEvent
->mbDefault
= ( ( rDTDE
.DropAction
& DNDConstants::ACTION_DEFAULT
) != 0 );
211 const sal_Int8 nRet
= mrParent
.AcceptDrop( *mpLastDragOverEvent
);
213 if( DNDConstants::ACTION_NONE
== nRet
)
214 rDTDE
.Context
->rejectDrag();
216 rDTDE
.Context
->acceptDrag( nRet
);
218 catch( const ::com::sun::star::uno::Exception
& )
223 // -----------------------------------------------------------------------------
225 void SAL_CALL
DropTargetHelper::DropTargetListener::dragExit( const DropTargetEvent
& ) throw( RuntimeException
)
227 const SolarMutexGuard aGuard
;
231 if( mpLastDragOverEvent
)
233 mpLastDragOverEvent
->mbLeaving
= sal_True
;
234 mrParent
.AcceptDrop( *mpLastDragOverEvent
);
235 delete mpLastDragOverEvent
;
236 mpLastDragOverEvent
= NULL
;
239 mrParent
.ImplEndDrag();
241 catch( const ::com::sun::star::uno::Exception
& )
247 // -----------------------------------------------------------------------------
249 void SAL_CALL
DropTargetHelper::DropTargetListener::dropActionChanged( const DropTargetDragEvent
& ) throw( RuntimeException
)
253 // --------------------
254 // - DropTargetHelper -
255 // --------------------
257 DropTargetHelper::DropTargetHelper( Window
* pWindow
) :
258 mxDropTarget( pWindow
->GetDropTarget() ),
259 mpFormats( new DataFlavorExVector
)
264 // -----------------------------------------------------------------------------
266 DropTargetHelper::DropTargetHelper( const Reference
< XDropTarget
>& rxDropTarget
) :
267 mxDropTarget( rxDropTarget
),
268 mpFormats( new DataFlavorExVector
)
273 // -----------------------------------------------------------------------------
275 DropTargetHelper::~DropTargetHelper()
277 if( mxDropTarget
.is() )
278 mxDropTarget
->removeDropTargetListener( mxDropTargetListener
);
283 // -----------------------------------------------------------------------------
285 void DropTargetHelper::ImplConstruct()
287 if( mxDropTarget
.is() )
289 mxDropTargetListener
= new DropTargetHelper::DropTargetListener( *this );
290 mxDropTarget
->addDropTargetListener( mxDropTargetListener
);
291 mxDropTarget
->setActive( sal_True
);
295 // -----------------------------------------------------------------------------
297 void DropTargetHelper::ImplBeginDrag( const Sequence
< DataFlavor
>& rSupportedDataFlavors
)
300 TransferableDataHelper::FillDataFlavorExVector( rSupportedDataFlavors
, *mpFormats
);
303 // -----------------------------------------------------------------------------
305 void DropTargetHelper::ImplEndDrag()
310 // -----------------------------------------------------------------------------
312 sal_Int8
DropTargetHelper::AcceptDrop( const AcceptDropEvent
& )
314 return( DNDConstants::ACTION_NONE
);
317 // -----------------------------------------------------------------------------
319 sal_Int8
DropTargetHelper::ExecuteDrop( const ExecuteDropEvent
& )
321 return( DNDConstants::ACTION_NONE
);
324 // -----------------------------------------------------------------------------
326 sal_Bool
DropTargetHelper::IsDropFormatSupported( SotFormatStringId nFormat
)
328 DataFlavorExVector::iterator
aIter( mpFormats
->begin() ), aEnd( mpFormats
->end() );
329 sal_Bool bRet
= sal_False
;
331 while( aIter
!= aEnd
)
333 if( nFormat
== (*aIter
++).mnSotId
)
343 // -----------------------------------------------------------------------------
345 sal_Bool
DropTargetHelper::IsDropFormatSupported( const DataFlavor
& rFlavor
)
347 DataFlavorExVector::iterator
aIter( mpFormats
->begin() ), aEnd( mpFormats
->end() );
348 sal_Bool bRet
= sal_False
;
350 while( aIter
!= aEnd
)
352 if( TransferableDataHelper::IsEqual( rFlavor
, *aIter
++ ) )
362 // -----------------------------------------------------------------------------
363 // TransferDataContainer
364 // -----------------------------------------------------------------------------
366 struct TDataCntnrEntry_Impl
368 ::com::sun::star::uno::Any aAny
;
369 SotFormatStringId nId
;
372 // -----------------------------------------------------------------------------
374 typedef ::std::list
< TDataCntnrEntry_Impl
> TDataCntnrEntryList
;
376 // -----------------------------------------------------------------------------
378 struct TransferDataContainer_Impl
380 TDataCntnrEntryList aFmtList
;
382 INetBookmark
* pBookmk
;
385 TransferDataContainer_Impl()
386 : pBookmk( 0 ), pGrf( 0 )
390 ~TransferDataContainer_Impl()
397 // -----------------------------------------------------------------------------
399 TransferDataContainer::TransferDataContainer()
400 : pImpl( new TransferDataContainer_Impl
)
404 // -----------------------------------------------------------------------------
406 TransferDataContainer::~TransferDataContainer()
411 // -----------------------------------------------------------------------------
413 void TransferDataContainer::AddSupportedFormats()
417 // -----------------------------------------------------------------------------
419 sal_Bool
TransferDataContainer::GetData( const
420 ::com::sun::star::datatransfer::DataFlavor
& rFlavor
)
422 TDataCntnrEntryList::iterator
aIter( pImpl
->aFmtList
.begin() ),
423 aEnd( pImpl
->aFmtList
.end() );
424 sal_Bool bFnd
= sal_False
;
425 sal_uLong nFmtId
= SotExchange::GetFormat( rFlavor
);
427 // test first the list
428 for( ; aIter
!= aEnd
; ++aIter
)
430 TDataCntnrEntry_Impl
& rEntry
= (TDataCntnrEntry_Impl
&)*aIter
;
431 if( nFmtId
== rEntry
.nId
)
433 bFnd
= SetAny( rEntry
.aAny
, rFlavor
);
438 // test second the bookmark pointer
442 case SOT_FORMAT_STRING
:
443 case SOT_FORMATSTR_ID_SOLK
:
444 case SOT_FORMATSTR_ID_NETSCAPE_BOOKMARK
:
445 case SOT_FORMATSTR_ID_FILECONTENT
:
446 case SOT_FORMATSTR_ID_FILEGRPDESCRIPTOR
:
447 case SOT_FORMATSTR_ID_UNIFORMRESOURCELOCATOR
:
449 bFnd
= SetINetBookmark( *pImpl
->pBookmk
, rFlavor
);
452 case SOT_FORMATSTR_ID_SVXB
:
453 case SOT_FORMAT_BITMAP
:
454 case SOT_FORMAT_GDIMETAFILE
:
456 bFnd
= SetGraphic( *pImpl
->pGrf
, rFlavor
);
463 // -----------------------------------------------------------------------------
465 void TransferDataContainer::CopyINetBookmark( const INetBookmark
& rBkmk
)
467 if( !pImpl
->pBookmk
)
468 pImpl
->pBookmk
= new INetBookmark( rBkmk
);
470 *pImpl
->pBookmk
= rBkmk
;
472 AddFormat( SOT_FORMAT_STRING
);
473 AddFormat( SOT_FORMATSTR_ID_SOLK
);
474 AddFormat( SOT_FORMATSTR_ID_NETSCAPE_BOOKMARK
);
475 AddFormat( SOT_FORMATSTR_ID_FILECONTENT
);
476 AddFormat( SOT_FORMATSTR_ID_FILEGRPDESCRIPTOR
);
477 AddFormat( SOT_FORMATSTR_ID_UNIFORMRESOURCELOCATOR
);
480 // -----------------------------------------------------------------------------
482 void TransferDataContainer::CopyAnyData( sal_uLong nFormatId
,
483 const sal_Char
* pData
, sal_uLong nLen
)
487 TDataCntnrEntry_Impl aEntry
;
488 aEntry
.nId
= nFormatId
;
490 Sequence
< sal_Int8
> aSeq( nLen
);
491 memcpy( aSeq
.getArray(), pData
, nLen
);
492 aEntry
.aAny
<<= aSeq
;
493 pImpl
->aFmtList
.push_back( aEntry
);
494 AddFormat( nFormatId
);
498 // -----------------------------------------------------------------------------
500 void TransferDataContainer::CopyByteString( sal_uLong nFormatId
,
501 const OString
& rStr
)
503 CopyAnyData( nFormatId
, rStr
.getStr(), rStr
.getLength() );
506 // -----------------------------------------------------------------------------
508 void TransferDataContainer::CopyINetImage( const INetImage
& rINtImg
)
510 SvMemoryStream
aMemStm( 1024, 1024 );
511 aMemStm
.SetVersion( SOFFICE_FILEFORMAT_50
);
512 rINtImg
.Write( aMemStm
, SOT_FORMATSTR_ID_INET_IMAGE
);
513 CopyAnyData( SOT_FORMATSTR_ID_INET_IMAGE
, (sal_Char
*)aMemStm
.GetData(),
514 aMemStm
.Seek( STREAM_SEEK_TO_END
) );
517 // -----------------------------------------------------------------------------
519 void TransferDataContainer::CopyImageMap( const ImageMap
& rImgMap
)
521 SvMemoryStream
aMemStm( 8192, 8192 );
522 aMemStm
.SetVersion( SOFFICE_FILEFORMAT_50
);
523 rImgMap
.Write( aMemStm
, String() );
524 CopyAnyData( SOT_FORMATSTR_ID_SVIM
, (sal_Char
*)aMemStm
.GetData(),
525 aMemStm
.Seek( STREAM_SEEK_TO_END
) );
528 // -----------------------------------------------------------------------------
530 void TransferDataContainer::CopyGraphic( const Graphic
& rGrf
)
532 GraphicType nType
= rGrf
.GetType();
533 if( GRAPHIC_NONE
!= nType
)
536 pImpl
->pGrf
= new Graphic( rGrf
);
540 AddFormat( SOT_FORMATSTR_ID_SVXB
);
541 if( GRAPHIC_BITMAP
== nType
)
542 AddFormat( SOT_FORMAT_BITMAP
);
543 else if( GRAPHIC_GDIMETAFILE
== nType
)
544 AddFormat( SOT_FORMAT_GDIMETAFILE
);
548 // -----------------------------------------------------------------------------
550 void TransferDataContainer::CopyString( sal_uInt16 nFmt
, const String
& rStr
)
554 TDataCntnrEntry_Impl aEntry
;
556 OUString
aStr( rStr
);
557 aEntry
.aAny
<<= aStr
;
558 pImpl
->aFmtList
.push_back( aEntry
);
559 AddFormat( aEntry
.nId
);
563 // -----------------------------------------------------------------------------
565 void TransferDataContainer::CopyString( const String
& rStr
)
567 CopyString( SOT_FORMAT_STRING
, rStr
);
570 // -----------------------------------------------------------------------------
572 void TransferDataContainer::CopyAny( sal_uInt16 nFmt
,
573 const ::com::sun::star::uno::Any
& rAny
)
575 TDataCntnrEntry_Impl aEntry
;
578 pImpl
->aFmtList
.push_back( aEntry
);
579 AddFormat( aEntry
.nId
);
582 // -----------------------------------------------------------------------------
584 sal_Bool
TransferDataContainer::HasAnyData() const
586 return pImpl
->aFmtList
.begin() != pImpl
->aFmtList
.end() ||
590 // -----------------------------------------------------------------------------
592 void TransferDataContainer::StartDrag(
593 Window
* pWindow
, sal_Int8 nDragSourceActions
,
594 const Link
& rLnk
, sal_Int32 nDragPointer
, sal_Int32 nDragImage
)
596 pImpl
->aFinshedLnk
= rLnk
;
597 TransferableHelper::StartDrag( pWindow
, nDragSourceActions
,
598 nDragPointer
, nDragImage
);
601 // -----------------------------------------------------------------------------
603 void TransferDataContainer::DragFinished( sal_Int8 nDropAction
)
605 if( pImpl
->aFinshedLnk
.IsSet() )
606 pImpl
->aFinshedLnk
.Call( &nDropAction
);
609 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */