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