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 <View.hxx>
21
22 #include <vector>
23 #include <com/sun/star/embed/XEmbedPersist.hpp>
24 #include <com/sun/star/embed/XEmbeddedObject.hpp>
25 #include <comphelper/sequenceashashmap.hxx>
26 #include <tools/urlobj.hxx>
27 #include <svx/svdoole2.hxx>
28 #include <svx/svxdlg.hxx>
29 #include <sfx2/docfile.hxx>
30 #include <svx/svdundo.hxx>
31 #include <svx/svdpagv.hxx>
32 #include <svl/urlbmk.hxx>
33 #include <editeng/outliner.hxx>
34 #include <svx/xflclit.hxx>
35 #include <sot/formats.hxx>
36 #include <editeng/editeng.hxx>
37
38 #include <svtools/embedtransfer.hxx>
39 #include <tools/debug.hxx>
40
41 #include <anminfo.hxx>
42 #include <strings.hrc>
43 #include <sdxfer.hxx>
44 #include <sdresid.hxx>
45 #include <sdmod.hxx>
46 #include <sdtreelb.hxx>
47 #include <DrawViewShell.hxx>
48 #include <DrawDocShell.hxx>
49 #include <fudraw.hxx>
50 #include <drawdoc.hxx>
51 #include <Window.hxx>
52 #include <sdpage.hxx>
53 #include <unoaprms.hxx>
54 #include <helpids.h>
55 #include <vcl/svapp.hxx>
56
57 #include <slideshow.hxx>
58 #include <memory>
59
60 namespace sd {
61
62 using namespace ::com::sun::star;
63
64 namespace {
65
66 struct SdNavigatorDropEvent : public ExecuteDropEvent
67 {
68 VclPtr< ::sd::Window> mpTargetWindow;
69
SdNavigatorDropEventsd::__anon14632cd70111::SdNavigatorDropEvent70 SdNavigatorDropEvent (
71 const ExecuteDropEvent& rEvt,
72 ::sd::Window* pTargetWindow )
73 : ExecuteDropEvent( rEvt ),
74 mpTargetWindow( pTargetWindow )
75 {}
76 };
77
78 }
79
CreateClipboardDataObject()80 css::uno::Reference< css::datatransfer::XTransferable > View::CreateClipboardDataObject()
81 {
82 // since SdTransferable::CopyToClipboard is called, this
83 // dynamically created object is destroyed automatically
84 rtl::Reference<SdTransferable> pTransferable = new SdTransferable( &mrDoc, nullptr, false );
85
86 SD_MOD()->pTransferClip = pTransferable.get();
87
88 mrDoc.CreatingDataObj( pTransferable.get() );
89 pTransferable->SetWorkDocument( static_cast<SdDrawDocument*>(CreateMarkedObjModel().release()) );
90 mrDoc.CreatingDataObj( nullptr );
91
92 // #112978# need to use GetAllMarkedBoundRect instead of GetAllMarkedRect to get
93 // fat lines correctly
94 const ::tools::Rectangle aMarkRect( GetAllMarkedBoundRect() );
95 std::unique_ptr<TransferableObjectDescriptor> pObjDesc(new TransferableObjectDescriptor);
96 SdrOle2Obj* pSdrOleObj = nullptr;
97 SdrPageView* pPgView = GetSdrPageView();
98 SdPage* pOldPage = pPgView ? static_cast<SdPage*>( pPgView->GetPage() ) : nullptr;
99 SdPage* pNewPage = const_cast<SdPage*>(static_cast<const SdPage*>( pTransferable->GetWorkDocument()->GetPage( 0 ) ));
100
101 if( pOldPage )
102 {
103 pNewPage->SetSize( pOldPage->GetSize() );
104 pNewPage->SetLayoutName( pOldPage->GetLayoutName() );
105 }
106
107 const SdrMarkList& rMarkList = GetMarkedObjectList();
108 if( rMarkList.GetMarkCount() == 1 )
109 {
110 SdrObject* pObj = rMarkList.GetMark(0)->GetMarkedSdrObj();
111
112 if( auto pOle2Obj = dynamic_cast<SdrOle2Obj *>( pObj ) )
113 if( pOle2Obj->GetObjRef() )
114 {
115 // If object has no persistence it must be copied as part of the document
116 try
117 {
118 uno::Reference< embed::XEmbedPersist > xPersObj( pOle2Obj->GetObjRef(), uno::UNO_QUERY );
119 if ( xPersObj.is() && xPersObj->hasEntry() )
120 pSdrOleObj = pOle2Obj;
121 }
122 catch( uno::Exception& )
123 {}
124 }
125 }
126
127 if( pSdrOleObj )
128 SvEmbedTransferHelper::FillTransferableObjectDescriptor( *pObjDesc, pSdrOleObj->GetObjRef(), pSdrOleObj->GetGraphic(), pSdrOleObj->GetAspect() );
129 else
130 pTransferable->GetWorkDocument()->GetDocSh()->FillTransferableObjectDescriptor( *pObjDesc );
131
132 if( mpDocSh )
133 pObjDesc->maDisplayName = mpDocSh->GetMedium()->GetURLObject().GetURLNoPass();
134
135 pObjDesc->maSize = aMarkRect.GetSize();
136
137 pTransferable->SetStartPos( aMarkRect.TopLeft() );
138 pTransferable->SetObjectDescriptor( std::move(pObjDesc) );
139 pTransferable->CopyToClipboard( mpViewSh->GetActiveWindow() );
140
141 return pTransferable;
142 }
143
CreateDragDataObject(View * pWorkView,vcl::Window & rWindow,const Point & rDragPos)144 css::uno::Reference< css::datatransfer::XTransferable > View::CreateDragDataObject( View* pWorkView, vcl::Window& rWindow, const Point& rDragPos )
145 {
146 rtl::Reference<SdTransferable> pTransferable = new SdTransferable( &mrDoc, pWorkView, false );
147
148 SD_MOD()->pTransferDrag = pTransferable.get();
149
150 std::unique_ptr<TransferableObjectDescriptor> pObjDesc(new TransferableObjectDescriptor);
151 OUString aDisplayName;
152 SdrOle2Obj* pSdrOleObj = nullptr;
153
154 const SdrMarkList& rMarkList = GetMarkedObjectList();
155 if( rMarkList.GetMarkCount() == 1 )
156 {
157 SdrObject* pObj = rMarkList.GetMark(0)->GetMarkedSdrObj();
158
159 if( auto pOle2Obj = dynamic_cast<SdrOle2Obj *>( pObj ) )
160 if( pOle2Obj->GetObjRef() )
161 {
162 // If object has no persistence it must be copied as part of the document
163 try
164 {
165 uno::Reference< embed::XEmbedPersist > xPersObj( pOle2Obj->GetObjRef(), uno::UNO_QUERY );
166 if ( xPersObj.is() && xPersObj->hasEntry() )
167 pSdrOleObj = pOle2Obj;
168 }
169 catch( uno::Exception& )
170 {}
171 }
172 }
173
174 if( mpDocSh )
175 aDisplayName = mpDocSh->GetMedium()->GetURLObject().GetURLNoPass();
176
177 if( pSdrOleObj )
178 SvEmbedTransferHelper::FillTransferableObjectDescriptor( *pObjDesc, pSdrOleObj->GetObjRef(), pSdrOleObj->GetGraphic(), pSdrOleObj->GetAspect() );
179 else if (mpDocSh)
180 mpDocSh->FillTransferableObjectDescriptor( *pObjDesc );
181
182 pObjDesc->maSize = GetAllMarkedRect().GetSize();
183 pObjDesc->maDragStartPos = rDragPos;
184 pObjDesc->maDisplayName = aDisplayName;
185
186 pTransferable->SetStartPos( rDragPos );
187 pTransferable->SetObjectDescriptor( std::move(pObjDesc) );
188 pTransferable->StartDrag( &rWindow, DND_ACTION_COPYMOVE | DND_ACTION_LINK );
189
190 return pTransferable;
191 }
192
CreateSelectionDataObject(View * pWorkView)193 css::uno::Reference< css::datatransfer::XTransferable > View::CreateSelectionDataObject( View* pWorkView )
194 {
195 rtl::Reference<SdTransferable> pTransferable = new SdTransferable( &mrDoc, pWorkView, true );
196 std::unique_ptr<TransferableObjectDescriptor> pObjDesc(new TransferableObjectDescriptor);
197 const ::tools::Rectangle aMarkRect( GetAllMarkedRect() );
198
199 SD_MOD()->pTransferSelection = pTransferable.get();
200
201 if( mpDocSh )
202 {
203 mpDocSh->FillTransferableObjectDescriptor( *pObjDesc );
204 pObjDesc->maDisplayName = mpDocSh->GetMedium()->GetURLObject().GetURLNoPass();
205 }
206
207 pObjDesc->maSize = aMarkRect.GetSize();
208
209 pTransferable->SetStartPos( aMarkRect.TopLeft() );
210 pTransferable->SetObjectDescriptor( std::move(pObjDesc) );
211 pTransferable->CopyToPrimarySelection();
212
213 return pTransferable;
214 }
215
UpdateSelectionClipboard()216 void View::UpdateSelectionClipboard() // false case
217 {
218 if (!mpViewSh)
219 return;
220 if (!mpViewSh->GetActiveWindow())
221 return;
222 const SdrMarkList& rMarkList = GetMarkedObjectList();
223 if (rMarkList.GetMarkCount())
224 CreateSelectionDataObject( this );
225 else
226 ClearSelectionClipboard();
227 }
228
ClearSelectionClipboard()229 void View::ClearSelectionClipboard() // true case
230 {
231 if (!mpViewSh)
232 return;
233 if (!mpViewSh->GetActiveWindow())
234 return;
235 if (SD_MOD()->pTransferSelection && SD_MOD()->pTransferSelection->GetView() == this)
236 {
237 TransferableHelper::ClearPrimarySelection();
238 SD_MOD()->pTransferSelection = nullptr;
239 }
240 }
241
DoCut()242 void View::DoCut()
243 {
244 const OutlinerView* pOLV = GetTextEditOutlinerView();
245
246 const SdrMarkList& rMarkList = GetMarkedObjectList();
247 if( pOLV )
248 const_cast<OutlinerView*>(pOLV)->Cut();
249 else if( rMarkList.GetMarkCount() != 0 )
250 {
251 OUString aStr(SdResId(STR_UNDO_CUT));
252
253 DoCopy();
254 BegUndo(aStr + " " + rMarkList.GetMarkDescription());
255 DeleteMarked();
256 EndUndo();
257 }
258 }
259
DoCopy()260 void View::DoCopy()
261 {
262 const OutlinerView* pOLV = GetTextEditOutlinerView();
263
264 const SdrMarkList& rMarkList = GetMarkedObjectList();
265 if( pOLV )
266 const_cast<OutlinerView*>(pOLV)->Copy();
267 else if( rMarkList.GetMarkCount() != 0 )
268 {
269 BrkAction();
270 CreateClipboardDataObject();
271 }
272 }
273
DoPaste(::sd::Window * pWindow)274 void View::DoPaste (::sd::Window* pWindow)
275 {
276 TransferableDataHelper aDataHelper( TransferableDataHelper::CreateFromSystemClipboard( mpViewSh->GetActiveWindow() ) );
277 if( !aDataHelper.GetTransferable().is() )
278 return; // empty clipboard?
279
280 const OutlinerView* pOLV = GetTextEditOutlinerView();
281
282 if( pOLV && EditEngine::HasValidData( aDataHelper.GetTransferable() ) )
283 {
284 const_cast< OutlinerView* >(pOLV)->PasteSpecial();
285
286 SdrObject* pObj = GetTextEditObject();
287 SdPage* pPage = static_cast<SdPage*>( pObj ? pObj->getSdrPageFromSdrObject() : nullptr );
288 ::Outliner* pOutliner = pOLV->GetOutliner();
289
290 if( pOutliner)
291 {
292 if( pObj && pPage && pPage->GetPresObjKind(pObj) == PresObjKind::Title )
293 {
294 // remove all hard linebreaks from the title
295 if (pOutliner->GetParagraphCount() > 1)
296 {
297 bool bOldUpdateMode = pOutliner->SetUpdateLayout( false );
298
299 const EditEngine& rEdit = pOutliner->GetEditEngine();
300 const sal_Int32 nParaCount = rEdit.GetParagraphCount();
301
302 for( sal_Int32 nPara = nParaCount - 2; nPara >= 0; nPara-- )
303 {
304 const sal_Int32 nParaLen = rEdit.GetTextLen( nPara );
305 pOutliner->QuickDelete( ESelection( nPara, nParaLen, nPara+1, 0 ) );
306 pOutliner->QuickInsertLineBreak( ESelection( nPara, nParaLen, nPara, nParaLen ) );
307 }
308
309 DBG_ASSERT( rEdit.GetParagraphCount() <= 1, "Titleobject contains hard line breaks" );
310 pOutliner->SetUpdateLayout(bOldUpdateMode);
311 }
312 }
313
314 if( !mrDoc.IsChanged() )
315 {
316 if (pOutliner->IsModified())
317 mrDoc.SetChanged();
318 }
319 }
320 }
321 else
322 {
323 Point aPos = pWindow->GetVisibleCenter();
324 DrawViewShell* pDrViewSh = static_cast<DrawViewShell*>( mpDocSh->GetViewShell() );
325
326 if (pDrViewSh != nullptr)
327 {
328 sal_Int8 nDnDAction = DND_ACTION_COPY;
329 if( !InsertData( aDataHelper, aPos, nDnDAction, false ) )
330 {
331 INetBookmark aINetBookmark( u""_ustr, u""_ustr );
332
333 if( ( aDataHelper.HasFormat( SotClipboardFormatId::NETSCAPE_BOOKMARK ) &&
334 aDataHelper.GetINetBookmark( SotClipboardFormatId::NETSCAPE_BOOKMARK, aINetBookmark ) ) ||
335 ( aDataHelper.HasFormat( SotClipboardFormatId::FILEGRPDESCRIPTOR ) &&
336 aDataHelper.GetINetBookmark( SotClipboardFormatId::FILEGRPDESCRIPTOR, aINetBookmark ) ) ||
337 ( aDataHelper.HasFormat( SotClipboardFormatId::UNIFORMRESOURCELOCATOR ) &&
338 aDataHelper.GetINetBookmark( SotClipboardFormatId::UNIFORMRESOURCELOCATOR, aINetBookmark ) ) )
339 {
340 pDrViewSh->InsertURLField( aINetBookmark.GetURL(), aINetBookmark.GetDescription(), u""_ustr );
341 }
342 }
343 }
344 }
345 }
346
StartDrag(const Point & rStartPos,vcl::Window * pWindow)347 void View::StartDrag( const Point& rStartPos, vcl::Window* pWindow )
348 {
349 const SdrMarkList& rMarkList = GetMarkedObjectList();
350 if (rMarkList.GetMarkCount() == 0 || !IsAction() || !mpViewSh || !pWindow)
351 return;
352
353 BrkAction();
354
355 if( IsTextEdit() )
356 SdrEndTextEdit();
357
358 if (DrawViewShell* pDrawViewShell = dynamic_cast<DrawViewShell*>(mpDocSh ? mpDocSh->GetViewShell() : nullptr))
359 {
360 const rtl::Reference<FuPoor>& xFunction(pDrawViewShell->GetCurrentFunction());
361 if (FuDraw* pFunction = dynamic_cast<FuDraw*>(xFunction.get()))
362 pFunction->ForcePointer();
363 }
364
365 mpDragSrcMarkList.reset( new SdrMarkList(GetMarkedObjectList()) );
366 mnDragSrcPgNum = GetSdrPageView()->GetPage()->GetPageNum();
367
368 CreateDragDataObject( this, *pWindow, rStartPos );
369 }
370
DragFinished(sal_Int8 nDropAction)371 void View::DragFinished( sal_Int8 nDropAction )
372 {
373 const bool bUndo = IsUndoEnabled();
374 const bool bGroupUndo = bUndo && mpDragSrcMarkList;
375 if (bGroupUndo)
376 {
377 OUString aStr(SdResId(STR_UNDO_DRAGDROP));
378 BegUndo(aStr + " " + mpDragSrcMarkList->GetMarkDescription());
379 }
380
381 SdTransferable* pDragTransferable = SD_MOD()->pTransferDrag;
382
383 if( pDragTransferable )
384 pDragTransferable->SetView( nullptr );
385
386 if( ( nDropAction & DND_ACTION_MOVE ) &&
387 pDragTransferable && !pDragTransferable->IsInternalMove() &&
388 mpDragSrcMarkList && mpDragSrcMarkList->GetMarkCount() &&
389 !IsPresObjSelected() )
390 {
391 mpDragSrcMarkList->ForceSort();
392
393 if( bUndo )
394 BegUndo();
395
396 const size_t nCnt = mpDragSrcMarkList->GetMarkCount();
397
398 for( size_t nm = nCnt; nm>0; )
399 {
400 --nm;
401 SdrMark* pM=mpDragSrcMarkList->GetMark(nm);
402 if( bUndo )
403 AddUndo(mrDoc.GetSdrUndoFactory().CreateUndoDeleteObject(*pM->GetMarkedSdrObj()));
404 }
405
406 mpDragSrcMarkList->GetMark(0)->GetMarkedSdrObj()->GetOrdNum();
407
408 for (size_t nm = nCnt; nm>0;)
409 {
410 --nm;
411 SdrMark* pM=mpDragSrcMarkList->GetMark(nm);
412 SdrObject* pObj=pM->GetMarkedSdrObj();
413
414 if( pObj && pObj->getSdrPageFromSdrObject() )
415 {
416 const size_t nOrdNum = pObj->GetOrdNumDirect();
417 rtl::Reference<SdrObject> pChkObj = pObj->getSdrPageFromSdrObject()->RemoveObject(nOrdNum);
418 DBG_ASSERT(pChkObj.get()==pObj,"pChkObj!=pObj in RemoveObject()");
419 }
420 }
421
422 if( bUndo )
423 EndUndo();
424 }
425
426 if( pDragTransferable )
427 pDragTransferable->SetInternalMove( false );
428
429 if (bGroupUndo)
430 EndUndo();
431 mnDragSrcPgNum = SDRPAGE_NOTFOUND;
432 mpDragSrcMarkList.reset();
433 }
434
AcceptDrop(const AcceptDropEvent & rEvt,DropTargetHelper & rTargetHelper,SdrLayerID nLayer)435 sal_Int8 View::AcceptDrop( const AcceptDropEvent& rEvt, DropTargetHelper& rTargetHelper,
436 SdrLayerID nLayer )
437 {
438 OUString aLayerName = GetActiveLayer();
439 SdrPageView* pPV = GetSdrPageView();
440 sal_Int8 nDropAction = rEvt.mnAction;
441 sal_Int8 nRet = DND_ACTION_NONE;
442
443 if( nLayer != SDRLAYER_NOTFOUND )
444 {
445 SdrLayerAdmin& rLayerAdmin = mrDoc.GetLayerAdmin();
446 SdrLayer* pLayer = rLayerAdmin.GetLayerPerID(nLayer);
447 assert(pLayer && "layer missing");
448 aLayerName = pLayer->GetName();
449 }
450
451 if( mbIsDropAllowed && !pPV->IsLayerLocked( aLayerName ) && pPV->IsLayerVisible( aLayerName ) )
452 {
453 const OutlinerView* pOLV = GetTextEditOutlinerView();
454 bool bIsInsideOutlinerView = false;
455
456 if( pOLV )
457 {
458 ::tools::Rectangle aRect( pOLV->GetOutputArea() );
459
460 const SdrMarkList& rMarkList = GetMarkedObjectList();
461 if (rMarkList.GetMarkCount() == 1)
462 {
463 SdrMark* pMark = rMarkList.GetMark(0);
464 SdrObject* pObj = pMark->GetMarkedSdrObj();
465 aRect.Union( pObj->GetLogicRect() );
466 }
467
468 if( aRect.Contains( pOLV->GetWindow()->PixelToLogic( rEvt.maPosPixel ) ) )
469 {
470 bIsInsideOutlinerView = true;
471 }
472 }
473
474 if( !bIsInsideOutlinerView )
475 {
476 SdTransferable* pDragTransferable = SD_MOD()->pTransferDrag;
477
478 if(pDragTransferable && (nDropAction & DND_ACTION_LINK))
479 {
480 // suppress own data when it's intention is to use it as fill information
481 pDragTransferable = nullptr;
482 }
483
484 if( pDragTransferable )
485 {
486 const View* pSourceView = pDragTransferable->GetView();
487
488 if( pDragTransferable->IsPageTransferable() )
489 {
490 nRet = DND_ACTION_COPY;
491 }
492 else if( pSourceView )
493 {
494 if( !( nDropAction & DND_ACTION_LINK ) ||
495 !pSourceView->GetDocSh()->GetMedium()->GetName().isEmpty() )
496 {
497 nRet = nDropAction;
498 }
499 }
500 }
501 else
502 {
503 const bool bDrawing = rTargetHelper.IsDropFormatSupported( SotClipboardFormatId::DRAWING );
504 const bool bGraphic = rTargetHelper.IsDropFormatSupported( SotClipboardFormatId::SVXB );
505 const bool bMtf = rTargetHelper.IsDropFormatSupported( SotClipboardFormatId::GDIMETAFILE );
506 const bool bBitmap = rTargetHelper.IsDropFormatSupported( SotClipboardFormatId::BITMAP );
507 bool bBookmark = rTargetHelper.IsDropFormatSupported( SotClipboardFormatId::NETSCAPE_BOOKMARK );
508 bool bXFillExchange = rTargetHelper.IsDropFormatSupported( SotClipboardFormatId::XFA );
509
510 // check handle insert
511 if ((bXFillExchange && (SdrDragMode::Gradient == GetDragMode()))
512 || (SdrDragMode::Transparence == GetDragMode()))
513 {
514 const SdrHdlList& rHdlList = GetHdlList();
515
516 for( size_t n = 0; n < rHdlList.GetHdlCount(); ++n )
517 {
518 SdrHdl* pIAOHandle = rHdlList.GetHdl( n );
519
520 if( pIAOHandle && ( SdrHdlKind::Color == pIAOHandle->GetKind() ) )
521 {
522 if(pIAOHandle->getOverlayObjectList().isHitPixel(rEvt.maPosPixel))
523 {
524 nRet = nDropAction;
525 static_cast< SdrHdlColor* >( pIAOHandle )->SetSize( SDR_HANDLE_COLOR_SIZE_SELECTED );
526 }
527 else
528 {
529 static_cast< SdrHdlColor* >( pIAOHandle )->SetSize( SDR_HANDLE_COLOR_SIZE_NORMAL );
530 }
531 }
532 }
533 }
534
535 // check object insert
536 if( !nRet && ( bXFillExchange || ( ( bDrawing || bGraphic || bMtf || bBitmap || bBookmark ) && ( nDropAction & DND_ACTION_LINK ) ) ) )
537 {
538 SdrPageView* pPageView = nullptr;
539 ::sd::Window* pWindow = mpViewSh->GetActiveWindow();
540 Point aPos( pWindow->PixelToLogic( rEvt.maPosPixel ) );
541 SdrObject* pPickObj = PickObj(aPos, getHitTolLog(), pPageView);
542 bool bIsPresTarget = false;
543
544 if (pPickObj && (pPickObj->IsEmptyPresObj() || pPickObj->GetUserCall()))
545 {
546 SdPage* pPage = static_cast<SdPage*>( pPickObj->getSdrPageFromSdrObject() );
547
548 if( pPage && pPage->IsMasterPage() )
549 bIsPresTarget = pPage->IsPresObj( pPickObj );
550 }
551
552 if (pPickObj && !bIsPresTarget && (bGraphic || bMtf || bBitmap || bXFillExchange))
553 {
554 if( mpDropMarkerObj != pPickObj )
555 {
556 mpDropMarkerObj = pPickObj;
557 ImplClearDrawDropMarker();
558
559 if(mpDropMarkerObj)
560 {
561 mpDropMarker.reset( new SdrDropMarkerOverlay(*this, *mpDropMarkerObj) );
562 }
563 }
564
565 nRet = nDropAction;
566 }
567 else
568 bXFillExchange = false;
569 }
570
571 // check normal insert
572 if( !nRet )
573 {
574 const bool bSBAFormat = rTargetHelper.IsDropFormatSupported( SotClipboardFormatId::SVX_FORMFIELDEXCH );
575 const bool bEditEngineODF = rTargetHelper.IsDropFormatSupported( SotClipboardFormatId::EDITENGINE_ODF_TEXT_FLAT );
576 const bool bString = rTargetHelper.IsDropFormatSupported( SotClipboardFormatId::STRING );
577 const bool bRTF = rTargetHelper.IsDropFormatSupported( SotClipboardFormatId::RTF );
578 const bool bFile = rTargetHelper.IsDropFormatSupported( SotClipboardFormatId::SIMPLE_FILE );
579 const bool bFileList = rTargetHelper.IsDropFormatSupported( SotClipboardFormatId::FILE_LIST );
580
581 if( mpDropMarker )
582 {
583 ImplClearDrawDropMarker();
584 mpDropMarkerObj = nullptr;
585 }
586
587 if( bBookmark && bFile && ( nDropAction & DND_ACTION_MOVE ) && mpViewSh
588 && ( SlideShow::IsRunning(mpViewSh->GetViewShellBase())
589 && !SlideShow::IsInteractiveSlideshow(&mpViewSh->GetViewShellBase()) )) // IASS
590 bBookmark = false;
591
592 if( bDrawing || bGraphic || bMtf || bBitmap || bBookmark || bFile || bFileList || bXFillExchange || bSBAFormat || bEditEngineODF || bString || bRTF )
593 nRet = nDropAction;
594
595 // For entries from the navigator, change action copy.
596 if (bBookmark
597 && rTargetHelper.IsDropFormatSupported(
598 SdPageObjsTLV::SdPageObjsTransferable::GetListBoxDropFormatId())
599 && (nDropAction & DND_ACTION_MOVE)!=0)
600 {
601 nRet = DND_ACTION_COPY;
602 }
603 }
604 }
605 }
606 }
607
608 // destroy drop marker if this is a leaving event
609 if( rEvt.mbLeaving && mpDropMarker )
610 {
611 ImplClearDrawDropMarker();
612 mpDropMarkerObj = nullptr;
613 }
614
615 return nRet;
616 }
617
ExecuteDrop(const ExecuteDropEvent & rEvt,::sd::Window * pTargetWindow,sal_uInt16 nPage,SdrLayerID nLayer)618 sal_Int8 View::ExecuteDrop( const ExecuteDropEvent& rEvt,
619 ::sd::Window* pTargetWindow, sal_uInt16 nPage, SdrLayerID nLayer )
620 {
621 SdrPageView* pPV = GetSdrPageView();
622 OUString aActiveLayer = GetActiveLayer();
623 sal_Int8 nDropAction = rEvt.mnAction;
624 sal_Int8 nRet = DND_ACTION_NONE;
625
626 // destroy drop marker if it is shown
627 if( mpDropMarker )
628 {
629 ImplClearDrawDropMarker();
630 mpDropMarkerObj = nullptr;
631 }
632
633 if( !pPV->IsLayerLocked( aActiveLayer ) )
634 {
635 const OutlinerView* pOLV = GetTextEditOutlinerView();
636 bool bIsInsideOutlinerView = false;
637
638 if( pOLV )
639 {
640 ::tools::Rectangle aRect( pOLV->GetOutputArea() );
641
642 const SdrMarkList& rMarkList = GetMarkedObjectList();
643 if( rMarkList.GetMarkCount() == 1 )
644 {
645 SdrMark* pMark = rMarkList.GetMark(0);
646 SdrObject* pObj = pMark->GetMarkedSdrObj();
647 aRect.Union( pObj->GetLogicRect() );
648 }
649
650 Point aPos( pOLV->GetWindow()->PixelToLogic( rEvt.maPosPixel ) );
651
652 if( aRect.Contains( aPos ) )
653 {
654 bIsInsideOutlinerView = true;
655 }
656 }
657
658 if( !bIsInsideOutlinerView )
659 {
660 Point aPos;
661 TransferableDataHelper aDataHelper( rEvt.maDropEvent.Transferable );
662
663 if( pTargetWindow )
664 aPos = pTargetWindow->PixelToLogic( rEvt.maPosPixel );
665
666 // handle insert?
667 if ((SdrDragMode::Gradient == GetDragMode())
668 || ((SdrDragMode::Transparence == GetDragMode())
669 && aDataHelper.HasFormat(SotClipboardFormatId::XFA)))
670 {
671 const SdrHdlList& rHdlList = GetHdlList();
672
673 for( size_t n = 0; !nRet && n < rHdlList.GetHdlCount(); ++n )
674 {
675 SdrHdl* pIAOHandle = rHdlList.GetHdl( n );
676
677 if( pIAOHandle && ( SdrHdlKind::Color == pIAOHandle->GetKind() ) )
678 {
679 if(pIAOHandle->getOverlayObjectList().isHitPixel(rEvt.maPosPixel))
680 {
681 uno::Any const data(aDataHelper.GetAny(SotClipboardFormatId::XFA, u""_ustr));
682 uno::Sequence<beans::NamedValue> props;
683 if (data >>= props)
684 {
685 ::comphelper::SequenceAsHashMap const map(props);
686 Color aColor(COL_BLACK);
687 auto const it = map.find(u"FillColor"_ustr);
688 if (it != map.end())
689 {
690 XFillColorItem color;
691 color.PutValue(it->second, 0);
692 aColor = color.GetColorValue();
693 }
694 static_cast< SdrHdlColor* >( pIAOHandle )->SetColor( aColor, true );
695 nRet = nDropAction;
696 }
697 }
698 }
699 }
700 }
701
702 // standard insert?
703 if( !nRet && InsertData( aDataHelper, aPos, nDropAction, true, SotClipboardFormatId::NONE, nPage, nLayer ) )
704 nRet = nDropAction;
705
706 // special insert?
707 if( !nRet && mpViewSh )
708 {
709 INetBookmark aINetBookmark( (OUString()), (OUString()) );
710
711 // insert bookmark
712 if( aDataHelper.HasFormat( SotClipboardFormatId::NETSCAPE_BOOKMARK ) &&
713 aDataHelper.GetINetBookmark( SotClipboardFormatId::NETSCAPE_BOOKMARK, aINetBookmark ) )
714 {
715 SdPageObjsTLV::SdPageObjsTransferable* pPageObjsTransferable = SdPageObjsTLV::SdPageObjsTransferable::getImplementation( aDataHelper.GetXTransferable() );
716
717 if( pPageObjsTransferable &&
718 ( NAVIGATOR_DRAGTYPE_LINK == pPageObjsTransferable->GetDragType() ||
719 NAVIGATOR_DRAGTYPE_EMBEDDED == pPageObjsTransferable->GetDragType() ) )
720 {
721 // insert bookmark from own navigator (handled async. due to possible message box )
722 Application::PostUserEvent( LINK( this, View, ExecuteNavigatorDrop ),
723 new SdNavigatorDropEvent( rEvt, pTargetWindow ) );
724 nRet = nDropAction;
725 }
726 else
727 {
728 SdrPageView* pPageView = nullptr;
729
730 SdrObject* pPickObj = PickObj(aPos, getHitTolLog(), pPageView);
731 if (pPickObj)
732 {
733 // insert as clip action => jump
734 OUString aBookmark( aINetBookmark.GetURL() );
735 SdAnimationInfo* pInfo = SdDrawDocument::GetAnimationInfo( pPickObj );
736
737 if( !aBookmark.isEmpty() )
738 {
739 bool bCreated = false;
740
741 presentation::ClickAction eClickAction = presentation::ClickAction_DOCUMENT;
742
743 sal_Int32 nIndex = aBookmark.indexOf( '#' );
744 if( nIndex != -1 )
745 {
746 const std::u16string_view aDocName( aBookmark.subView( 0, nIndex ) );
747
748 if (mpDocSh->GetMedium()->GetName() == aDocName || aDocName == mpDocSh->GetName())
749 {
750 // internal jump, only use the part after and including '#'
751 eClickAction = presentation::ClickAction_BOOKMARK;
752 aBookmark = aBookmark.copy( nIndex+1 );
753 }
754 }
755
756 if( !pInfo )
757 {
758 pInfo = SdDrawDocument::GetShapeUserData( *pPickObj, true );
759 bCreated = true;
760 }
761
762 // create undo action with old and new sizes
763 std::unique_ptr<SdAnimationPrmsUndoAction> pAction(new SdAnimationPrmsUndoAction(&mrDoc, pPickObj, bCreated));
764 pAction->SetActive(pInfo->mbActive, pInfo->mbActive);
765 pAction->SetEffect(pInfo->meEffect, pInfo->meEffect);
766 pAction->SetTextEffect(pInfo->meTextEffect, pInfo->meTextEffect);
767 pAction->SetSpeed(pInfo->meSpeed, pInfo->meSpeed);
768 pAction->SetDim(pInfo->mbDimPrevious, pInfo->mbDimPrevious);
769 pAction->SetDimColor(pInfo->maDimColor, pInfo->maDimColor);
770 pAction->SetDimHide(pInfo->mbDimHide, pInfo->mbDimHide);
771 pAction->SetSoundOn(pInfo->mbSoundOn, pInfo->mbSoundOn);
772 pAction->SetSound(pInfo->maSoundFile, pInfo->maSoundFile);
773 pAction->SetPlayFull(pInfo->mbPlayFull, pInfo->mbPlayFull);
774 pAction->SetClickAction(pInfo->meClickAction, eClickAction);
775 pAction->SetBookmark(pInfo->GetBookmark(), aBookmark);
776 pAction->SetVerb(pInfo->mnVerb, pInfo->mnVerb);
777 pAction->SetSecondEffect(pInfo->meSecondEffect, pInfo->meSecondEffect);
778 pAction->SetSecondSpeed(pInfo->meSecondSpeed, pInfo->meSecondSpeed);
779 pAction->SetSecondSoundOn(pInfo->mbSecondSoundOn, pInfo->mbSecondSoundOn);
780 pAction->SetSecondPlayFull(pInfo->mbSecondPlayFull, pInfo->mbSecondPlayFull);
781
782 OUString aString(SdResId(STR_UNDO_ANIMATION));
783 pAction->SetComment(aString);
784 mpDocSh->GetUndoManager()->AddUndoAction(std::move(pAction));
785 pInfo->meClickAction = eClickAction;
786 pInfo->SetBookmark( aBookmark );
787 mrDoc.SetChanged();
788
789 nRet = nDropAction;
790 }
791 }
792 else if( auto pDrawViewShell = dynamic_cast< DrawViewShell *>( mpViewSh ) )
793 {
794 // insert as normal URL button
795 pDrawViewShell->InsertURLButton( aINetBookmark.GetURL(), aINetBookmark.GetDescription(), OUString(), &aPos );
796 nRet = nDropAction;
797 }
798 }
799 }
800 }
801 }
802 }
803
804 return nRet;
805 }
806
IMPL_LINK(View,ExecuteNavigatorDrop,void *,p,void)807 IMPL_LINK( View, ExecuteNavigatorDrop, void*, p, void )
808 {
809 SdNavigatorDropEvent* pSdNavigatorDropEvent = static_cast<SdNavigatorDropEvent*>(p);
810 TransferableDataHelper aDataHelper( pSdNavigatorDropEvent->maDropEvent.Transferable );
811 SdPageObjsTLV::SdPageObjsTransferable* pPageObjsTransferable = SdPageObjsTLV::SdPageObjsTransferable::getImplementation( aDataHelper.GetXTransferable() );
812 INetBookmark aINetBookmark;
813
814 if( pPageObjsTransferable && aDataHelper.GetINetBookmark( SotClipboardFormatId::NETSCAPE_BOOKMARK, aINetBookmark ) )
815 {
816 Point aPos;
817 OUString aBookmark;
818 SdPage* pPage = static_cast<SdPage*>( GetSdrPageView()->GetPage() );
819 sal_uInt16 nPgPos = 0xFFFF;
820
821 if( pSdNavigatorDropEvent->mpTargetWindow )
822 aPos = pSdNavigatorDropEvent->mpTargetWindow->PixelToLogic( pSdNavigatorDropEvent->maPosPixel );
823
824 const OUString& aURL( aINetBookmark.GetURL() );
825 sal_Int32 nIndex = aURL.indexOf( '#' );
826 if( nIndex != -1 )
827 aBookmark = aURL.copy( nIndex+1 );
828
829 std::vector<OUString> aExchangeList;
830 std::vector<OUString> aBookmarkList(1,aBookmark);
831
832 if( !pPage->IsMasterPage() )
833 {
834 if( pPage->GetPageKind() == PageKind::Standard )
835 nPgPos = pPage->GetPageNum() + 2;
836 else if( pPage->GetPageKind() == PageKind::Notes )
837 nPgPos = pPage->GetPageNum() + 1;
838 }
839
840 /* In order t ensure unique page names, we test the ones we want to
841 insert. If necessary. we put them into and replacement list (bNameOK
842 == sal_False -> User canceled). */
843 bool bLink = pPageObjsTransferable->GetDragType() == NAVIGATOR_DRAGTYPE_LINK;
844 bool bNameOK = GetExchangeList( aExchangeList, aBookmarkList, 2 );
845
846 /* Since we don't know the type (page or object), we fill a list with
847 pages and objects.
848 Of course we have problems if there are pages and objects with the
849 same name!!! */
850 if( bNameOK )
851 {
852 mrDoc.InsertBookmark( aBookmarkList, aExchangeList,
853 bLink, nPgPos,
854 &pPageObjsTransferable->GetDocShell(),
855 &aPos );
856 }
857 }
858
859 delete pSdNavigatorDropEvent;
860 }
861
GetExchangeList(std::vector<OUString> & rExchangeList,std::vector<OUString> & rBookmarkList,const sal_uInt16 nType)862 bool View::GetExchangeList (std::vector<OUString> &rExchangeList,
863 std::vector<OUString> &rBookmarkList,
864 const sal_uInt16 nType)
865 {
866 assert(rExchangeList.empty());
867
868 bool bListIdentical = true; ///< Bookmark list and exchange list are identical
869 bool bNameOK = true; ///< name is unique
870
871 for ( const auto& rBookmark : rBookmarkList )
872 {
873 OUString aNewName = rBookmark;
874
875 if( nType == 0 || nType == 2 )
876 bNameOK = mpDocSh->CheckPageName(mpViewSh->GetFrameWeld(), aNewName);
877
878 if( bNameOK && ( nType == 1 || nType == 2 ) )
879 {
880 if( mrDoc.GetObj( aNewName ) )
881 {
882 OUString aTitle(SdResId(STR_TITLE_NAMEGROUP));
883 OUString aDesc(SdResId(STR_DESC_NAMEGROUP));
884
885 SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create();
886 ScopedVclPtr<AbstractSvxNameDialog> pDlg(pFact->CreateSvxNameDialog(mpViewSh->GetFrameWeld(), aNewName, aDesc));
887
888 pDlg->SetEditHelpId( HID_SD_NAMEDIALOG_OBJECT );
889
890 bNameOK = false;
891 pDlg->SetText( aTitle );
892
893 while( !bNameOK && pDlg->Execute() == RET_OK )
894 {
895 aNewName = pDlg->GetName();
896
897 if( !mrDoc.GetObj( aNewName ) )
898 bNameOK = true;
899 }
900 }
901 }
902
903 bListIdentical = rBookmark == aNewName;
904
905 rExchangeList.push_back(aNewName);
906
907 if (!bNameOK)
908 break;
909 }
910
911 // Exchange list is identical to bookmark list
912 if( !rExchangeList.empty() && bListIdentical )
913 rExchangeList.clear();
914
915 return bNameOK;
916 }
917
918 } // end of namespace sd
919
920 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
921