1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: transfer2.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_svtools.hxx"
33 #include <vos/mutex.hxx>
35 #include <tools/debug.hxx>
38 #include <tools/urlobj.hxx>
40 #include <unotools/ucbstreamhelper.hxx>
41 #include <sot/exchange.hxx>
42 #include <sot/storage.hxx>
43 #include <vcl/bitmap.hxx>
44 #include <vcl/gdimtf.hxx>
45 #include <vcl/graph.hxx>
46 #include <vcl/svapp.hxx>
47 #include <vcl/window.hxx>
48 #include <comphelper/processfactory.hxx>
49 #ifndef _COM_SUN_STAR_DATATRANSFER_DND_DROPTARGETDRAGCONTEXT_HPP_
50 #include <com/sun/star/datatransfer/dnd/XDropTargetDragContext.hpp>
54 #include "inetimg.hxx"
55 #include <svtools/imap.hxx>
56 #include <svtools/transfer.hxx>
62 using namespace ::com::sun::star::uno
;
63 using namespace ::com::sun::star::lang
;
64 using namespace ::com::sun::star::io
;
65 using namespace ::com::sun::star::datatransfer
;
66 using namespace ::com::sun::star::datatransfer::clipboard
;
67 using namespace ::com::sun::star::datatransfer::dnd
;
69 // -----------------------------------------
70 // - DragSourceHelper::DragGestureListener -
71 // -----------------------------------------
73 DragSourceHelper::DragGestureListener::DragGestureListener( DragSourceHelper
& rDragSourceHelper
) :
74 mrParent( rDragSourceHelper
)
78 // -----------------------------------------------------------------------------
80 DragSourceHelper::DragGestureListener::~DragGestureListener()
84 // -----------------------------------------------------------------------------
86 void SAL_CALL
DragSourceHelper::DragGestureListener::disposing( const EventObject
& ) throw( RuntimeException
)
90 // -----------------------------------------------------------------------------
92 void SAL_CALL
DragSourceHelper::DragGestureListener::dragGestureRecognized( const DragGestureEvent
& rDGE
) throw( RuntimeException
)
94 const ::vos::OGuard
aGuard( Application::GetSolarMutex() );
96 const Point
aPtPixel( rDGE
.DragOriginX
, rDGE
.DragOriginY
);
97 mrParent
.StartDrag( rDGE
.DragAction
, aPtPixel
);
100 // --------------------
101 // - DragSourceHelper -
102 // --------------------
104 DragSourceHelper::DragSourceHelper( Window
* pWindow
) :
105 mxDragGestureRecognizer( pWindow
->GetDragGestureRecognizer() )
107 if( mxDragGestureRecognizer
.is() )
109 mxDragGestureListener
= new DragSourceHelper::DragGestureListener( *this );
110 mxDragGestureRecognizer
->addDragGestureListener( mxDragGestureListener
);
114 // -----------------------------------------------------------------------------
116 DragSourceHelper::~DragSourceHelper()
118 if( mxDragGestureRecognizer
.is() )
119 mxDragGestureRecognizer
->removeDragGestureListener( mxDragGestureListener
);
122 // -----------------------------------------------------------------------------
124 void DragSourceHelper::StartDrag( sal_Int8
, const Point
& )
128 // ----------------------------------------
129 // - DropTargetHelper::DropTargetListener -
130 // ----------------------------------------
132 DropTargetHelper::DropTargetListener::DropTargetListener( DropTargetHelper
& rDropTargetHelper
) :
133 mrParent( rDropTargetHelper
),
134 mpLastDragOverEvent( NULL
)
138 // -----------------------------------------------------------------------------
140 DropTargetHelper::DropTargetListener::~DropTargetListener()
142 delete mpLastDragOverEvent
;
145 // -----------------------------------------------------------------------------
147 void SAL_CALL
DropTargetHelper::DropTargetListener::disposing( const EventObject
& ) throw( RuntimeException
)
151 // -----------------------------------------------------------------------------
153 void SAL_CALL
DropTargetHelper::DropTargetListener::drop( const DropTargetDropEvent
& rDTDE
) throw( RuntimeException
)
155 const ::vos::OGuard
aGuard( Application::GetSolarMutex() );
159 AcceptDropEvent aAcceptEvent
;
160 ExecuteDropEvent
aExecuteEvt( rDTDE
.DropAction
& ~DNDConstants::ACTION_DEFAULT
, Point( rDTDE
.LocationX
, rDTDE
.LocationY
), rDTDE
);
161 sal_Int8 nRet
= DNDConstants::ACTION_NONE
;
163 aExecuteEvt
.mbDefault
= ( ( rDTDE
.DropAction
& DNDConstants::ACTION_DEFAULT
) != 0 );
165 // in case of a default action, call ::AcceptDrop first and use the returned
166 // accepted action as the execute action in the call to ::ExecuteDrop
167 aAcceptEvent
.mnAction
= aExecuteEvt
.mnAction
;
168 aAcceptEvent
.maPosPixel
= aExecuteEvt
.maPosPixel
;
169 (DropTargetEvent
&)( aAcceptEvent
.maDragEvent
) = (DropTargetEvent
&) rDTDE
;
170 ( (DropTargetDragEvent
&)( aAcceptEvent
.maDragEvent
) ).DropAction
= rDTDE
.DropAction
;
171 ( (DropTargetDragEvent
&)( aAcceptEvent
.maDragEvent
) ).LocationX
= rDTDE
.LocationX
;
172 ( (DropTargetDragEvent
&)( aAcceptEvent
.maDragEvent
) ).LocationY
= rDTDE
.LocationY
;
173 ( (DropTargetDragEvent
&)( aAcceptEvent
.maDragEvent
) ).SourceActions
= rDTDE
.SourceActions
;
174 aAcceptEvent
.mbLeaving
= sal_False
;
175 aAcceptEvent
.mbDefault
= aExecuteEvt
.mbDefault
;
177 nRet
= mrParent
.AcceptDrop( aAcceptEvent
);
179 if( DNDConstants::ACTION_NONE
!= nRet
)
181 rDTDE
.Context
->acceptDrop( nRet
);
183 if( aExecuteEvt
.mbDefault
)
184 aExecuteEvt
.mnAction
= nRet
;
186 nRet
= mrParent
.ExecuteDrop( aExecuteEvt
);
189 rDTDE
.Context
->dropComplete( DNDConstants::ACTION_NONE
!= nRet
);
191 if( mpLastDragOverEvent
)
193 delete mpLastDragOverEvent
;
194 mpLastDragOverEvent
= NULL
;
197 catch( const ::com::sun::star::uno::Exception
& )
202 // -----------------------------------------------------------------------------
204 void SAL_CALL
DropTargetHelper::DropTargetListener::dragEnter( const DropTargetDragEnterEvent
& rDTDEE
) throw( RuntimeException
)
206 const ::vos::OGuard
aGuard( Application::GetSolarMutex() );
210 mrParent
.ImplBeginDrag( rDTDEE
.SupportedDataFlavors
);
212 catch( const ::com::sun::star::uno::Exception
& )
219 // -----------------------------------------------------------------------------
221 void SAL_CALL
DropTargetHelper::DropTargetListener::dragOver( const DropTargetDragEvent
& rDTDE
) throw( RuntimeException
)
223 const ::vos::OGuard
aGuard( Application::GetSolarMutex() );
227 if( mpLastDragOverEvent
)
228 delete mpLastDragOverEvent
;
230 mpLastDragOverEvent
= new AcceptDropEvent( rDTDE
.DropAction
& ~DNDConstants::ACTION_DEFAULT
, Point( rDTDE
.LocationX
, rDTDE
.LocationY
), rDTDE
);
231 mpLastDragOverEvent
->mbDefault
= ( ( rDTDE
.DropAction
& DNDConstants::ACTION_DEFAULT
) != 0 );
233 const sal_Int8 nRet
= mrParent
.AcceptDrop( *mpLastDragOverEvent
);
235 if( DNDConstants::ACTION_NONE
== nRet
)
236 rDTDE
.Context
->rejectDrag();
238 rDTDE
.Context
->acceptDrag( nRet
);
240 catch( const ::com::sun::star::uno::Exception
& )
245 // -----------------------------------------------------------------------------
247 void SAL_CALL
DropTargetHelper::DropTargetListener::dragExit( const DropTargetEvent
& ) throw( RuntimeException
)
249 const ::vos::OGuard
aGuard( Application::GetSolarMutex() );
253 if( mpLastDragOverEvent
)
255 mpLastDragOverEvent
->mbLeaving
= sal_True
;
256 mrParent
.AcceptDrop( *mpLastDragOverEvent
);
257 delete mpLastDragOverEvent
;
258 mpLastDragOverEvent
= NULL
;
261 mrParent
.ImplEndDrag();
263 catch( const ::com::sun::star::uno::Exception
& )
269 // -----------------------------------------------------------------------------
271 void SAL_CALL
DropTargetHelper::DropTargetListener::dropActionChanged( const DropTargetDragEvent
& ) throw( RuntimeException
)
275 // --------------------
276 // - DropTargetHelper -
277 // --------------------
279 DropTargetHelper::DropTargetHelper( Window
* pWindow
) :
280 mxDropTarget( pWindow
->GetDropTarget() ),
281 mpFormats( new DataFlavorExVector
)
286 // -----------------------------------------------------------------------------
288 DropTargetHelper::DropTargetHelper( const Reference
< XDropTarget
>& rxDropTarget
) :
289 mxDropTarget( rxDropTarget
),
290 mpFormats( new DataFlavorExVector
)
295 // -----------------------------------------------------------------------------
297 DropTargetHelper::~DropTargetHelper()
299 if( mxDropTarget
.is() )
300 mxDropTarget
->removeDropTargetListener( mxDropTargetListener
);
305 // -----------------------------------------------------------------------------
307 void DropTargetHelper::ImplConstruct()
309 if( mxDropTarget
.is() )
311 mxDropTargetListener
= new DropTargetHelper::DropTargetListener( *this );
312 mxDropTarget
->addDropTargetListener( mxDropTargetListener
);
313 mxDropTarget
->setActive( sal_True
);
317 // -----------------------------------------------------------------------------
319 void DropTargetHelper::ImplBeginDrag( const Sequence
< DataFlavor
>& rSupportedDataFlavors
)
322 TransferableDataHelper::FillDataFlavorExVector( rSupportedDataFlavors
, *mpFormats
);
325 // -----------------------------------------------------------------------------
327 void DropTargetHelper::ImplEndDrag()
332 // -----------------------------------------------------------------------------
334 sal_Int8
DropTargetHelper::AcceptDrop( const AcceptDropEvent
& )
336 return( DNDConstants::ACTION_NONE
);
339 // -----------------------------------------------------------------------------
341 sal_Int8
DropTargetHelper::ExecuteDrop( const ExecuteDropEvent
& )
343 return( DNDConstants::ACTION_NONE
);
346 // -----------------------------------------------------------------------------
348 sal_Bool
DropTargetHelper::IsDropFormatSupported( SotFormatStringId nFormat
)
350 DataFlavorExVector::iterator
aIter( mpFormats
->begin() ), aEnd( mpFormats
->end() );
351 sal_Bool bRet
= sal_False
;
353 while( aIter
!= aEnd
)
355 if( nFormat
== (*aIter
++).mnSotId
)
365 // -----------------------------------------------------------------------------
367 sal_Bool
DropTargetHelper::IsDropFormatSupported( const DataFlavor
& rFlavor
)
369 DataFlavorExVector::iterator
aIter( mpFormats
->begin() ), aEnd( mpFormats
->end() );
370 sal_Bool bRet
= sal_False
;
372 while( aIter
!= aEnd
)
374 if( TransferableDataHelper::IsEqual( rFlavor
, *aIter
++ ) )
384 // -----------------------------------------------------------------------------
385 // TransferDataContainer
386 // -----------------------------------------------------------------------------
388 struct TDataCntnrEntry_Impl
390 ::com::sun::star::uno::Any aAny
;
391 SotFormatStringId nId
;
394 // -----------------------------------------------------------------------------
396 typedef ::std::list
< TDataCntnrEntry_Impl
> TDataCntnrEntryList
;
398 // -----------------------------------------------------------------------------
400 struct TransferDataContainer_Impl
402 TDataCntnrEntryList aFmtList
;
404 INetBookmark
* pBookmk
;
407 TransferDataContainer_Impl()
408 : pBookmk( 0 ), pGrf( 0 )
412 ~TransferDataContainer_Impl()
419 // -----------------------------------------------------------------------------
421 TransferDataContainer::TransferDataContainer()
422 : pImpl( new TransferDataContainer_Impl
)
426 // -----------------------------------------------------------------------------
428 TransferDataContainer::~TransferDataContainer()
433 // -----------------------------------------------------------------------------
435 void TransferDataContainer::AddSupportedFormats()
439 // -----------------------------------------------------------------------------
441 sal_Bool
TransferDataContainer::GetData( const
442 ::com::sun::star::datatransfer::DataFlavor
& rFlavor
)
444 TDataCntnrEntryList::iterator
aIter( pImpl
->aFmtList
.begin() ),
445 aEnd( pImpl
->aFmtList
.end() );
446 sal_Bool bFnd
= sal_False
;
447 ULONG nFmtId
= SotExchange::GetFormat( rFlavor
);
449 // test first the list
450 for( ; aIter
!= aEnd
; ++aIter
)
452 TDataCntnrEntry_Impl
& rEntry
= (TDataCntnrEntry_Impl
&)*aIter
;
453 if( nFmtId
== rEntry
.nId
)
455 bFnd
= SetAny( rEntry
.aAny
, rFlavor
);
460 // test second the bookmark pointer
464 case SOT_FORMAT_STRING
:
465 case SOT_FORMATSTR_ID_SOLK
:
466 case SOT_FORMATSTR_ID_NETSCAPE_BOOKMARK
:
467 case SOT_FORMATSTR_ID_FILECONTENT
:
468 case SOT_FORMATSTR_ID_FILEGRPDESCRIPTOR
:
469 case SOT_FORMATSTR_ID_UNIFORMRESOURCELOCATOR
:
471 bFnd
= SetINetBookmark( *pImpl
->pBookmk
, rFlavor
);
474 case SOT_FORMATSTR_ID_SVXB
:
475 case SOT_FORMAT_BITMAP
:
476 case SOT_FORMAT_GDIMETAFILE
:
478 bFnd
= SetGraphic( *pImpl
->pGrf
, rFlavor
);
485 // -----------------------------------------------------------------------------
487 void TransferDataContainer::ClearData()
490 pImpl
= new TransferDataContainer_Impl
;
494 // -----------------------------------------------------------------------------
496 void TransferDataContainer::CopyINetBookmark( const INetBookmark
& rBkmk
)
498 if( !pImpl
->pBookmk
)
499 pImpl
->pBookmk
= new INetBookmark( rBkmk
);
501 *pImpl
->pBookmk
= rBkmk
;
503 AddFormat( SOT_FORMAT_STRING
);
504 AddFormat( SOT_FORMATSTR_ID_SOLK
);
505 AddFormat( SOT_FORMATSTR_ID_NETSCAPE_BOOKMARK
);
506 AddFormat( SOT_FORMATSTR_ID_FILECONTENT
);
507 AddFormat( SOT_FORMATSTR_ID_FILEGRPDESCRIPTOR
);
508 AddFormat( SOT_FORMATSTR_ID_UNIFORMRESOURCELOCATOR
);
511 // -----------------------------------------------------------------------------
513 void TransferDataContainer::CopyAnyData( ULONG nFormatId
,
514 const sal_Char
* pData
, ULONG nLen
)
518 TDataCntnrEntry_Impl aEntry
;
519 aEntry
.nId
= nFormatId
;
521 Sequence
< sal_Int8
> aSeq( nLen
);
522 memcpy( aSeq
.getArray(), pData
, nLen
);
523 aEntry
.aAny
<<= aSeq
;
524 pImpl
->aFmtList
.push_back( aEntry
);
525 AddFormat( nFormatId
);
529 // -----------------------------------------------------------------------------
531 void TransferDataContainer::CopyByteString( ULONG nFormatId
,
532 const ByteString
& rStr
)
534 CopyAnyData( nFormatId
, rStr
.GetBuffer(), rStr
.Len() );
537 // -----------------------------------------------------------------------------
539 void TransferDataContainer::CopyINetImage( const INetImage
& rINtImg
)
541 SvMemoryStream
aMemStm( 1024, 1024 );
542 aMemStm
.SetVersion( SOFFICE_FILEFORMAT_50
);
543 rINtImg
.Write( aMemStm
, SOT_FORMATSTR_ID_INET_IMAGE
);
544 CopyAnyData( SOT_FORMATSTR_ID_INET_IMAGE
, (sal_Char
*)aMemStm
.GetData(),
545 aMemStm
.Seek( STREAM_SEEK_TO_END
) );
548 // -----------------------------------------------------------------------------
550 void TransferDataContainer::CopyImageMap( const ImageMap
& rImgMap
)
552 SvMemoryStream
aMemStm( 8192, 8192 );
553 aMemStm
.SetVersion( SOFFICE_FILEFORMAT_50
);
554 rImgMap
.Write( aMemStm
, String() );
555 CopyAnyData( SOT_FORMATSTR_ID_SVIM
, (sal_Char
*)aMemStm
.GetData(),
556 aMemStm
.Seek( STREAM_SEEK_TO_END
) );
559 // -----------------------------------------------------------------------------
561 void TransferDataContainer::CopyGraphic( const Graphic
& rGrf
)
563 GraphicType nType
= rGrf
.GetType();
564 if( GRAPHIC_NONE
!= nType
)
567 pImpl
->pGrf
= new Graphic( rGrf
);
571 AddFormat( SOT_FORMATSTR_ID_SVXB
);
572 if( GRAPHIC_BITMAP
== nType
)
573 AddFormat( SOT_FORMAT_BITMAP
);
574 else if( GRAPHIC_GDIMETAFILE
== nType
)
575 AddFormat( SOT_FORMAT_GDIMETAFILE
);
579 // -----------------------------------------------------------------------------
581 void TransferDataContainer::CopyString( USHORT nFmt
, const String
& rStr
)
585 TDataCntnrEntry_Impl aEntry
;
587 rtl::OUString
aStr( rStr
);
588 aEntry
.aAny
<<= aStr
;
589 pImpl
->aFmtList
.push_back( aEntry
);
590 AddFormat( aEntry
.nId
);
594 // -----------------------------------------------------------------------------
596 void TransferDataContainer::CopyString( const String
& rStr
)
598 CopyString( SOT_FORMAT_STRING
, rStr
);
601 // -----------------------------------------------------------------------------
603 void TransferDataContainer::CopyAny( USHORT nFmt
,
604 const ::com::sun::star::uno::Any
& rAny
)
606 TDataCntnrEntry_Impl aEntry
;
609 pImpl
->aFmtList
.push_back( aEntry
);
610 AddFormat( aEntry
.nId
);
613 // -----------------------------------------------------------------------------
615 sal_Bool
TransferDataContainer::HasAnyData() const
617 return pImpl
->aFmtList
.begin() != pImpl
->aFmtList
.end() ||
621 // -----------------------------------------------------------------------------
623 void TransferDataContainer::StartDrag(
624 Window
* pWindow
, sal_Int8 nDragSourceActions
,
625 const Link
& rLnk
, sal_Int32 nDragPointer
, sal_Int32 nDragImage
)
627 pImpl
->aFinshedLnk
= rLnk
;
628 TransferableHelper::StartDrag( pWindow
, nDragSourceActions
,
629 nDragPointer
, nDragImage
);
632 // -----------------------------------------------------------------------------
634 void TransferDataContainer::DragFinished( sal_Int8 nDropAction
)
636 if( pImpl
->aFinshedLnk
.IsSet() )
637 pImpl
->aFinshedLnk
.Call( &nDropAction
);