Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
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/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
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 .
18 : */
19 :
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>
35 :
36 :
37 : // - Namespaces -
38 :
39 :
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;
46 :
47 :
48 : // - DragSourceHelper::DragGestureListener -
49 :
50 :
51 4029 : DragSourceHelper::DragGestureListener::DragGestureListener( DragSourceHelper& rDragSourceHelper ) :
52 4029 : mrParent( rDragSourceHelper )
53 : {
54 4029 : }
55 :
56 :
57 :
58 1820 : DragSourceHelper::DragGestureListener::~DragGestureListener()
59 : {
60 1820 : }
61 :
62 :
63 :
64 4015 : void SAL_CALL DragSourceHelper::DragGestureListener::disposing( const EventObject& ) throw( RuntimeException, std::exception )
65 : {
66 4015 : }
67 :
68 :
69 :
70 0 : void SAL_CALL DragSourceHelper::DragGestureListener::dragGestureRecognized( const DragGestureEvent& rDGE ) throw( RuntimeException, std::exception )
71 : {
72 0 : const SolarMutexGuard aGuard;
73 :
74 0 : const Point aPtPixel( rDGE.DragOriginX, rDGE.DragOriginY );
75 0 : mrParent.StartDrag( rDGE.DragAction, aPtPixel );
76 0 : }
77 :
78 :
79 : // - DragSourceHelper -
80 :
81 :
82 4029 : DragSourceHelper::DragSourceHelper( vcl::Window* pWindow ) :
83 4029 : mxDragGestureRecognizer( pWindow->GetDragGestureRecognizer() )
84 : {
85 4029 : if( mxDragGestureRecognizer.is() )
86 : {
87 4029 : mxDragGestureListener = new DragSourceHelper::DragGestureListener( *this );
88 4029 : mxDragGestureRecognizer->addDragGestureListener( mxDragGestureListener );
89 : }
90 4029 : }
91 :
92 :
93 :
94 1820 : DragSourceHelper::~DragSourceHelper()
95 : {
96 910 : if( mxDragGestureRecognizer.is() )
97 910 : mxDragGestureRecognizer->removeDragGestureListener( mxDragGestureListener );
98 910 : }
99 :
100 :
101 :
102 0 : void DragSourceHelper::StartDrag( sal_Int8, const Point& )
103 : {
104 0 : }
105 :
106 :
107 : // - DropTargetHelper::DropTargetListener -
108 :
109 :
110 4039 : DropTargetHelper::DropTargetListener::DropTargetListener( DropTargetHelper& rDropTargetHelper ) :
111 : mrParent( rDropTargetHelper ),
112 4039 : mpLastDragOverEvent( NULL )
113 : {
114 4039 : }
115 :
116 :
117 :
118 2712 : DropTargetHelper::DropTargetListener::~DropTargetListener()
119 : {
120 904 : delete mpLastDragOverEvent;
121 1808 : }
122 :
123 :
124 :
125 4024 : void SAL_CALL DropTargetHelper::DropTargetListener::disposing( const EventObject& ) throw( RuntimeException, std::exception )
126 : {
127 4024 : }
128 :
129 :
130 :
131 0 : void SAL_CALL DropTargetHelper::DropTargetListener::drop( const DropTargetDropEvent& rDTDE ) throw( RuntimeException, std::exception )
132 : {
133 0 : const SolarMutexGuard aGuard;
134 :
135 : try
136 : {
137 0 : AcceptDropEvent aAcceptEvent;
138 0 : ExecuteDropEvent aExecuteEvt( rDTDE.DropAction & ~DNDConstants::ACTION_DEFAULT, Point( rDTDE.LocationX, rDTDE.LocationY ), rDTDE );
139 :
140 0 : aExecuteEvt.mbDefault = ( ( rDTDE.DropAction & DNDConstants::ACTION_DEFAULT ) != 0 );
141 :
142 : // in case of a default action, call ::AcceptDrop first and use the returned
143 : // accepted action as the execute action in the call to ::ExecuteDrop
144 0 : aAcceptEvent.mnAction = aExecuteEvt.mnAction;
145 0 : aAcceptEvent.maPosPixel = aExecuteEvt.maPosPixel;
146 0 : (DropTargetEvent&)( aAcceptEvent.maDragEvent ) = (DropTargetEvent&) rDTDE;
147 0 : ( (DropTargetDragEvent&)( aAcceptEvent.maDragEvent ) ).DropAction = rDTDE.DropAction;
148 0 : ( (DropTargetDragEvent&)( aAcceptEvent.maDragEvent ) ).LocationX = rDTDE.LocationX;
149 0 : ( (DropTargetDragEvent&)( aAcceptEvent.maDragEvent ) ).LocationY = rDTDE.LocationY;
150 0 : ( (DropTargetDragEvent&)( aAcceptEvent.maDragEvent ) ).SourceActions = rDTDE.SourceActions;
151 0 : aAcceptEvent.mbLeaving = false;
152 0 : aAcceptEvent.mbDefault = aExecuteEvt.mbDefault;
153 :
154 0 : sal_Int8 nRet = mrParent.AcceptDrop( aAcceptEvent );
155 :
156 0 : if( DNDConstants::ACTION_NONE != nRet )
157 : {
158 0 : rDTDE.Context->acceptDrop( nRet );
159 :
160 0 : if( aExecuteEvt.mbDefault )
161 0 : aExecuteEvt.mnAction = nRet;
162 :
163 0 : nRet = mrParent.ExecuteDrop( aExecuteEvt );
164 : }
165 :
166 0 : rDTDE.Context->dropComplete( DNDConstants::ACTION_NONE != nRet );
167 :
168 0 : if( mpLastDragOverEvent )
169 : {
170 0 : delete mpLastDragOverEvent;
171 0 : mpLastDragOverEvent = NULL;
172 0 : }
173 : }
174 0 : catch( const ::com::sun::star::uno::Exception& )
175 : {
176 0 : }
177 0 : }
178 :
179 :
180 :
181 0 : void SAL_CALL DropTargetHelper::DropTargetListener::dragEnter( const DropTargetDragEnterEvent& rDTDEE ) throw( RuntimeException, std::exception )
182 : {
183 0 : const SolarMutexGuard aGuard;
184 :
185 : try
186 : {
187 0 : mrParent.ImplBeginDrag( rDTDEE.SupportedDataFlavors );
188 : }
189 0 : catch( const ::com::sun::star::uno::Exception& )
190 : {
191 : }
192 :
193 0 : dragOver( rDTDEE );
194 0 : }
195 :
196 :
197 :
198 0 : void SAL_CALL DropTargetHelper::DropTargetListener::dragOver( const DropTargetDragEvent& rDTDE ) throw( RuntimeException, std::exception )
199 : {
200 0 : const SolarMutexGuard aGuard;
201 :
202 : try
203 : {
204 0 : if( mpLastDragOverEvent )
205 0 : delete mpLastDragOverEvent;
206 :
207 0 : mpLastDragOverEvent = new AcceptDropEvent( rDTDE.DropAction & ~DNDConstants::ACTION_DEFAULT, Point( rDTDE.LocationX, rDTDE.LocationY ), rDTDE );
208 0 : mpLastDragOverEvent->mbDefault = ( ( rDTDE.DropAction & DNDConstants::ACTION_DEFAULT ) != 0 );
209 :
210 0 : const sal_Int8 nRet = mrParent.AcceptDrop( *mpLastDragOverEvent );
211 :
212 0 : if( DNDConstants::ACTION_NONE == nRet )
213 0 : rDTDE.Context->rejectDrag();
214 : else
215 0 : rDTDE.Context->acceptDrag( nRet );
216 : }
217 0 : catch( const ::com::sun::star::uno::Exception& )
218 : {
219 0 : }
220 0 : }
221 :
222 :
223 :
224 0 : void SAL_CALL DropTargetHelper::DropTargetListener::dragExit( const DropTargetEvent& ) throw( RuntimeException, std::exception )
225 : {
226 0 : const SolarMutexGuard aGuard;
227 :
228 : try
229 : {
230 0 : if( mpLastDragOverEvent )
231 : {
232 0 : mpLastDragOverEvent->mbLeaving = true;
233 0 : mrParent.AcceptDrop( *mpLastDragOverEvent );
234 0 : delete mpLastDragOverEvent;
235 0 : mpLastDragOverEvent = NULL;
236 : }
237 :
238 0 : mrParent.ImplEndDrag();
239 : }
240 0 : catch( const ::com::sun::star::uno::Exception& )
241 : {
242 0 : }
243 0 : }
244 :
245 :
246 :
247 :
248 0 : void SAL_CALL DropTargetHelper::DropTargetListener::dropActionChanged( const DropTargetDragEvent& ) throw( RuntimeException, std::exception )
249 : {
250 0 : }
251 :
252 :
253 : // - DropTargetHelper -
254 :
255 :
256 4022 : DropTargetHelper::DropTargetHelper( vcl::Window* pWindow ) :
257 : mxDropTarget( pWindow->GetDropTarget() ),
258 4022 : mpFormats( new DataFlavorExVector )
259 : {
260 4022 : ImplConstruct();
261 4022 : }
262 :
263 :
264 :
265 17 : DropTargetHelper::DropTargetHelper( const Reference< XDropTarget >& rxDropTarget ) :
266 : mxDropTarget( rxDropTarget ),
267 17 : mpFormats( new DataFlavorExVector )
268 : {
269 17 : ImplConstruct();
270 17 : }
271 :
272 :
273 :
274 1808 : DropTargetHelper::~DropTargetHelper()
275 : {
276 904 : if( mxDropTarget.is() )
277 904 : mxDropTarget->removeDropTargetListener( mxDropTargetListener );
278 :
279 904 : delete mpFormats;
280 904 : }
281 :
282 :
283 :
284 4039 : void DropTargetHelper::ImplConstruct()
285 : {
286 4039 : if( mxDropTarget.is() )
287 : {
288 4039 : mxDropTargetListener = new DropTargetHelper::DropTargetListener( *this );
289 4039 : mxDropTarget->addDropTargetListener( mxDropTargetListener );
290 4039 : mxDropTarget->setActive( sal_True );
291 : }
292 4039 : }
293 :
294 :
295 :
296 0 : void DropTargetHelper::ImplBeginDrag( const Sequence< DataFlavor >& rSupportedDataFlavors )
297 : {
298 0 : mpFormats->clear();
299 0 : TransferableDataHelper::FillDataFlavorExVector( rSupportedDataFlavors, *mpFormats );
300 0 : }
301 :
302 :
303 :
304 0 : void DropTargetHelper::ImplEndDrag()
305 : {
306 0 : mpFormats->clear();
307 0 : }
308 :
309 :
310 :
311 0 : sal_Int8 DropTargetHelper::AcceptDrop( const AcceptDropEvent& )
312 : {
313 0 : return( DNDConstants::ACTION_NONE );
314 : }
315 :
316 :
317 :
318 0 : sal_Int8 DropTargetHelper::ExecuteDrop( const ExecuteDropEvent& )
319 : {
320 0 : return( DNDConstants::ACTION_NONE );
321 : }
322 :
323 :
324 :
325 0 : bool DropTargetHelper::IsDropFormatSupported( SotClipboardFormatId nFormat )
326 : {
327 0 : DataFlavorExVector::iterator aIter( mpFormats->begin() ), aEnd( mpFormats->end() );
328 0 : bool bRet = false;
329 :
330 0 : while( aIter != aEnd )
331 : {
332 0 : if( nFormat == (*aIter++).mnSotId )
333 : {
334 0 : bRet = true;
335 0 : aIter = aEnd;
336 : }
337 : }
338 :
339 0 : return bRet;
340 : }
341 :
342 :
343 :
344 0 : bool DropTargetHelper::IsDropFormatSupported( const DataFlavor& rFlavor )
345 : {
346 0 : DataFlavorExVector::iterator aIter( mpFormats->begin() ), aEnd( mpFormats->end() );
347 0 : bool bRet = false;
348 :
349 0 : while( aIter != aEnd )
350 : {
351 0 : if( TransferableDataHelper::IsEqual( rFlavor, *aIter++ ) )
352 : {
353 0 : bRet = true;
354 0 : aIter = aEnd;
355 : }
356 : }
357 :
358 0 : return bRet;
359 : }
360 :
361 :
362 : // TransferDataContainer
363 :
364 :
365 0 : struct TDataCntnrEntry_Impl
366 : {
367 : ::com::sun::star::uno::Any aAny;
368 : SotClipboardFormatId nId;
369 : };
370 :
371 :
372 :
373 : typedef ::std::list< TDataCntnrEntry_Impl > TDataCntnrEntryList;
374 :
375 :
376 :
377 : struct TransferDataContainer_Impl
378 : {
379 : TDataCntnrEntryList aFmtList;
380 : Link<> aFinshedLnk;
381 : INetBookmark* pBookmk;
382 : Graphic* pGrf;
383 :
384 0 : TransferDataContainer_Impl()
385 0 : : pBookmk( 0 ), pGrf( 0 )
386 : {
387 0 : }
388 :
389 0 : ~TransferDataContainer_Impl()
390 0 : {
391 0 : delete pBookmk;
392 0 : delete pGrf;
393 0 : }
394 : };
395 :
396 :
397 :
398 0 : TransferDataContainer::TransferDataContainer()
399 0 : : pImpl( new TransferDataContainer_Impl )
400 : {
401 0 : }
402 :
403 :
404 :
405 0 : TransferDataContainer::~TransferDataContainer()
406 : {
407 0 : delete pImpl;
408 0 : }
409 :
410 :
411 :
412 0 : void TransferDataContainer::AddSupportedFormats()
413 : {
414 0 : }
415 :
416 :
417 :
418 0 : bool TransferDataContainer::GetData(
419 : const css::datatransfer::DataFlavor& rFlavor, const OUString& /*rDestDoc*/ )
420 : {
421 0 : TDataCntnrEntryList::iterator aIter( pImpl->aFmtList.begin() ),
422 0 : aEnd( pImpl->aFmtList.end() );
423 0 : bool bFnd = false;
424 0 : SotClipboardFormatId nFmtId = SotExchange::GetFormat( rFlavor );
425 :
426 : // test first the list
427 0 : for( ; aIter != aEnd; ++aIter )
428 : {
429 0 : TDataCntnrEntry_Impl& rEntry = (TDataCntnrEntry_Impl&)*aIter;
430 0 : if( nFmtId == rEntry.nId )
431 : {
432 0 : bFnd = SetAny( rEntry.aAny, rFlavor );
433 0 : break;
434 : }
435 : }
436 :
437 : // test second the bookmark pointer
438 0 : if( !bFnd )
439 0 : switch( nFmtId )
440 : {
441 : case SotClipboardFormatId::STRING:
442 : case SotClipboardFormatId::SOLK:
443 : case SotClipboardFormatId::NETSCAPE_BOOKMARK:
444 : case SotClipboardFormatId::FILECONTENT:
445 : case SotClipboardFormatId::FILEGRPDESCRIPTOR:
446 : case SotClipboardFormatId::UNIFORMRESOURCELOCATOR:
447 0 : if( pImpl->pBookmk )
448 0 : bFnd = SetINetBookmark( *pImpl->pBookmk, rFlavor );
449 0 : break;
450 :
451 : case SotClipboardFormatId::SVXB:
452 : case SotClipboardFormatId::PNG:
453 : case SotClipboardFormatId::BITMAP:
454 : case SotClipboardFormatId::GDIMETAFILE:
455 0 : if( pImpl->pGrf )
456 0 : bFnd = SetGraphic( *pImpl->pGrf, rFlavor );
457 0 : break;
458 0 : default: break;
459 : }
460 :
461 0 : return bFnd;
462 : }
463 :
464 :
465 :
466 0 : void TransferDataContainer::CopyINetBookmark( const INetBookmark& rBkmk )
467 : {
468 0 : if( !pImpl->pBookmk )
469 0 : pImpl->pBookmk = new INetBookmark( rBkmk );
470 : else
471 0 : *pImpl->pBookmk = rBkmk;
472 :
473 0 : AddFormat( SotClipboardFormatId::STRING );
474 0 : AddFormat( SotClipboardFormatId::SOLK );
475 0 : AddFormat( SotClipboardFormatId::NETSCAPE_BOOKMARK );
476 0 : AddFormat( SotClipboardFormatId::FILECONTENT );
477 0 : AddFormat( SotClipboardFormatId::FILEGRPDESCRIPTOR );
478 0 : AddFormat( SotClipboardFormatId::UNIFORMRESOURCELOCATOR );
479 0 : }
480 :
481 :
482 :
483 0 : void TransferDataContainer::CopyAnyData( SotClipboardFormatId nFormatId,
484 : const sal_Char* pData, sal_uLong nLen )
485 : {
486 0 : if( nLen )
487 : {
488 0 : TDataCntnrEntry_Impl aEntry;
489 0 : aEntry.nId = nFormatId;
490 :
491 0 : Sequence< sal_Int8 > aSeq( nLen );
492 0 : memcpy( aSeq.getArray(), pData, nLen );
493 0 : aEntry.aAny <<= aSeq;
494 0 : pImpl->aFmtList.push_back( aEntry );
495 0 : AddFormat( nFormatId );
496 : }
497 0 : }
498 :
499 :
500 :
501 0 : void TransferDataContainer::CopyByteString( SotClipboardFormatId nFormatId,
502 : const OString& rStr )
503 : {
504 0 : CopyAnyData( nFormatId, rStr.getStr(), rStr.getLength() );
505 0 : }
506 :
507 :
508 :
509 0 : void TransferDataContainer::CopyINetImage( const INetImage& rINtImg )
510 : {
511 0 : SvMemoryStream aMemStm( 1024, 1024 );
512 0 : aMemStm.SetVersion( SOFFICE_FILEFORMAT_50 );
513 0 : rINtImg.Write( aMemStm, SotClipboardFormatId::INET_IMAGE );
514 0 : CopyAnyData( SotClipboardFormatId::INET_IMAGE, static_cast<sal_Char const *>(aMemStm.GetData()),
515 0 : aMemStm.Seek( STREAM_SEEK_TO_END ) );
516 0 : }
517 :
518 :
519 :
520 0 : void TransferDataContainer::CopyImageMap( const ImageMap& rImgMap )
521 : {
522 0 : SvMemoryStream aMemStm( 8192, 8192 );
523 0 : aMemStm.SetVersion( SOFFICE_FILEFORMAT_50 );
524 0 : rImgMap.Write( aMemStm, OUString() );
525 0 : CopyAnyData( SotClipboardFormatId::SVIM, static_cast<sal_Char const *>(aMemStm.GetData()),
526 0 : aMemStm.Seek( STREAM_SEEK_TO_END ) );
527 0 : }
528 :
529 :
530 :
531 0 : void TransferDataContainer::CopyGraphic( const Graphic& rGrf )
532 : {
533 0 : GraphicType nType = rGrf.GetType();
534 0 : if( GRAPHIC_NONE != nType )
535 : {
536 0 : if( !pImpl->pGrf )
537 0 : pImpl->pGrf = new Graphic( rGrf );
538 : else
539 0 : *pImpl->pGrf = rGrf;
540 :
541 0 : AddFormat( SotClipboardFormatId::SVXB );
542 :
543 0 : if( GRAPHIC_BITMAP == nType )
544 : {
545 0 : AddFormat( SotClipboardFormatId::PNG );
546 0 : AddFormat( SotClipboardFormatId::BITMAP );
547 : }
548 0 : else if( GRAPHIC_GDIMETAFILE == nType )
549 : {
550 0 : AddFormat( SotClipboardFormatId::GDIMETAFILE );
551 : }
552 : }
553 0 : }
554 :
555 :
556 :
557 0 : void TransferDataContainer::CopyString( SotClipboardFormatId nFmt, const OUString& rStr )
558 : {
559 0 : if( !rStr.isEmpty() )
560 : {
561 0 : TDataCntnrEntry_Impl aEntry;
562 0 : aEntry.nId = nFmt;
563 0 : OUString aStr( rStr );
564 0 : aEntry.aAny <<= aStr;
565 0 : pImpl->aFmtList.push_back( aEntry );
566 0 : AddFormat( aEntry.nId );
567 : }
568 0 : }
569 :
570 :
571 :
572 0 : void TransferDataContainer::CopyString( const OUString& rStr )
573 : {
574 0 : CopyString( SotClipboardFormatId::STRING, rStr );
575 0 : }
576 :
577 :
578 :
579 0 : void TransferDataContainer::CopyAny( SotClipboardFormatId nFmt,
580 : const ::com::sun::star::uno::Any& rAny )
581 : {
582 0 : TDataCntnrEntry_Impl aEntry;
583 0 : aEntry.nId = nFmt;
584 0 : aEntry.aAny = rAny;
585 0 : pImpl->aFmtList.push_back( aEntry );
586 0 : AddFormat( aEntry.nId );
587 0 : }
588 :
589 :
590 :
591 0 : bool TransferDataContainer::HasAnyData() const
592 : {
593 0 : return pImpl->aFmtList.begin() != pImpl->aFmtList.end() ||
594 0 : 0 != pImpl->pBookmk;
595 : }
596 :
597 :
598 :
599 0 : void TransferDataContainer::StartDrag(
600 : vcl::Window* pWindow, sal_Int8 nDragSourceActions,
601 : const Link<>& rLnk, sal_Int32 nDragPointer, sal_Int32 nDragImage )
602 : {
603 0 : pImpl->aFinshedLnk = rLnk;
604 : TransferableHelper::StartDrag( pWindow, nDragSourceActions,
605 0 : nDragPointer, nDragImage );
606 0 : }
607 :
608 :
609 :
610 0 : void TransferDataContainer::DragFinished( sal_Int8 nDropAction )
611 : {
612 0 : if( pImpl->aFinshedLnk.IsSet() )
613 0 : pImpl->aFinshedLnk.Call( &nDropAction );
614 0 : }
615 :
616 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|