blob: c90b0612bef19167169a778f1c574c0d840d28e5 [file] [log] [blame]
/**************************************************************
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*************************************************************/
// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_svtools.hxx"
#include <vos/mutex.hxx>
#include <tools/debug.hxx>
#include <tools/urlobj.hxx>
#include <unotools/ucbstreamhelper.hxx>
#include <sot/exchange.hxx>
#include <sot/storage.hxx>
#include <vcl/bitmap.hxx>
#include <vcl/gdimtf.hxx>
#include <vcl/graph.hxx>
#include <vcl/svapp.hxx>
#include <vcl/window.hxx>
#include <comphelper/processfactory.hxx>
#include <com/sun/star/datatransfer/dnd/XDropTargetDragContext.hpp>
#include "svl/urlbmk.hxx"
#include <svtools/inetimg.hxx>
#include <svtools/imap.hxx>
#include <svtools/transfer.hxx>
// --------------
// - Namespaces -
// --------------
using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::lang;
using namespace ::com::sun::star::io;
using namespace ::com::sun::star::datatransfer;
using namespace ::com::sun::star::datatransfer::clipboard;
using namespace ::com::sun::star::datatransfer::dnd;
// -----------------------------------------
// - DragSourceHelper::DragGestureListener -
// -----------------------------------------
DragSourceHelper::DragGestureListener::DragGestureListener( DragSourceHelper& rDragSourceHelper ) :
mrParent( rDragSourceHelper )
{
}
// -----------------------------------------------------------------------------
DragSourceHelper::DragGestureListener::~DragGestureListener()
{
}
// -----------------------------------------------------------------------------
void SAL_CALL DragSourceHelper::DragGestureListener::disposing( const EventObject& ) throw( RuntimeException )
{
}
// -----------------------------------------------------------------------------
void SAL_CALL DragSourceHelper::DragGestureListener::dragGestureRecognized( const DragGestureEvent& rDGE ) throw( RuntimeException )
{
const ::vos::OGuard aGuard( Application::GetSolarMutex() );
const Point aPtPixel( rDGE.DragOriginX, rDGE.DragOriginY );
mrParent.StartDrag( rDGE.DragAction, aPtPixel );
}
// --------------------
// - DragSourceHelper -
// --------------------
DragSourceHelper::DragSourceHelper( Window* pWindow ) :
mxDragGestureRecognizer( pWindow->GetDragGestureRecognizer() )
{
if( mxDragGestureRecognizer.is() )
{
mxDragGestureListener = new DragSourceHelper::DragGestureListener( *this );
mxDragGestureRecognizer->addDragGestureListener( mxDragGestureListener );
}
}
// -----------------------------------------------------------------------------
DragSourceHelper::~DragSourceHelper()
{
if( mxDragGestureRecognizer.is() )
mxDragGestureRecognizer->removeDragGestureListener( mxDragGestureListener );
}
// -----------------------------------------------------------------------------
void DragSourceHelper::StartDrag( sal_Int8, const Point& )
{
}
// ----------------------------------------
// - DropTargetHelper::DropTargetListener -
// ----------------------------------------
DropTargetHelper::DropTargetListener::DropTargetListener( DropTargetHelper& rDropTargetHelper ) :
mrParent( rDropTargetHelper ),
mpLastDragOverEvent( NULL )
{
}
// -----------------------------------------------------------------------------
DropTargetHelper::DropTargetListener::~DropTargetListener()
{
delete mpLastDragOverEvent;
}
// -----------------------------------------------------------------------------
void SAL_CALL DropTargetHelper::DropTargetListener::disposing( const EventObject& ) throw( RuntimeException )
{
}
// -----------------------------------------------------------------------------
void SAL_CALL DropTargetHelper::DropTargetListener::drop( const DropTargetDropEvent& rDTDE ) throw( RuntimeException )
{
const ::vos::OGuard aGuard( Application::GetSolarMutex() );
try
{
AcceptDropEvent aAcceptEvent;
ExecuteDropEvent aExecuteEvt( rDTDE.DropAction & ~DNDConstants::ACTION_DEFAULT, Point( rDTDE.LocationX, rDTDE.LocationY ), rDTDE );
sal_Int8 nRet = DNDConstants::ACTION_NONE;
aExecuteEvt.mbDefault = ( ( rDTDE.DropAction & DNDConstants::ACTION_DEFAULT ) != 0 );
// in case of a default action, call ::AcceptDrop first and use the returned
// accepted action as the execute action in the call to ::ExecuteDrop
aAcceptEvent.mnAction = aExecuteEvt.mnAction;
aAcceptEvent.maPosPixel = aExecuteEvt.maPosPixel;
(DropTargetEvent&)( aAcceptEvent.maDragEvent ) = (DropTargetEvent&) rDTDE;
( (DropTargetDragEvent&)( aAcceptEvent.maDragEvent ) ).DropAction = rDTDE.DropAction;
( (DropTargetDragEvent&)( aAcceptEvent.maDragEvent ) ).LocationX = rDTDE.LocationX;
( (DropTargetDragEvent&)( aAcceptEvent.maDragEvent ) ).LocationY = rDTDE.LocationY;
( (DropTargetDragEvent&)( aAcceptEvent.maDragEvent ) ).SourceActions = rDTDE.SourceActions;
aAcceptEvent.mbLeaving = sal_False;
aAcceptEvent.mbDefault = aExecuteEvt.mbDefault;
nRet = mrParent.AcceptDrop( aAcceptEvent );
if( DNDConstants::ACTION_NONE != nRet )
{
rDTDE.Context->acceptDrop( nRet );
if( aExecuteEvt.mbDefault )
aExecuteEvt.mnAction = nRet;
nRet = mrParent.ExecuteDrop( aExecuteEvt );
}
rDTDE.Context->dropComplete( DNDConstants::ACTION_NONE != nRet );
if( mpLastDragOverEvent )
{
delete mpLastDragOverEvent;
mpLastDragOverEvent = NULL;
}
}
catch( const ::com::sun::star::uno::Exception& )
{
}
}
// -----------------------------------------------------------------------------
void SAL_CALL DropTargetHelper::DropTargetListener::dragEnter( const DropTargetDragEnterEvent& rDTDEE ) throw( RuntimeException )
{
const ::vos::OGuard aGuard( Application::GetSolarMutex() );
try
{
mrParent.ImplBeginDrag( rDTDEE.SupportedDataFlavors );
}
catch( const ::com::sun::star::uno::Exception& )
{
}
dragOver( rDTDEE );
}
// -----------------------------------------------------------------------------
void SAL_CALL DropTargetHelper::DropTargetListener::dragOver( const DropTargetDragEvent& rDTDE ) throw( RuntimeException )
{
const ::vos::OGuard aGuard( Application::GetSolarMutex() );
try
{
if( mpLastDragOverEvent )
delete mpLastDragOverEvent;
mpLastDragOverEvent = new AcceptDropEvent( rDTDE.DropAction & ~DNDConstants::ACTION_DEFAULT, Point( rDTDE.LocationX, rDTDE.LocationY ), rDTDE );
mpLastDragOverEvent->mbDefault = ( ( rDTDE.DropAction & DNDConstants::ACTION_DEFAULT ) != 0 );
const sal_Int8 nRet = mrParent.AcceptDrop( *mpLastDragOverEvent );
if( DNDConstants::ACTION_NONE == nRet )
rDTDE.Context->rejectDrag();
else
rDTDE.Context->acceptDrag( nRet );
}
catch( const ::com::sun::star::uno::Exception& )
{
}
}
// -----------------------------------------------------------------------------
void SAL_CALL DropTargetHelper::DropTargetListener::dragExit( const DropTargetEvent& ) throw( RuntimeException )
{
const ::vos::OGuard aGuard( Application::GetSolarMutex() );
try
{
if( mpLastDragOverEvent )
{
mpLastDragOverEvent->mbLeaving = sal_True;
mrParent.AcceptDrop( *mpLastDragOverEvent );
delete mpLastDragOverEvent;
mpLastDragOverEvent = NULL;
}
mrParent.ImplEndDrag();
}
catch( const ::com::sun::star::uno::Exception& )
{
}
}
// -----------------------------------------------------------------------------
void SAL_CALL DropTargetHelper::DropTargetListener::dropActionChanged( const DropTargetDragEvent& ) throw( RuntimeException )
{
}
// --------------------
// - DropTargetHelper -
// --------------------
DropTargetHelper::DropTargetHelper( Window* pWindow ) :
mxDropTarget( pWindow->GetDropTarget() ),
mpFormats( new DataFlavorExVector )
{
ImplConstruct();
}
// -----------------------------------------------------------------------------
DropTargetHelper::DropTargetHelper( const Reference< XDropTarget >& rxDropTarget ) :
mxDropTarget( rxDropTarget ),
mpFormats( new DataFlavorExVector )
{
ImplConstruct();
}
// -----------------------------------------------------------------------------
DropTargetHelper::~DropTargetHelper()
{
if( mxDropTarget.is() )
mxDropTarget->removeDropTargetListener( mxDropTargetListener );
delete mpFormats;
}
// -----------------------------------------------------------------------------
void DropTargetHelper::ImplConstruct()
{
if( mxDropTarget.is() )
{
mxDropTargetListener = new DropTargetHelper::DropTargetListener( *this );
mxDropTarget->addDropTargetListener( mxDropTargetListener );
mxDropTarget->setActive( sal_True );
}
}
// -----------------------------------------------------------------------------
void DropTargetHelper::ImplBeginDrag( const Sequence< DataFlavor >& rSupportedDataFlavors )
{
mpFormats->clear();
TransferableDataHelper::FillDataFlavorExVector( rSupportedDataFlavors, *mpFormats );
}
// -----------------------------------------------------------------------------
void DropTargetHelper::ImplEndDrag()
{
mpFormats->clear();
}
// -----------------------------------------------------------------------------
sal_Int8 DropTargetHelper::AcceptDrop( const AcceptDropEvent& )
{
return( DNDConstants::ACTION_NONE );
}
// -----------------------------------------------------------------------------
sal_Int8 DropTargetHelper::ExecuteDrop( const ExecuteDropEvent& )
{
return( DNDConstants::ACTION_NONE );
}
// -----------------------------------------------------------------------------
sal_Bool DropTargetHelper::IsDropFormatSupported( SotFormatStringId nFormat )
{
DataFlavorExVector::iterator aIter( mpFormats->begin() ), aEnd( mpFormats->end() );
sal_Bool bRet = sal_False;
while( aIter != aEnd )
{
if( nFormat == (*aIter++).mnSotId )
{
bRet = sal_True;
aIter = aEnd;
}
}
return bRet;
}
// -----------------------------------------------------------------------------
sal_Bool DropTargetHelper::IsDropFormatSupported( const DataFlavor& rFlavor )
{
DataFlavorExVector::iterator aIter( mpFormats->begin() ), aEnd( mpFormats->end() );
sal_Bool bRet = sal_False;
while( aIter != aEnd )
{
if( TransferableDataHelper::IsEqual( rFlavor, *aIter++ ) )
{
bRet = sal_True;
aIter = aEnd;
}
}
return bRet;
}
// -----------------------------------------------------------------------------
// TransferDataContainer
// -----------------------------------------------------------------------------
struct TDataCntnrEntry_Impl
{
::com::sun::star::uno::Any aAny;
SotFormatStringId nId;
};
// -----------------------------------------------------------------------------
typedef ::std::list< TDataCntnrEntry_Impl > TDataCntnrEntryList;
// -----------------------------------------------------------------------------
struct TransferDataContainer_Impl
{
TDataCntnrEntryList aFmtList;
Link aFinshedLnk;
INetBookmark* pBookmk;
Graphic* pGrf;
TransferDataContainer_Impl()
: pBookmk( 0 ), pGrf( 0 )
{
}
~TransferDataContainer_Impl()
{
delete pBookmk;
delete pGrf;
}
};
// -----------------------------------------------------------------------------
TransferDataContainer::TransferDataContainer()
: pImpl( new TransferDataContainer_Impl )
{
}
// -----------------------------------------------------------------------------
TransferDataContainer::~TransferDataContainer()
{
delete pImpl;
}
// -----------------------------------------------------------------------------
void TransferDataContainer::AddSupportedFormats()
{
}
// -----------------------------------------------------------------------------
sal_Bool TransferDataContainer::GetData( const
::com::sun::star::datatransfer::DataFlavor& rFlavor )
{
TDataCntnrEntryList::iterator aIter( pImpl->aFmtList.begin() ),
aEnd( pImpl->aFmtList.end() );
sal_Bool bFnd = sal_False;
sal_uLong nFmtId = SotExchange::GetFormat( rFlavor );
// test first the list
for( ; aIter != aEnd; ++aIter )
{
TDataCntnrEntry_Impl& rEntry = (TDataCntnrEntry_Impl&)*aIter;
if( nFmtId == rEntry.nId )
{
bFnd = SetAny( rEntry.aAny, rFlavor );
break;
}
}
// test second the bookmark pointer
if( !bFnd )
switch( nFmtId )
{
case SOT_FORMAT_STRING:
case SOT_FORMATSTR_ID_SOLK:
case SOT_FORMATSTR_ID_NETSCAPE_BOOKMARK:
case SOT_FORMATSTR_ID_FILECONTENT:
case SOT_FORMATSTR_ID_FILEGRPDESCRIPTOR:
case SOT_FORMATSTR_ID_UNIFORMRESOURCELOCATOR:
if( pImpl->pBookmk )
bFnd = SetINetBookmark( *pImpl->pBookmk, rFlavor );
break;
case SOT_FORMATSTR_ID_SVXB:
case SOT_FORMATSTR_ID_PNG:
case SOT_FORMAT_BITMAP:
case SOT_FORMAT_GDIMETAFILE:
if( pImpl->pGrf )
bFnd = SetGraphic( *pImpl->pGrf, rFlavor );
break;
}
return bFnd;
}
// -----------------------------------------------------------------------------
void TransferDataContainer::ClearData()
{
delete pImpl;
pImpl = new TransferDataContainer_Impl;
ClearFormats();
}
// -----------------------------------------------------------------------------
void TransferDataContainer::CopyINetBookmark( const INetBookmark& rBkmk )
{
if( !pImpl->pBookmk )
pImpl->pBookmk = new INetBookmark( rBkmk );
else
*pImpl->pBookmk = rBkmk;
AddFormat( SOT_FORMAT_STRING );
AddFormat( SOT_FORMATSTR_ID_SOLK );
AddFormat( SOT_FORMATSTR_ID_NETSCAPE_BOOKMARK );
AddFormat( SOT_FORMATSTR_ID_FILECONTENT );
AddFormat( SOT_FORMATSTR_ID_FILEGRPDESCRIPTOR );
AddFormat( SOT_FORMATSTR_ID_UNIFORMRESOURCELOCATOR );
}
// -----------------------------------------------------------------------------
void TransferDataContainer::CopyAnyData( sal_uLong nFormatId,
const sal_Char* pData, sal_uLong nLen )
{
if( nLen )
{
TDataCntnrEntry_Impl aEntry;
aEntry.nId = nFormatId;
Sequence< sal_Int8 > aSeq( nLen );
memcpy( aSeq.getArray(), pData, nLen );
aEntry.aAny <<= aSeq;
pImpl->aFmtList.push_back( aEntry );
AddFormat( nFormatId );
}
}
// -----------------------------------------------------------------------------
void TransferDataContainer::CopyByteString( sal_uLong nFormatId,
const ByteString& rStr )
{
CopyAnyData( nFormatId, rStr.GetBuffer(), rStr.Len() );
}
// -----------------------------------------------------------------------------
void TransferDataContainer::CopyINetImage( const INetImage& rINtImg )
{
SvMemoryStream aMemStm( 1024, 1024 );
aMemStm.SetVersion( SOFFICE_FILEFORMAT_50 );
rINtImg.Write( aMemStm, SOT_FORMATSTR_ID_INET_IMAGE );
CopyAnyData( SOT_FORMATSTR_ID_INET_IMAGE, (sal_Char*)aMemStm.GetData(),
aMemStm.Seek( STREAM_SEEK_TO_END ) );
}
// -----------------------------------------------------------------------------
void TransferDataContainer::CopyImageMap( const ImageMap& rImgMap )
{
SvMemoryStream aMemStm( 8192, 8192 );
aMemStm.SetVersion( SOFFICE_FILEFORMAT_50 );
rImgMap.Write( aMemStm, String() );
CopyAnyData( SOT_FORMATSTR_ID_SVIM, (sal_Char*)aMemStm.GetData(),
aMemStm.Seek( STREAM_SEEK_TO_END ) );
}
// -----------------------------------------------------------------------------
void TransferDataContainer::CopyGraphic( const Graphic& rGrf )
{
GraphicType nType = rGrf.GetType();
if( GRAPHIC_NONE != nType )
{
if( !pImpl->pGrf )
pImpl->pGrf = new Graphic( rGrf );
else
*pImpl->pGrf = rGrf;
AddFormat( SOT_FORMATSTR_ID_SVXB );
if( GRAPHIC_BITMAP == nType )
{
AddFormat( SOT_FORMATSTR_ID_PNG );
AddFormat( SOT_FORMAT_BITMAP );
}
else if( GRAPHIC_GDIMETAFILE == nType )
{
AddFormat( SOT_FORMAT_GDIMETAFILE );
}
}
}
// -----------------------------------------------------------------------------
void TransferDataContainer::CopyString( sal_uInt16 nFmt, const String& rStr )
{
if( rStr.Len() )
{
TDataCntnrEntry_Impl aEntry;
aEntry.nId = nFmt;
rtl::OUString aStr( rStr );
aEntry.aAny <<= aStr;
pImpl->aFmtList.push_back( aEntry );
AddFormat( aEntry.nId );
}
}
// -----------------------------------------------------------------------------
void TransferDataContainer::CopyString( const String& rStr )
{
CopyString( SOT_FORMAT_STRING, rStr );
}
// -----------------------------------------------------------------------------
void TransferDataContainer::CopyAny( sal_uInt16 nFmt,
const ::com::sun::star::uno::Any& rAny )
{
TDataCntnrEntry_Impl aEntry;
aEntry.nId = nFmt;
aEntry.aAny = rAny;
pImpl->aFmtList.push_back( aEntry );
AddFormat( aEntry.nId );
}
// -----------------------------------------------------------------------------
sal_Bool TransferDataContainer::HasAnyData() const
{
return pImpl->aFmtList.begin() != pImpl->aFmtList.end() ||
0 != pImpl->pBookmk;
}
// -----------------------------------------------------------------------------
void TransferDataContainer::StartDrag(
Window* pWindow, sal_Int8 nDragSourceActions,
const Link& rLnk, sal_Int32 nDragPointer, sal_Int32 nDragImage )
{
pImpl->aFinshedLnk = rLnk;
TransferableHelper::StartDrag( pWindow, nDragSourceActions,
nDragPointer, nDragImage );
}
// -----------------------------------------------------------------------------
void TransferDataContainer::DragFinished( sal_Int8 nDropAction )
{
if( pImpl->aFinshedLnk.IsSet() )
pImpl->aFinshedLnk.Call( &nDropAction );
}