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 0 : DragSourceHelper::DragGestureListener::DragGestureListener( DragSourceHelper& rDragSourceHelper ) :
52 0 : mrParent( rDragSourceHelper )
53 : {
54 0 : }
55 :
56 :
57 :
58 0 : DragSourceHelper::DragGestureListener::~DragGestureListener()
59 : {
60 0 : }
61 :
62 :
63 :
64 0 : void SAL_CALL DragSourceHelper::DragGestureListener::disposing( const EventObject& ) throw( RuntimeException, std::exception )
65 : {
66 0 : }
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 0 : DragSourceHelper::DragSourceHelper( Window* pWindow ) :
83 0 : mxDragGestureRecognizer( pWindow->GetDragGestureRecognizer() )
84 : {
85 0 : if( mxDragGestureRecognizer.is() )
86 : {
87 0 : mxDragGestureListener = new DragSourceHelper::DragGestureListener( *this );
88 0 : mxDragGestureRecognizer->addDragGestureListener( mxDragGestureListener );
89 : }
90 0 : }
91 :
92 :
93 :
94 0 : DragSourceHelper::~DragSourceHelper()
95 : {
96 0 : if( mxDragGestureRecognizer.is() )
97 0 : mxDragGestureRecognizer->removeDragGestureListener( mxDragGestureListener );
98 0 : }
99 :
100 :
101 :
102 0 : void DragSourceHelper::StartDrag( sal_Int8, const Point& )
103 : {
104 0 : }
105 :
106 :
107 : // - DropTargetHelper::DropTargetListener -
108 :
109 :
110 0 : DropTargetHelper::DropTargetListener::DropTargetListener( DropTargetHelper& rDropTargetHelper ) :
111 : mrParent( rDropTargetHelper ),
112 0 : mpLastDragOverEvent( NULL )
113 : {
114 0 : }
115 :
116 :
117 :
118 0 : DropTargetHelper::DropTargetListener::~DropTargetListener()
119 : {
120 0 : delete mpLastDragOverEvent;
121 0 : }
122 :
123 :
124 :
125 0 : void SAL_CALL DropTargetHelper::DropTargetListener::disposing( const EventObject& ) throw( RuntimeException, std::exception )
126 : {
127 0 : }
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 0 : DropTargetHelper::DropTargetHelper( Window* pWindow ) :
257 0 : mxDropTarget( pWindow->GetDropTarget() ),
258 0 : mpFormats( new DataFlavorExVector )
259 : {
260 0 : ImplConstruct();
261 0 : }
262 :
263 :
264 :
265 0 : DropTargetHelper::DropTargetHelper( const Reference< XDropTarget >& rxDropTarget ) :
266 : mxDropTarget( rxDropTarget ),
267 0 : mpFormats( new DataFlavorExVector )
268 : {
269 0 : ImplConstruct();
270 0 : }
271 :
272 :
273 :
274 0 : DropTargetHelper::~DropTargetHelper()
275 : {
276 0 : if( mxDropTarget.is() )
277 0 : mxDropTarget->removeDropTargetListener( mxDropTargetListener );
278 :
279 0 : delete mpFormats;
280 0 : }
281 :
282 :
283 :
284 0 : void DropTargetHelper::ImplConstruct()
285 : {
286 0 : if( mxDropTarget.is() )
287 : {
288 0 : mxDropTargetListener = new DropTargetHelper::DropTargetListener( *this );
289 0 : mxDropTarget->addDropTargetListener( mxDropTargetListener );
290 0 : mxDropTarget->setActive( sal_True );
291 : }
292 0 : }
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( SotFormatStringId 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 : SotFormatStringId 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( const
419 : ::com::sun::star::datatransfer::DataFlavor& rFlavor )
420 : {
421 0 : TDataCntnrEntryList::iterator aIter( pImpl->aFmtList.begin() ),
422 0 : aEnd( pImpl->aFmtList.end() );
423 0 : bool bFnd = false;
424 0 : sal_uLong 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 SOT_FORMAT_STRING:
442 : case SOT_FORMATSTR_ID_SOLK:
443 : case SOT_FORMATSTR_ID_NETSCAPE_BOOKMARK:
444 : case SOT_FORMATSTR_ID_FILECONTENT:
445 : case SOT_FORMATSTR_ID_FILEGRPDESCRIPTOR:
446 : case SOT_FORMATSTR_ID_UNIFORMRESOURCELOCATOR:
447 0 : if( pImpl->pBookmk )
448 0 : bFnd = SetINetBookmark( *pImpl->pBookmk, rFlavor );
449 0 : break;
450 :
451 : case SOT_FORMATSTR_ID_SVXB:
452 : case SOT_FORMATSTR_ID_PNG:
453 : case SOT_FORMAT_BITMAP:
454 : case SOT_FORMAT_GDIMETAFILE:
455 0 : if( pImpl->pGrf )
456 0 : bFnd = SetGraphic( *pImpl->pGrf, rFlavor );
457 0 : break;
458 : }
459 :
460 0 : return bFnd;
461 : }
462 :
463 :
464 :
465 0 : void TransferDataContainer::CopyINetBookmark( const INetBookmark& rBkmk )
466 : {
467 0 : if( !pImpl->pBookmk )
468 0 : pImpl->pBookmk = new INetBookmark( rBkmk );
469 : else
470 0 : *pImpl->pBookmk = rBkmk;
471 :
472 0 : AddFormat( SOT_FORMAT_STRING );
473 0 : AddFormat( SOT_FORMATSTR_ID_SOLK );
474 0 : AddFormat( SOT_FORMATSTR_ID_NETSCAPE_BOOKMARK );
475 0 : AddFormat( SOT_FORMATSTR_ID_FILECONTENT );
476 0 : AddFormat( SOT_FORMATSTR_ID_FILEGRPDESCRIPTOR );
477 0 : AddFormat( SOT_FORMATSTR_ID_UNIFORMRESOURCELOCATOR );
478 0 : }
479 :
480 :
481 :
482 0 : void TransferDataContainer::CopyAnyData( sal_uLong nFormatId,
483 : const sal_Char* pData, sal_uLong nLen )
484 : {
485 0 : if( nLen )
486 : {
487 0 : TDataCntnrEntry_Impl aEntry;
488 0 : aEntry.nId = nFormatId;
489 :
490 0 : Sequence< sal_Int8 > aSeq( nLen );
491 0 : memcpy( aSeq.getArray(), pData, nLen );
492 0 : aEntry.aAny <<= aSeq;
493 0 : pImpl->aFmtList.push_back( aEntry );
494 0 : AddFormat( nFormatId );
495 : }
496 0 : }
497 :
498 :
499 :
500 0 : void TransferDataContainer::CopyByteString( sal_uLong nFormatId,
501 : const OString& rStr )
502 : {
503 0 : CopyAnyData( nFormatId, rStr.getStr(), rStr.getLength() );
504 0 : }
505 :
506 :
507 :
508 0 : void TransferDataContainer::CopyINetImage( const INetImage& rINtImg )
509 : {
510 0 : SvMemoryStream aMemStm( 1024, 1024 );
511 0 : aMemStm.SetVersion( SOFFICE_FILEFORMAT_50 );
512 0 : rINtImg.Write( aMemStm, SOT_FORMATSTR_ID_INET_IMAGE );
513 0 : CopyAnyData( SOT_FORMATSTR_ID_INET_IMAGE, (sal_Char*)aMemStm.GetData(),
514 0 : aMemStm.Seek( STREAM_SEEK_TO_END ) );
515 0 : }
516 :
517 :
518 :
519 0 : void TransferDataContainer::CopyImageMap( const ImageMap& rImgMap )
520 : {
521 0 : SvMemoryStream aMemStm( 8192, 8192 );
522 0 : aMemStm.SetVersion( SOFFICE_FILEFORMAT_50 );
523 0 : rImgMap.Write( aMemStm, OUString() );
524 0 : CopyAnyData( SOT_FORMATSTR_ID_SVIM, (sal_Char*)aMemStm.GetData(),
525 0 : aMemStm.Seek( STREAM_SEEK_TO_END ) );
526 0 : }
527 :
528 :
529 :
530 0 : void TransferDataContainer::CopyGraphic( const Graphic& rGrf )
531 : {
532 0 : GraphicType nType = rGrf.GetType();
533 0 : if( GRAPHIC_NONE != nType )
534 : {
535 0 : if( !pImpl->pGrf )
536 0 : pImpl->pGrf = new Graphic( rGrf );
537 : else
538 0 : *pImpl->pGrf = rGrf;
539 :
540 0 : AddFormat( SOT_FORMATSTR_ID_SVXB );
541 :
542 0 : if( GRAPHIC_BITMAP == nType )
543 : {
544 0 : AddFormat( SOT_FORMATSTR_ID_PNG );
545 0 : AddFormat( SOT_FORMAT_BITMAP );
546 : }
547 0 : else if( GRAPHIC_GDIMETAFILE == nType )
548 : {
549 0 : AddFormat( SOT_FORMAT_GDIMETAFILE );
550 : }
551 : }
552 0 : }
553 :
554 :
555 :
556 0 : void TransferDataContainer::CopyString( sal_uInt16 nFmt, const OUString& rStr )
557 : {
558 0 : if( !rStr.isEmpty() )
559 : {
560 0 : TDataCntnrEntry_Impl aEntry;
561 0 : aEntry.nId = nFmt;
562 0 : OUString aStr( rStr );
563 0 : aEntry.aAny <<= aStr;
564 0 : pImpl->aFmtList.push_back( aEntry );
565 0 : AddFormat( aEntry.nId );
566 : }
567 0 : }
568 :
569 :
570 :
571 0 : void TransferDataContainer::CopyString( const OUString& rStr )
572 : {
573 0 : CopyString( SOT_FORMAT_STRING, rStr );
574 0 : }
575 :
576 :
577 :
578 0 : void TransferDataContainer::CopyAny( sal_uInt16 nFmt,
579 : const ::com::sun::star::uno::Any& rAny )
580 : {
581 0 : TDataCntnrEntry_Impl aEntry;
582 0 : aEntry.nId = nFmt;
583 0 : aEntry.aAny = rAny;
584 0 : pImpl->aFmtList.push_back( aEntry );
585 0 : AddFormat( aEntry.nId );
586 0 : }
587 :
588 :
589 :
590 0 : bool TransferDataContainer::HasAnyData() const
591 : {
592 0 : return pImpl->aFmtList.begin() != pImpl->aFmtList.end() ||
593 0 : 0 != pImpl->pBookmk;
594 : }
595 :
596 :
597 :
598 0 : void TransferDataContainer::StartDrag(
599 : Window* pWindow, sal_Int8 nDragSourceActions,
600 : const Link& rLnk, sal_Int32 nDragPointer, sal_Int32 nDragImage )
601 : {
602 0 : pImpl->aFinshedLnk = rLnk;
603 : TransferableHelper::StartDrag( pWindow, nDragSourceActions,
604 0 : nDragPointer, nDragImage );
605 0 : }
606 :
607 :
608 :
609 0 : void TransferDataContainer::DragFinished( sal_Int8 nDropAction )
610 : {
611 0 : if( pImpl->aFinshedLnk.IsSet() )
612 0 : pImpl->aFinshedLnk.Call( &nDropAction );
613 0 : }
614 :
615 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|