1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <controller/SlsClipboard.hxx>
22 #include <SlideSorterViewShell.hxx>
23 #include <SlideSorter.hxx>
24 #include <model/SlideSorterModel.hxx>
25 #include <model/SlsPageDescriptor.hxx>
26 #include <model/SlsPageEnumerationProvider.hxx>
27 #include <view/SlideSorterView.hxx>
28 #include <view/SlsTheme.hxx>
29 #include <controller/SlideSorterController.hxx>
30 #include <controller/SlsInsertionIndicatorHandler.hxx>
31 #include <controller/SlsPageSelector.hxx>
32 #include <controller/SlsSelectionFunction.hxx>
33 #include <controller/SlsCurrentSlideManager.hxx>
34 #include <controller/SlsScrollBarManager.hxx>
35 #include <controller/SlsFocusManager.hxx>
36 #include <controller/SlsSelectionManager.hxx>
37 #include <controller/SlsTransferableData.hxx>
38 #include <controller/SlsSelectionObserver.hxx>
39 #include <controller/SlsVisibleAreaManager.hxx>
40 #include <cache/SlsPageCache.hxx>
42 #include <ViewShellBase.hxx>
44 #include <DrawViewShell.hxx>
48 #include <fucushow.hxx>
49 #include <fusldlg.hxx>
50 #include <fuexpand.hxx>
51 #include <fusumry.hxx>
53 #include <strings.hrc>
54 #include <sdresid.hxx>
57 #include <ins_paste.hxx>
58 #include <drawdoc.hxx>
59 #include <DrawDocShell.hxx>
61 #include <sdtreelb.hxx>
63 #include <com/sun/star/datatransfer/dnd/DNDConstants.hpp>
64 #include <sfx2/request.hxx>
65 #include <sfx2/viewfrm.hxx>
66 #include <sfx2/bindings.hxx>
67 #include <sfx2/docfile.hxx>
68 #include <svx/svxids.hrc>
69 #include <tools/urlobj.hxx>
70 #include <rtl/ustring.hxx>
71 #include <vcl/svapp.hxx>
73 namespace sd
{ namespace slidesorter
{ namespace controller
{
76 /** Temporarily deactivate slide tracking of the VisibleAreaManager.
77 This is used as a workaround to avoid unwanted repositioning of
78 the visible area when the selection of slides is copied to the
79 clipboard (cloning of slides leads to model change notifications
80 for the original model.)
82 class TemporarySlideTrackingDeactivator
85 explicit TemporarySlideTrackingDeactivator (SlideSorterController
& rController
)
86 : mrController(rController
),
87 mbIsCurrentSlideTrackingActive (
88 mrController
.GetVisibleAreaManager().IsCurrentSlideTrackingActive())
90 if (mbIsCurrentSlideTrackingActive
)
91 mrController
.GetVisibleAreaManager().DeactivateCurrentSlideTracking();
93 ~TemporarySlideTrackingDeactivator()
95 if (mbIsCurrentSlideTrackingActive
)
96 mrController
.GetVisibleAreaManager().ActivateCurrentSlideTracking();
100 SlideSorterController
& mrController
;
101 const bool mbIsCurrentSlideTrackingActive
;
103 } // end of anonymous namespace
105 class Clipboard::UndoContext
109 SdDrawDocument
* pDocument
,
110 const std::shared_ptr
<ViewShell
>& rpMainViewShell
)
111 : mpDocument(pDocument
),
112 mpMainViewShell(rpMainViewShell
)
114 if (mpDocument
!=nullptr && mpDocument
->IsUndoEnabled())
116 if (mpMainViewShell
&& mpMainViewShell
->GetShellType() == ViewShell::ST_DRAW
)
117 mpDocument
->BegUndo(SdResId(STRING_DRAG_AND_DROP_PAGES
));
119 mpDocument
->BegUndo(SdResId(STRING_DRAG_AND_DROP_SLIDES
));
125 if (mpDocument
!=nullptr && mpDocument
->IsUndoEnabled())
126 mpDocument
->EndUndo();
127 if (mpMainViewShell
&& mpMainViewShell
->GetViewFrame()!=nullptr)
129 SfxBindings
& rBindings
= mpMainViewShell
->GetViewFrame()->GetBindings();
130 rBindings
.Invalidate(SID_UNDO
);
131 rBindings
.Invalidate(SID_REDO
);
135 SdDrawDocument
* mpDocument
;
136 std::shared_ptr
<ViewShell
> mpMainViewShell
;
139 Clipboard::Clipboard (SlideSorter
& rSlideSorter
)
140 : ViewClipboard(rSlideSorter
.GetView()),
141 mrSlideSorter(rSlideSorter
),
142 mrController(mrSlideSorter
.GetController()),
145 mxSelectionObserverContext(),
146 mnDragFinishedUserEventId(nullptr)
150 Clipboard::~Clipboard()
152 if (mnDragFinishedUserEventId
!= nullptr)
153 Application::RemoveUserEvent(mnDragFinishedUserEventId
);
156 /** With the current implementation the forwarded calls to the current
157 function will come back eventually to call the local Do(Cut|Copy|Paste)
158 methods. A shortcut is possible but would be an unclean hack.
160 void Clipboard::HandleSlotCall (SfxRequest
& rRequest
)
162 ViewShell
* pViewShell
= mrSlideSorter
.GetViewShell();
163 rtl::Reference
<FuPoor
> xFunc
;
164 if (pViewShell
!= nullptr)
165 xFunc
= pViewShell
->GetCurrentFunction();
166 switch (rRequest
.GetSlot())
169 if (mrSlideSorter
.GetModel().GetEditMode() != EditMode::MasterPage
)
180 if (mrSlideSorter
.GetModel().GetEditMode() != EditMode::MasterPage
)
191 // Prevent redraws while inserting pages from the clipboard
192 // because the intermediate inconsistent state might lead to
194 if (mrSlideSorter
.GetModel().GetEditMode() != EditMode::MasterPage
)
196 view::SlideSorterView::DrawLock
aLock (mrSlideSorter
);
197 SelectionObserver::Context
aContext (mrSlideSorter
);
213 void Clipboard::DoCut ()
215 if (mrSlideSorter
.GetModel().GetPageCount() > 1)
222 void Clipboard::DoDelete()
224 if (mrSlideSorter
.GetModel().GetPageCount() > 1)
226 mrController
.GetSelectionManager()->DeleteSelectedPages();
230 void Clipboard::DoCopy ()
232 CreateSlideTransferable( nullptr, false );
235 void Clipboard::DoPaste ()
237 SdTransferable
* pClipTransferable
= SD_MOD()->pTransferClip
;
239 if (pClipTransferable
==nullptr || !pClipTransferable
->IsPageTransferable())
242 sal_Int32 nInsertPosition
= GetInsertionPosition();
244 if (nInsertPosition
>= 0)
246 // Paste the pages from the clipboard.
247 sal_Int32 nInsertPageCount
= PasteTransferable(nInsertPosition
);
248 // Select the pasted pages and make the first of them the
250 mrSlideSorter
.GetContentWindow()->GrabFocus();
251 SelectPageRange(nInsertPosition
, nInsertPageCount
);
255 sal_Int32
Clipboard::GetInsertionPosition ()
257 sal_Int32 nInsertPosition
= -1;
259 // Determine the insertion position:
260 // a) When the insertion indicator is visible, then at that position.
261 // b) When the focus indicator is visible, then before or after the
262 // focused page, depending on user input to a dialog.
263 // c) When there is a selection but no focus, then after the
265 // d) After the last page when there is no selection and no focus.
267 std::shared_ptr
<controller::InsertionIndicatorHandler
> pInsertionIndicatorHandler (
268 mrController
.GetInsertionIndicatorHandler());
269 if (pInsertionIndicatorHandler
->IsActive())
271 // Use the insertion index of an active insertion indicator.
272 nInsertPosition
= pInsertionIndicatorHandler
->GetInsertionPageIndex();
274 else if (mrController
.GetSelectionManager()->GetInsertionPosition() >= 0)
276 // Use the insertion index of an insertion indicator that has been
277 // deactivated a short while ago.
278 nInsertPosition
= mrController
.GetSelectionManager()->GetInsertionPosition();
280 else if (mrController
.GetFocusManager().IsFocusShowing())
282 // Use the focus to determine the insertion position.
283 vcl::Window
* pWin
= mrSlideSorter
.GetContentWindow();
284 SdInsertPasteDlg
aDialog(pWin
? pWin
->GetFrameWeld() : nullptr);
285 if (aDialog
.run() == RET_OK
)
287 nInsertPosition
= mrController
.GetFocusManager().GetFocusedPageIndex();
288 if (!aDialog
.IsInsertBefore())
293 return nInsertPosition
;
296 sal_Int32
Clipboard::PasteTransferable (sal_Int32 nInsertPosition
)
298 SdTransferable
* pClipTransferable
= SD_MOD()->pTransferClip
;
299 model::SlideSorterModel
& rModel (mrSlideSorter
.GetModel());
300 bool bMergeMasterPages
= !pClipTransferable
->HasSourceDoc (rModel
.GetDocument());
301 sal_uInt16
nInsertIndex (rModel
.GetCoreIndex(nInsertPosition
));
302 sal_Int32
nInsertPageCount (0);
303 if (pClipTransferable
->HasPageBookmarks())
305 const std::vector
<OUString
> &rBookmarkList
= pClipTransferable
->GetPageBookmarks();
306 const SolarMutexGuard aGuard
;
308 nInsertPageCount
= static_cast<sal_uInt16
>(rBookmarkList
.size());
309 rModel
.GetDocument()->InsertBookmarkAsPage(
316 pClipTransferable
->GetPageDocShell(),
323 SfxObjectShell
* pShell
= pClipTransferable
->GetDocShell().get();
324 DrawDocShell
* pDataDocSh
= static_cast<DrawDocShell
*>(pShell
);
325 SdDrawDocument
* pDataDoc
= pDataDocSh
->GetDoc();
327 if (pDataDoc
!=nullptr
328 && pDataDoc
->GetSdPageCount(PageKind::Standard
))
330 const SolarMutexGuard aGuard
;
332 bMergeMasterPages
= (pDataDoc
!= rModel
.GetDocument());
333 nInsertPageCount
= pDataDoc
->GetSdPageCount( PageKind::Standard
);
334 rModel
.GetDocument()->InsertBookmarkAsPage(
335 std::vector
<OUString
>(),
347 mrController
.HandleModelChange();
348 return nInsertPageCount
;
351 void Clipboard::SelectPageRange (sal_Int32 nFirstIndex
, sal_Int32 nPageCount
)
353 // Select the newly inserted pages. That are the nInsertPageCount pages
354 // after the nInsertIndex position.
355 PageSelector
& rSelector (mrController
.GetPageSelector());
356 rSelector
.DeselectAllPages();
357 for (sal_Int32 i
=0; i
<nPageCount
; i
++)
359 model::SharedPageDescriptor
pDescriptor (
360 mrSlideSorter
.GetModel().GetPageDescriptor(nFirstIndex
+ i
));
361 if (pDescriptor
.get() != nullptr)
363 rSelector
.SelectPage(pDescriptor
);
364 // The first page of the new selection is made the current page.
367 mrController
.GetCurrentSlideManager()->SwitchCurrentSlide(pDescriptor
);
373 void Clipboard::CreateSlideTransferable (
374 vcl::Window
* pWindow
,
377 std::vector
<OUString
> aBookmarkList
;
379 // Insert all selected pages into a bookmark list and remember them in
380 // maPagesToRemove for possible later removal.
381 model::PageEnumeration aSelectedPages
382 (model::PageEnumerationProvider::CreateSelectedPagesEnumeration(
383 mrSlideSorter
.GetModel()));
384 SdDrawDocument
* const pDocument
= mrSlideSorter
.GetModel().GetDocument();
385 DrawDocShell
* const pDataDocSh
= pDocument
->GetDocSh();
387 sal_Int32 nUniqueID
= 0;
388 while (aSelectedPages
.HasMoreElements())
390 model::SharedPageDescriptor
pDescriptor (aSelectedPages
.GetNextElement());
392 //ensure that the slides have unique names
393 const OUString sOrigName
= pDescriptor
->GetPage()->GetName();
394 if ( pDataDocSh
&& !pDataDocSh
->IsPageNameUnique( sOrigName
) )
396 OUString sUniqueName
;
397 bool bUnique
= false;
400 sUniqueName
= sOrigName
+ "_clipboard" + OUString::number(nUniqueID
++);
401 bUnique
= pDataDocSh
->IsNewPageNameValid( sUniqueName
);
403 pDescriptor
->GetPage()->SetName(sUniqueName
);
407 aBookmarkList
.push_back(pDescriptor
->GetPage()->GetName());
408 maPagesToRemove
.push_back (pDescriptor
->GetPage());
411 // Create a small set of representatives of the selection for which
412 // previews are included into the transferable so that an insertion
413 // indicator can be rendered.
414 aSelectedPages
.Rewind();
415 ::std::vector
<TransferableData::Representative
> aRepresentatives
;
416 aRepresentatives
.reserve(3);
417 std::shared_ptr
<cache::PageCache
> pPreviewCache (
418 mrSlideSorter
.GetView().GetPreviewCache());
419 while (aSelectedPages
.HasMoreElements())
421 model::SharedPageDescriptor
pDescriptor (aSelectedPages
.GetNextElement());
422 if ( ! pDescriptor
|| pDescriptor
->GetPage()==nullptr)
424 BitmapEx
aPreview (pPreviewCache
->GetPreviewBitmap(pDescriptor
->GetPage(), false));
425 aRepresentatives
.emplace_back(
427 pDescriptor
->HasState(model::PageDescriptor::ST_Excluded
));
428 if (aRepresentatives
.size() >= 3)
432 if (aBookmarkList
.empty())
435 mrSlideSorter
.GetView().BrkAction();
436 SdTransferable
* pTransferable
= TransferableData::CreateTransferable (
438 dynamic_cast<SlideSorterViewShell
*>(mrSlideSorter
.GetViewShell()),
442 SD_MOD()->pTransferDrag
= pTransferable
;
444 SD_MOD()->pTransferClip
= pTransferable
;
446 pDocument
->CreatingDataObj (pTransferable
);
447 pTransferable
->SetWorkDocument(pDocument
->AllocSdDrawDocument());
448 std::unique_ptr
<TransferableObjectDescriptor
> pObjDesc(new TransferableObjectDescriptor
);
449 pTransferable
->GetWorkDocument()->GetDocSh()
450 ->FillTransferableObjectDescriptor (*pObjDesc
);
452 if (pDataDocSh
!= nullptr)
453 pObjDesc
->maDisplayName
= pDataDocSh
->GetMedium()->GetURLObject().GetURLNoPass();
455 vcl::Window
* pActionWindow
= pWindow
;
456 if (pActionWindow
== nullptr)
458 ViewShell
* pViewShell
= mrSlideSorter
.GetViewShell();
459 if (pViewShell
!= nullptr)
460 pActionWindow
= pViewShell
->GetActiveWindow();
463 assert(pActionWindow
);
465 pTransferable
->SetStartPos (pActionWindow
->PixelToLogic(
466 pActionWindow
->GetPointerPosPixel()));
467 pTransferable
->SetObjectDescriptor (std::move(pObjDesc
));
470 TemporarySlideTrackingDeactivator
aDeactivator (mrController
);
471 pTransferable
->SetPageBookmarks (aBookmarkList
, !bDrag
);
476 pTransferable
->SetView (&mrSlideSorter
.GetView());
477 pTransferable
->StartDrag (pActionWindow
, DND_ACTION_COPY
| DND_ACTION_MOVE
);
480 pTransferable
->CopyToClipboard (pActionWindow
);
482 pDocument
->CreatingDataObj(nullptr);
485 std::shared_ptr
<SdTransferable::UserData
> Clipboard::CreateTransferableUserData (SdTransferable
* pTransferable
)
489 SdPageObjsTLB::SdPageObjsTransferable
* pTreeListBoxTransferable
490 = dynamic_cast<SdPageObjsTLB::SdPageObjsTransferable
*>(pTransferable
);
491 if (pTreeListBoxTransferable
== nullptr)
494 // Find view shell for the document of the transferable.
495 ::sd::ViewShell
* pViewShell
496 = SdPageObjsTLB::GetViewShellForDocShell(pTreeListBoxTransferable
->GetDocShell());
497 if (pViewShell
== nullptr)
500 // Find slide sorter for the document of the transferable.
501 SlideSorterViewShell
* pSlideSorterViewShell
502 = SlideSorterViewShell::GetSlideSorter(pViewShell
->GetViewShellBase());
503 if (pSlideSorterViewShell
== nullptr)
505 SlideSorter
& rSlideSorter (pSlideSorterViewShell
->GetSlideSorter());
507 // Get bookmark from transferable.
508 TransferableDataHelper
aDataHelper (pTransferable
);
509 INetBookmark aINetBookmark
;
510 if ( ! aDataHelper
.GetINetBookmark(SotClipboardFormatId::NETSCAPE_BOOKMARK
, aINetBookmark
))
512 const OUString
sURL (aINetBookmark
.GetURL());
513 const sal_Int32
nIndex (sURL
.indexOf('#'));
516 OUString
sBookmark (sURL
.copy(nIndex
+1));
518 // Make sure that the bookmark points to a page.
519 SdDrawDocument
* pTransferableDocument
= rSlideSorter
.GetModel().GetDocument();
520 if (pTransferableDocument
== nullptr)
522 bool bIsMasterPage
= false;
523 const sal_uInt16
nPageIndex (pTransferableDocument
->GetPageByName(sBookmark
, bIsMasterPage
));
524 if (nPageIndex
== SDRPAGE_NOTFOUND
)
528 ::std::vector
<TransferableData::Representative
> aRepresentatives
;
529 aRepresentatives
.reserve(1);
530 std::shared_ptr
<cache::PageCache
> pPreviewCache (
531 rSlideSorter
.GetView().GetPreviewCache());
532 model::SharedPageDescriptor
pDescriptor (rSlideSorter
.GetModel().GetPageDescriptor((nPageIndex
-1)/2));
533 if ( ! pDescriptor
|| pDescriptor
->GetPage()==nullptr)
535 BitmapEx
aPreview (pPreviewCache
->GetPreviewBitmap(pDescriptor
->GetPage(), false));
536 aRepresentatives
.emplace_back(
538 pDescriptor
->HasState(model::PageDescriptor::ST_Excluded
));
540 // Remember the page in maPagesToRemove so that it can be removed
541 // when drag and drop action is "move".
542 Clipboard
& rOtherClipboard (pSlideSorterViewShell
->GetSlideSorter().GetController().GetClipboard());
543 rOtherClipboard
.maPagesToRemove
.clear();
544 rOtherClipboard
.maPagesToRemove
.push_back(pDescriptor
->GetPage());
546 // Create the new transferable.
547 std::shared_ptr
<SdTransferable::UserData
> pNewTransferable (
548 new TransferableData(
549 pSlideSorterViewShell
,
551 pTransferable
->SetWorkDocument(pTreeListBoxTransferable
->GetSourceDoc()->AllocSdDrawDocument());
552 // pTransferable->SetView(&mrSlideSorter.GetView());
554 // Set page bookmark list.
555 std::vector
<OUString
> aPageBookmarks
;
556 aPageBookmarks
.push_back(sBookmark
);
557 pTransferable
->SetPageBookmarks(aPageBookmarks
, false);
559 // Replace the view referenced by the transferable with the
560 // corresponding slide sorter view.
561 pTransferable
->SetView(&pSlideSorterViewShell
->GetSlideSorter().GetView());
563 return pNewTransferable
;
567 return std::shared_ptr
<SdTransferable::UserData
>();
570 void Clipboard::StartDrag (
571 const Point
& rPosition
,
572 vcl::Window
* pWindow
)
574 maPagesToRemove
.clear();
575 CreateSlideTransferable(pWindow
, true);
577 mrController
.GetInsertionIndicatorHandler()->UpdatePosition(
579 InsertionIndicatorHandler::UnknownMode
);
582 void Clipboard::DragFinished (sal_Int8 nDropAction
)
584 if (mnDragFinishedUserEventId
== nullptr)
586 mnDragFinishedUserEventId
= Application::PostUserEvent(
587 LINK(this, Clipboard
, ProcessDragFinished
),
588 reinterpret_cast<void*>(nDropAction
));
592 IMPL_LINK(Clipboard
, ProcessDragFinished
, void*, pUserData
, void)
594 const sal_Int8
nDropAction (static_cast<sal_Int8
>(reinterpret_cast<sal_IntPtr
>(pUserData
)));
596 mnDragFinishedUserEventId
= nullptr;
598 // Hide the substitution display and insertion indicator.
599 ::rtl::Reference
<SelectionFunction
> pFunction (mrController
.GetCurrentSelectionFunction());
601 pFunction
->NotifyDragFinished();
603 PageSelector
& rSelector (mrController
.GetPageSelector());
604 if ((nDropAction
& DND_ACTION_MOVE
) != 0
605 && ! maPagesToRemove
.empty())
607 // Remove the pages that have been moved to another place (possibly
608 // in the same document.)
609 rSelector
.DeselectAllPages();
610 for (const auto& rpDraggedPage
: maPagesToRemove
)
612 rSelector
.SelectPage(rpDraggedPage
);
614 mrController
.GetSelectionManager()->DeleteSelectedPages();
616 mxUndoContext
.reset();
617 mxSelectionObserverContext
.reset();
620 sal_Int8
Clipboard::AcceptDrop (
621 const AcceptDropEvent
& rEvent
,
622 DropTargetHelper
& rTargetHelper
,
623 ::sd::Window
* pTargetWindow
,
627 sal_Int8
nAction (DND_ACTION_NONE
);
629 const Clipboard::DropType
eDropType (IsDropAccepted());
634 case DT_PAGE_FROM_NAVIGATOR
:
637 nAction
= rEvent
.mnAction
;
639 // Use the copy action when the drop action is the default, i.e. not
640 // explicitly set to move or link, and when the source and
641 // target models are not the same.
642 SdTransferable
* pDragTransferable
= SD_MOD()->pTransferDrag
;
643 if (pDragTransferable
!= nullptr
644 && pDragTransferable
->IsPageTransferable()
645 && ((rEvent
.maDragEvent
.DropAction
646 & css::datatransfer::dnd::DNDConstants::ACTION_DEFAULT
) != 0)
647 && (mrSlideSorter
.GetModel().GetDocument()->GetDocSh()
648 != pDragTransferable
->GetPageDocShell()))
650 nAction
= DND_ACTION_COPY
;
652 else if (IsInsertionTrivial(pDragTransferable
, nAction
))
654 nAction
= DND_ACTION_NONE
;
657 // Show the insertion marker and the substitution for a drop.
658 SelectionFunction
* pSelectionFunction
= dynamic_cast<SelectionFunction
*>(
659 mrSlideSorter
.GetViewShell()->GetCurrentFunction().get());
660 if (pSelectionFunction
!= nullptr)
661 pSelectionFunction
->MouseDragged(rEvent
, nAction
);
663 // Scroll the window when the mouse reaches the window border.
664 // mrController.GetScrollBarManager().AutoScroll (rEvent.maPosPixel);
669 nAction
= ExecuteOrAcceptShapeDrop(
681 nAction
= DND_ACTION_NONE
;
688 sal_Int8
Clipboard::ExecuteDrop (
689 const ExecuteDropEvent
& rEvent
,
690 DropTargetHelper
& rTargetHelper
,
691 ::sd::Window
* pTargetWindow
,
695 sal_Int8 nResult
= DND_ACTION_NONE
;
696 mxUndoContext
.reset();
697 const Clipboard::DropType
eDropType (IsDropAccepted());
702 case DT_PAGE_FROM_NAVIGATOR
:
704 SdTransferable
* pDragTransferable
= SD_MOD()->pTransferDrag
;
705 const Point
aEventModelPosition (
706 pTargetWindow
->PixelToLogic (rEvent
.maPosPixel
));
707 const sal_Int32
nXOffset (labs (pDragTransferable
->GetStartPos().X()
708 - aEventModelPosition
.X()));
709 const sal_Int32
nYOffset (labs (pDragTransferable
->GetStartPos().Y()
710 - aEventModelPosition
.Y()));
712 ( pDragTransferable
->GetView() != &mrSlideSorter
.GetView() )
713 || ( nXOffset
>= 2 && nYOffset
>= 2 );
715 std::shared_ptr
<InsertionIndicatorHandler
> pInsertionIndicatorHandler(
716 mrController
.GetInsertionIndicatorHandler());
717 // Get insertion position and then turn off the insertion indicator.
718 pInsertionIndicatorHandler
->UpdatePosition(aEventModelPosition
, rEvent
.mnAction
);
719 // sal_uInt16 nIndex = DetermineInsertPosition(*pDragTransferable);
721 // Do not process the insertion when it is trivial,
722 // i.e. would insert pages at their original place.
723 if (IsInsertionTrivial(pDragTransferable
, rEvent
.mnAction
))
726 // Tell the insertion indicator handler to hide before the model
727 // is modified. Doing it later may result in page objects whose
728 // animation state is not properly reset because they are then
729 // in another run then before the model change.
730 pInsertionIndicatorHandler
->End(Animator::AM_Immediate
);
734 SlideSorterController::ModelChangeLock
aModelChangeLock (mrController
);
736 // Handle a general drop operation.
737 mxUndoContext
.reset(new UndoContext (
738 mrSlideSorter
.GetModel().GetDocument(),
739 mrSlideSorter
.GetViewShell()->GetViewShellBase().GetMainViewShell()));
740 mxSelectionObserverContext
.reset(new SelectionObserver::Context(mrSlideSorter
));
742 HandlePageDrop(*pDragTransferable
);
743 nResult
= rEvent
.mnAction
;
745 // We leave the undo context alive for when moving or
746 // copying inside one view then the actions in
747 // NotifyDragFinished should be covered as well as
748 // well as the ones above.
751 // When the pages originated in another slide sorter then
752 // only that is notified automatically about the drag
753 // operation being finished. Because the target slide sorter
754 // has be notified, too, add a callback for that.
755 std::shared_ptr
<TransferableData
> pSlideSorterTransferable (
756 TransferableData::GetFromTransferable(pDragTransferable
));
757 BOOST_ASSERT(pSlideSorterTransferable
);
758 if (pSlideSorterTransferable
759 && pSlideSorterTransferable
->GetSourceViewShell() != mrSlideSorter
.GetViewShell())
761 DragFinished(nResult
);
764 // Notify the receiving selection function that drag-and-drop is
765 // finished and the substitution handler can be released.
766 ::rtl::Reference
<SelectionFunction
> pFunction (
767 mrController
.GetCurrentSelectionFunction());
769 pFunction
->NotifyDragFinished();
774 nResult
= ExecuteOrAcceptShapeDrop(
792 bool Clipboard::IsInsertionTrivial (
793 SdTransferable
const * pTransferable
,
794 const sal_Int8 nDndAction
) const
796 std::shared_ptr
<TransferableData
> pSlideSorterTransferable (
797 TransferableData::GetFromTransferable(pTransferable
));
798 if (pSlideSorterTransferable
799 && pSlideSorterTransferable
->GetSourceViewShell() != mrSlideSorter
.GetViewShell())
801 return mrController
.GetInsertionIndicatorHandler()->IsInsertionTrivial(nDndAction
);
804 void Clipboard::Abort()
806 if (mxSelectionObserverContext
)
808 mxSelectionObserverContext
->Abort();
809 mxSelectionObserverContext
.reset();
813 sal_uInt16
Clipboard::DetermineInsertPosition (const SdTransferable
& )
815 // Tell the model to move the dragged pages behind the one with the
816 // index nInsertionIndex which first has to be transformed into an index
817 // understandable by the document.
818 const sal_Int32
nInsertionIndex (
819 mrController
.GetInsertionIndicatorHandler()->GetInsertionPageIndex());
821 // Convert to insertion index to that of an SdModel.
822 if (nInsertionIndex
>= 0)
823 return mrSlideSorter
.GetModel().GetCoreIndex(nInsertionIndex
);
828 Clipboard::DropType
Clipboard::IsDropAccepted() const
830 const SdTransferable
* pDragTransferable
= SD_MOD()->pTransferDrag
;
831 if (pDragTransferable
== nullptr)
834 if (pDragTransferable
->IsPageTransferable())
836 if (mrSlideSorter
.GetModel().GetEditMode() != EditMode::MasterPage
)
842 const SdPageObjsTLB::SdPageObjsTransferable
* pPageObjsTransferable
843 = dynamic_cast<const SdPageObjsTLB::SdPageObjsTransferable
*>(pDragTransferable
);
844 if (pPageObjsTransferable
!= nullptr)
845 return DT_PAGE_FROM_NAVIGATOR
;
850 sal_Int8
Clipboard::ExecuteOrAcceptShapeDrop (
851 DropCommand eCommand
,
852 const Point
& rPosition
,
853 const void* pDropEvent
,
854 DropTargetHelper
& rTargetHelper
,
855 ::sd::Window
* pTargetWindow
,
859 sal_Int8 nResult
= 0;
861 // The dropping of a shape is accepted or executed only when there is
862 // DrawViewShell available to which we can forward this call. This has
863 // technical reasons: The actual code to accept or execute a shape drop
864 // is implemented in the ViewShell class and uses the page view of the
865 // main edit view. This is not possible without a DrawViewShell.
866 std::shared_ptr
<DrawViewShell
> pDrawViewShell
;
867 if (mrSlideSorter
.GetViewShell() != nullptr)
868 pDrawViewShell
= std::dynamic_pointer_cast
<DrawViewShell
>(
869 mrSlideSorter
.GetViewShell()->GetViewShellBase().GetMainViewShell());
870 if (pDrawViewShell
!= nullptr
871 && (pDrawViewShell
->GetShellType() == ViewShell::ST_IMPRESS
872 || pDrawViewShell
->GetShellType() == ViewShell::ST_DRAW
))
874 // The drop is only accepted or executed when it takes place over a
875 // page object. Therefore we replace a missing page number by the
876 // number of the page under the mouse.
877 if (nPage
== SDRPAGE_NOTFOUND
)
879 model::SharedPageDescriptor
pDescriptor (
880 mrSlideSorter
.GetModel().GetPageDescriptor(
881 mrSlideSorter
.GetView().GetPageIndexAtPoint(rPosition
)));
883 nPage
= pDescriptor
->GetPageIndex();
886 // Now comes the code that is different for the Execute and Accept:
887 // We simply forward the call to the AcceptDrop() or ExecuteDrop()
888 // methods of the DrawViewShell in the center pane.
889 if (nPage
!= SDRPAGE_NOTFOUND
)
893 nResult
= pDrawViewShell
->AcceptDrop(
894 *static_cast<const AcceptDropEvent
*>(pDropEvent
),
902 nResult
= pDrawViewShell
->ExecuteDrop(
903 *static_cast<const ExecuteDropEvent
*>(pDropEvent
),
915 } } } // end of namespace ::sd::slidesorter::controller
917 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */