xref: /core/sd/source/ui/view/sdview2.cxx (revision 5da4acd4)
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