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