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"
54 #include "strings.hrc"
55 #include "sdresid.hxx"
58 #include "ins_paste.hxx"
59 #include "drawdoc.hxx"
60 #include "DrawDocShell.hxx"
62 #include "sdtreelb.hxx"
64 #include <com/sun/star/datatransfer/dnd/DNDConstants.hpp>
65 #include <sfx2/request.hxx>
66 #include <sfx2/viewfrm.hxx>
67 #include <sfx2/bindings.hxx>
68 #include <sfx2/docfile.hxx>
69 #include <svx/svxids.hrc>
70 #include <svx/svdstr.hrc>
71 #include <vcl/msgbox.hxx>
72 #include <tools/urlobj.hxx>
73 #include <rtl/ustring.hxx>
74 #include <osl/mutex.hxx>
75 #include <vcl/svapp.hxx>
76 #include <boost/bind.hpp>
78 namespace sd
{ namespace slidesorter
{ namespace controller
{
81 /** Temporarily deactivate slide tracking of the VisibleAreaManager.
82 This is used as a workaround to avoid unwanted repositioning of
83 the visible area when the selection of slides is copied to the
84 clipboard (cloning of slides leads to model change notifications
85 for the original model.)
87 class TemporarySlideTrackingDeactivator
90 TemporarySlideTrackingDeactivator (SlideSorterController
& rController
)
91 : mrController(rController
),
92 mbIsCurrentSlideTrackingActive (
93 mrController
.GetVisibleAreaManager().IsCurrentSlideTrackingActive())
95 if (mbIsCurrentSlideTrackingActive
)
96 mrController
.GetVisibleAreaManager().DeactivateCurrentSlideTracking();
98 ~TemporarySlideTrackingDeactivator()
100 if (mbIsCurrentSlideTrackingActive
)
101 mrController
.GetVisibleAreaManager().ActivateCurrentSlideTracking();
105 SlideSorterController
& mrController
;
106 const bool mbIsCurrentSlideTrackingActive
;
108 } // end of anonymous namespace
110 class Clipboard::UndoContext
114 SdDrawDocument
* pDocument
,
115 const ::boost::shared_ptr
<ViewShell
>& rpMainViewShell
)
116 : mpDocument(pDocument
),
117 mpMainViewShell(rpMainViewShell
)
119 if (mpDocument
!=NULL
&& mpDocument
->IsUndoEnabled())
121 if (mpMainViewShell
&& mpMainViewShell
->GetShellType() == ViewShell::ST_DRAW
)
122 mpDocument
->BegUndo(SD_RESSTR(STRING_DRAG_AND_DROP_PAGES
));
124 mpDocument
->BegUndo(SD_RESSTR(STRING_DRAG_AND_DROP_SLIDES
));
130 if (mpDocument
!=NULL
&& mpDocument
->IsUndoEnabled())
131 mpDocument
->EndUndo();
132 if (mpMainViewShell
&& mpMainViewShell
->GetViewFrame()!=NULL
)
134 SfxBindings
& rBindings
= mpMainViewShell
->GetViewFrame()->GetBindings();
135 rBindings
.Invalidate(SID_UNDO
);
136 rBindings
.Invalidate(SID_REDO
);
140 SdDrawDocument
* mpDocument
;
141 ::boost::shared_ptr
<ViewShell
> mpMainViewShell
;
144 Clipboard::Clipboard (SlideSorter
& rSlideSorter
)
145 : ViewClipboard(rSlideSorter
.GetView()),
146 mrSlideSorter(rSlideSorter
),
147 mrController(mrSlideSorter
.GetController()),
150 mbUpdateSelectionPending(false),
152 mxSelectionObserverContext(),
153 mnDragFinishedUserEventId(0)
157 Clipboard::~Clipboard()
159 if (mnDragFinishedUserEventId
!= 0)
160 Application::RemoveUserEvent(mnDragFinishedUserEventId
);
163 /** With the current implementation the forwarded calls to the current
164 function will come back eventually to call the local Do(Cut|Copy|Paste)
165 methods. A shortcut is possible but would be an unclean hack.
167 void Clipboard::HandleSlotCall (SfxRequest
& rRequest
)
169 ViewShell
* pViewShell
= mrSlideSorter
.GetViewShell();
170 rtl::Reference
<FuPoor
> xFunc
;
171 if (pViewShell
!= NULL
)
172 xFunc
= pViewShell
->GetCurrentFunction();
173 switch (rRequest
.GetSlot())
176 if (mrSlideSorter
.GetModel().GetEditMode() != EM_MASTERPAGE
)
187 if (mrSlideSorter
.GetModel().GetEditMode() != EM_MASTERPAGE
)
198 // Prevent redraws while inserting pages from the clipboard
199 // because the intermediate inconsistent state might lead to
201 if (mrSlideSorter
.GetModel().GetEditMode() != EM_MASTERPAGE
)
203 view::SlideSorterView::DrawLock
aLock (mrSlideSorter
);
204 SelectionObserver::Context
aContext (mrSlideSorter
);
220 void Clipboard::DoCut (vcl::Window
* pWindow
)
222 if (mrSlideSorter
.GetModel().GetPageCount() > 1)
229 void Clipboard::DoDelete (vcl::Window
* )
231 if (mrSlideSorter
.GetModel().GetPageCount() > 1)
233 mrController
.GetSelectionManager()->DeleteSelectedPages();
237 void Clipboard::DoCopy (vcl::Window
* pWindow
)
239 CreateSlideTransferable( pWindow
, false );
242 void Clipboard::DoPaste (vcl::Window
* pWindow
)
244 SdTransferable
* pClipTransferable
= SD_MOD()->pTransferClip
;
246 if (pClipTransferable
!=NULL
&& pClipTransferable
->IsPageTransferable())
248 sal_Int32 nInsertPosition
= GetInsertionPosition(pWindow
);
250 if (nInsertPosition
>= 0)
252 // Paste the pages from the clipboard.
253 sal_Int32 nInsertPageCount
= PasteTransferable(nInsertPosition
);
254 // Select the pasted pages and make the first of them the
256 mrSlideSorter
.GetContentWindow()->GrabFocus();
257 SelectPageRange(nInsertPosition
, nInsertPageCount
);
262 sal_Int32
Clipboard::GetInsertionPosition (vcl::Window
* pWindow
)
264 sal_Int32 nInsertPosition
= -1;
266 // Determine the insertion position:
267 // a) When the insertion indicator is visible, then at that position.
268 // b) When the focus indicator is visible, then before or after the
269 // focused page, depending on user input to a dialog.
270 // c) When there is a selection but no focus, then after the
272 // d) After the last page when there is no selection and no focus.
274 ::boost::shared_ptr
<controller::InsertionIndicatorHandler
> pInsertionIndicatorHandler (
275 mrController
.GetInsertionIndicatorHandler());
276 if (pInsertionIndicatorHandler
->IsActive())
278 // Use the insertion index of an active insertion indicator.
279 nInsertPosition
= pInsertionIndicatorHandler
->GetInsertionPageIndex();
281 else if (mrController
.GetSelectionManager()->GetInsertionPosition() >= 0)
283 // Use the insertion index of an insertion indicator that has been
284 // deactivated a short while ago.
285 nInsertPosition
= mrController
.GetSelectionManager()->GetInsertionPosition();
287 else if (mrController
.GetFocusManager().IsFocusShowing())
289 // Use the focus to determine the insertion position.
290 ScopedVclPtrInstance
< SdInsertPasteDlg
> aDialog(pWindow
);
291 if (aDialog
->Execute() == RET_OK
)
293 nInsertPosition
= mrController
.GetFocusManager().GetFocusedPageIndex();
294 if ( ! aDialog
->IsInsertBefore())
299 return nInsertPosition
;
302 sal_Int32
Clipboard::PasteTransferable (sal_Int32 nInsertPosition
)
304 SdTransferable
* pClipTransferable
= SD_MOD()->pTransferClip
;
305 model::SlideSorterModel
& rModel (mrSlideSorter
.GetModel());
306 bool bMergeMasterPages
= !pClipTransferable
->HasSourceDoc (rModel
.GetDocument());
307 sal_uInt16
nInsertIndex (rModel
.GetCoreIndex(nInsertPosition
));
308 sal_Int32
nInsertPageCount (0);
309 if (pClipTransferable
->HasPageBookmarks())
311 const std::vector
<OUString
> &rBookmarkList
= pClipTransferable
->GetPageBookmarks();
312 const SolarMutexGuard aGuard
;
314 nInsertPageCount
= (sal_uInt16
) rBookmarkList
.size();
315 rModel
.GetDocument()->InsertBookmarkAsPage(
322 pClipTransferable
->GetPageDocShell(),
329 SfxObjectShell
* pShell
= pClipTransferable
->GetDocShell();
330 DrawDocShell
* pDataDocSh
= static_cast<DrawDocShell
*>(pShell
);
331 SdDrawDocument
* pDataDoc
= pDataDocSh
->GetDoc();
334 && pDataDoc
->GetSdPageCount(PK_STANDARD
))
336 const SolarMutexGuard aGuard
;
338 bMergeMasterPages
= (pDataDoc
!= rModel
.GetDocument());
339 nInsertPageCount
= pDataDoc
->GetSdPageCount( PK_STANDARD
);
340 rModel
.GetDocument()->InsertBookmarkAsPage(
341 std::vector
<OUString
>(),
353 mrController
.HandleModelChange();
354 return nInsertPageCount
;
357 void Clipboard::SelectPageRange (sal_Int32 nFirstIndex
, sal_Int32 nPageCount
)
359 // Select the newly inserted pages. That are the nInsertPageCount pages
360 // after the nInsertIndex position.
361 PageSelector
& rSelector (mrController
.GetPageSelector());
362 rSelector
.DeselectAllPages();
363 for (sal_uInt16 i
=0; i
<nPageCount
; i
++)
365 model::SharedPageDescriptor
pDescriptor (
366 mrSlideSorter
.GetModel().GetPageDescriptor(nFirstIndex
+ i
));
367 if (pDescriptor
.get() != NULL
)
369 rSelector
.SelectPage(pDescriptor
);
370 // The first page of the new selection is made the current page.
373 mrController
.GetCurrentSlideManager()->SwitchCurrentSlide(pDescriptor
);
379 void Clipboard::CreateSlideTransferable (
380 vcl::Window
* pWindow
,
383 std::vector
<OUString
> aBookmarkList
;
385 // Insert all selected pages into a bookmark list and remember them in
386 // maPagesToRemove for possible later removal.
387 model::PageEnumeration aSelectedPages
388 (model::PageEnumerationProvider::CreateSelectedPagesEnumeration(
389 mrSlideSorter
.GetModel()));
390 while (aSelectedPages
.HasMoreElements())
392 model::SharedPageDescriptor
pDescriptor (aSelectedPages
.GetNextElement());
393 aBookmarkList
.push_back(pDescriptor
->GetPage()->GetName());
394 maPagesToRemove
.push_back (pDescriptor
->GetPage());
397 // Create a small set of representatives of the selection for which
398 // previews are included into the transferable so that an insertion
399 // indicator can be rendered.
400 aSelectedPages
.Rewind();
401 ::std::vector
<TransferableData::Representative
> aRepresentatives
;
402 aRepresentatives
.reserve(3);
403 ::boost::shared_ptr
<cache::PageCache
> pPreviewCache (
404 mrSlideSorter
.GetView().GetPreviewCache());
405 while (aSelectedPages
.HasMoreElements())
407 model::SharedPageDescriptor
pDescriptor (aSelectedPages
.GetNextElement());
408 if ( ! pDescriptor
|| pDescriptor
->GetPage()==NULL
)
410 Bitmap
aPreview (pPreviewCache
->GetPreviewBitmap(pDescriptor
->GetPage(), false));
411 aRepresentatives
.push_back(TransferableData::Representative(
413 pDescriptor
->HasState(model::PageDescriptor::ST_Excluded
)));
414 if (aRepresentatives
.size() >= 3)
418 if (!aBookmarkList
.empty())
420 mrSlideSorter
.GetView().BrkAction();
421 SdDrawDocument
* pDocument
= mrSlideSorter
.GetModel().GetDocument();
422 SdTransferable
* pTransferable
= TransferableData::CreateTransferable (
426 dynamic_cast<SlideSorterViewShell
*>(mrSlideSorter
.GetViewShell()),
430 SD_MOD()->pTransferDrag
= pTransferable
;
432 SD_MOD()->pTransferClip
= pTransferable
;
434 pDocument
->CreatingDataObj (pTransferable
);
435 pTransferable
->SetWorkDocument(pDocument
->AllocSdDrawDocument());
436 pDocument
->CreatingDataObj (NULL
);
437 TransferableObjectDescriptor aObjDesc
;
438 pTransferable
->GetWorkDocument()->GetDocSh()
439 ->FillTransferableObjectDescriptor (aObjDesc
);
441 if (pDocument
->GetDocSh() != NULL
)
442 aObjDesc
.maDisplayName
= pDocument
->GetDocSh()
443 ->GetMedium()->GetURLObject().GetURLNoPass();
445 vcl::Window
* pActionWindow
= pWindow
;
446 if (pActionWindow
== NULL
)
448 ViewShell
* pViewShell
= mrSlideSorter
.GetViewShell();
449 if (pViewShell
!= NULL
)
450 pActionWindow
= pViewShell
->GetActiveWindow();
453 pTransferable
->SetStartPos (pActionWindow
->PixelToLogic(
454 pActionWindow
->GetPointerPosPixel()));
455 pTransferable
->SetObjectDescriptor (aObjDesc
);
458 TemporarySlideTrackingDeactivator
aDeactivator (mrController
);
459 pTransferable
->SetPageBookmarks (aBookmarkList
, !bDrag
);
464 pTransferable
->SetView (&mrSlideSorter
.GetView());
465 pTransferable
->StartDrag (pActionWindow
, DND_ACTION_COPY
| DND_ACTION_MOVE
);
468 pTransferable
->CopyToClipboard (pActionWindow
);
472 ::boost::shared_ptr
<SdTransferable::UserData
> Clipboard::CreateTransferableUserData (SdTransferable
* pTransferable
)
476 SdPageObjsTLB::SdPageObjsTransferable
* pTreeListBoxTransferable
477 = dynamic_cast<SdPageObjsTLB::SdPageObjsTransferable
*>(pTransferable
);
478 if (pTreeListBoxTransferable
== NULL
)
481 // Find view shell for the document of the transferable.
482 ::sd::ViewShell
* pViewShell
483 = SdPageObjsTLB::GetViewShellForDocShell(pTreeListBoxTransferable
->GetDocShell());
484 if (pViewShell
== NULL
)
487 // Find slide sorter for the document of the transferable.
488 SlideSorterViewShell
* pSlideSorterViewShell
489 = SlideSorterViewShell::GetSlideSorter(pViewShell
->GetViewShellBase());
490 if (pSlideSorterViewShell
== NULL
)
492 SlideSorter
& rSlideSorter (pSlideSorterViewShell
->GetSlideSorter());
494 // Get bookmark from transferable.
495 TransferableDataHelper
aDataHelper (pTransferable
);
496 INetBookmark aINetBookmark
;
497 if ( ! aDataHelper
.GetINetBookmark(SotClipboardFormatId::NETSCAPE_BOOKMARK
, aINetBookmark
))
499 const OUString
sURL (aINetBookmark
.GetURL());
500 const sal_Int32
nIndex (sURL
.indexOf((sal_Unicode
)'#'));
503 OUString
sBookmark (sURL
.copy(nIndex
+1));
505 // Make sure that the bookmark points to a page.
506 SdDrawDocument
* pTransferableDocument
= rSlideSorter
.GetModel().GetDocument();
507 if (pTransferableDocument
== NULL
)
509 bool bIsMasterPage
= false;
510 const sal_uInt16
nPageIndex (pTransferableDocument
->GetPageByName(sBookmark
, bIsMasterPage
));
511 if (nPageIndex
== SDRPAGE_NOTFOUND
)
515 ::std::vector
<TransferableData::Representative
> aRepresentatives
;
516 aRepresentatives
.reserve(1);
517 ::boost::shared_ptr
<cache::PageCache
> pPreviewCache (
518 rSlideSorter
.GetView().GetPreviewCache());
519 model::SharedPageDescriptor
pDescriptor (rSlideSorter
.GetModel().GetPageDescriptor((nPageIndex
-1)/2));
520 if ( ! pDescriptor
|| pDescriptor
->GetPage()==NULL
)
522 Bitmap
aPreview (pPreviewCache
->GetPreviewBitmap(pDescriptor
->GetPage(), false));
523 aRepresentatives
.push_back(TransferableData::Representative(
525 pDescriptor
->HasState(model::PageDescriptor::ST_Excluded
)));
527 // Remember the page in maPagesToRemove so that it can be removed
528 // when drag and drop action is "move".
529 Clipboard
& rOtherClipboard (pSlideSorterViewShell
->GetSlideSorter().GetController().GetClipboard());
530 rOtherClipboard
.maPagesToRemove
.clear();
531 rOtherClipboard
.maPagesToRemove
.push_back(pDescriptor
->GetPage());
533 // Create the new transferable.
534 ::boost::shared_ptr
<SdTransferable::UserData
> pNewTransferable (
535 new TransferableData(
536 pSlideSorterViewShell
,
538 pTransferable
->SetWorkDocument(pTreeListBoxTransferable
->GetSourceDoc()->AllocSdDrawDocument());
539 // pTransferable->SetView(&mrSlideSorter.GetView());
541 // Set page bookmark list.
542 std::vector
<OUString
> aPageBookmarks
;
543 aPageBookmarks
.push_back(sBookmark
);
544 pTransferable
->SetPageBookmarks(aPageBookmarks
, false);
546 // Replace the view referenced by the transferable with the
547 // corresponding slide sorter view.
548 pTransferable
->SetView(&pSlideSorterViewShell
->GetSlideSorter().GetView());
550 return pNewTransferable
;
554 return ::boost::shared_ptr
<SdTransferable::UserData
>();
557 void Clipboard::StartDrag (
558 const Point
& rPosition
,
559 vcl::Window
* pWindow
)
561 maPagesToRemove
.clear();
562 maPagesToSelect
.clear();
563 mbUpdateSelectionPending
= false;
564 CreateSlideTransferable(pWindow
, true);
566 mrController
.GetInsertionIndicatorHandler()->UpdatePosition(
568 InsertionIndicatorHandler::UnknownMode
);
571 void Clipboard::DragFinished (sal_Int8 nDropAction
)
573 if (mnDragFinishedUserEventId
== 0)
575 mnDragFinishedUserEventId
= Application::PostUserEvent(
576 LINK(this, Clipboard
, ProcessDragFinished
),
577 reinterpret_cast<void*>(nDropAction
));
581 IMPL_LINK(Clipboard
, ProcessDragFinished
, void*, pUserData
)
583 const sal_Int8
nDropAction (static_cast<sal_Int8
>(reinterpret_cast<sal_IntPtr
>(pUserData
)));
585 mnDragFinishedUserEventId
= 0;
587 // Hide the substitution display and insertion indicator.
588 ::rtl::Reference
<SelectionFunction
> pFunction (mrController
.GetCurrentSelectionFunction());
590 pFunction
->NotifyDragFinished();
592 PageSelector
& rSelector (mrController
.GetPageSelector());
593 if ((nDropAction
& DND_ACTION_MOVE
) != 0
594 && ! maPagesToRemove
.empty())
596 // Remove the pages that have been moved to another place (possibly
597 // in the same document.)
598 rSelector
.DeselectAllPages();
599 PageList::iterator aDraggedPage
;
600 for (aDraggedPage
=maPagesToRemove
.begin();
601 aDraggedPage
!=maPagesToRemove
.end();
604 rSelector
.SelectPage(*aDraggedPage
);
606 mrController
.GetSelectionManager()->DeleteSelectedPages();
608 mxUndoContext
.reset();
609 mxSelectionObserverContext
.reset();
614 sal_Int8
Clipboard::AcceptDrop (
615 const AcceptDropEvent
& rEvent
,
616 DropTargetHelper
& rTargetHelper
,
617 ::sd::Window
* pTargetWindow
,
621 sal_Int8
nAction (DND_ACTION_NONE
);
623 const Clipboard::DropType
eDropType (IsDropAccepted(rTargetHelper
));
628 case DT_PAGE_FROM_NAVIGATOR
:
631 nAction
= rEvent
.mnAction
;
633 // Use the copy action when the drop action is the default, i.e. not
634 // explicitly set to move or link, and when the source and
635 // target models are not the same.
636 SdTransferable
* pDragTransferable
= SD_MOD()->pTransferDrag
;
637 if (pDragTransferable
!= NULL
638 && pDragTransferable
->IsPageTransferable()
639 && ((rEvent
.maDragEvent
.DropAction
640 & ::com::sun::star::datatransfer::dnd::DNDConstants::ACTION_DEFAULT
) != 0)
641 && (mrSlideSorter
.GetModel().GetDocument()->GetDocSh()
642 != pDragTransferable
->GetPageDocShell()))
644 nAction
= DND_ACTION_COPY
;
646 else if (IsInsertionTrivial(pDragTransferable
, nAction
))
648 nAction
= DND_ACTION_NONE
;
651 // Show the insertion marker and the substitution for a drop.
652 SelectionFunction
* pSelectionFunction
= dynamic_cast<SelectionFunction
*>(
653 mrSlideSorter
.GetViewShell()->GetCurrentFunction().get());
654 if (pSelectionFunction
!= NULL
)
655 pSelectionFunction
->MouseDragged(rEvent
, nAction
);
657 // Scroll the window when the mouse reaches the window border.
658 // mrController.GetScrollBarManager().AutoScroll (rEvent.maPosPixel);
663 nAction
= ExecuteOrAcceptShapeDrop(
675 nAction
= DND_ACTION_NONE
;
682 sal_Int8
Clipboard::ExecuteDrop (
683 const ExecuteDropEvent
& rEvent
,
684 DropTargetHelper
& rTargetHelper
,
685 ::sd::Window
* pTargetWindow
,
689 sal_Int8 nResult
= DND_ACTION_NONE
;
690 mxUndoContext
.reset();
691 const Clipboard::DropType
eDropType (IsDropAccepted(rTargetHelper
));
696 case DT_PAGE_FROM_NAVIGATOR
:
698 SdTransferable
* pDragTransferable
= SD_MOD()->pTransferDrag
;
699 const Point
aEventModelPosition (
700 pTargetWindow
->PixelToLogic (rEvent
.maPosPixel
));
701 const sal_Int32
nXOffset (labs (pDragTransferable
->GetStartPos().X()
702 - aEventModelPosition
.X()));
703 const sal_Int32
nYOffset (labs (pDragTransferable
->GetStartPos().Y()
704 - aEventModelPosition
.Y()));
706 ( pDragTransferable
->GetView() != &mrSlideSorter
.GetView() )
707 || ( nXOffset
>= 2 && nYOffset
>= 2 );
709 ::boost::shared_ptr
<InsertionIndicatorHandler
> pInsertionIndicatorHandler(
710 mrController
.GetInsertionIndicatorHandler());
711 // Get insertion position and then turn off the insertion indicator.
712 pInsertionIndicatorHandler
->UpdatePosition(aEventModelPosition
, rEvent
.mnAction
);
713 // sal_uInt16 nIndex = DetermineInsertPosition(*pDragTransferable);
715 // Do not process the insertion when it is trivial,
716 // i.e. would insert pages at their original place.
717 if (IsInsertionTrivial(pDragTransferable
, rEvent
.mnAction
))
720 // Tell the insertion indicator handler to hide before the model
721 // is modified. Doing it later may result in page objects whose
722 // animation state is not properly reset because they are then
723 // in another run then before the model change.
724 pInsertionIndicatorHandler
->End(Animator::AM_Immediate
);
728 SlideSorterController::ModelChangeLock
aModelChangeLock (mrController
);
730 // Handle a general drop operation.
731 mxUndoContext
.reset(new UndoContext (
732 mrSlideSorter
.GetModel().GetDocument(),
733 mrSlideSorter
.GetViewShell()->GetViewShellBase().GetMainViewShell()));
734 mxSelectionObserverContext
.reset(new SelectionObserver::Context(mrSlideSorter
));
736 HandlePageDrop(*pDragTransferable
);
737 nResult
= rEvent
.mnAction
;
739 // We leave the undo context alive for when moving or
740 // copying inside one view then the actions in
741 // NotifyDragFinished should be covered as well as
742 // well as the ones above.
745 // When the pages originated in another slide sorter then
746 // only that is notified automatically about the drag
747 // operation being finished. Because the target slide sorter
748 // has be notified, too, add a callback for that.
749 ::boost::shared_ptr
<TransferableData
> pSlideSorterTransferable (
750 TransferableData::GetFromTransferable(pDragTransferable
));
751 BOOST_ASSERT(pSlideSorterTransferable
);
752 if (pSlideSorterTransferable
753 && pSlideSorterTransferable
->GetSourceViewShell() != mrSlideSorter
.GetViewShell())
755 DragFinished(nResult
);
758 // Notify the receiving selection function that drag-and-drop is
759 // finished and the substitution handler can be released.
760 ::rtl::Reference
<SelectionFunction
> pFunction (
761 mrController
.GetCurrentSelectionFunction());
763 pFunction
->NotifyDragFinished();
768 nResult
= ExecuteOrAcceptShapeDrop(
786 bool Clipboard::IsInsertionTrivial (
787 SdTransferable
* pTransferable
,
788 const sal_Int8 nDndAction
) const
790 ::boost::shared_ptr
<TransferableData
> pSlideSorterTransferable (
791 TransferableData::GetFromTransferable(pTransferable
));
792 if (pSlideSorterTransferable
793 && pSlideSorterTransferable
->GetSourceViewShell() != mrSlideSorter
.GetViewShell())
795 return mrController
.GetInsertionIndicatorHandler()->IsInsertionTrivial(nDndAction
);
798 void Clipboard::Abort()
800 if (mxSelectionObserverContext
)
802 mxSelectionObserverContext
->Abort();
803 mxSelectionObserverContext
.reset();
807 sal_uInt16
Clipboard::DetermineInsertPosition (const SdTransferable
& )
809 // Tell the model to move the dragged pages behind the one with the
810 // index nInsertionIndex which first has to be transformed into an index
811 // understandable by the document.
812 const sal_Int32
nInsertionIndex (
813 mrController
.GetInsertionIndicatorHandler()->GetInsertionPageIndex());
815 // Convert to insertion index to that of an SdModel.
816 if (nInsertionIndex
>= 0)
817 return mrSlideSorter
.GetModel().GetCoreIndex(nInsertionIndex
);
822 sal_uInt16
Clipboard::InsertSlides (
823 const SdTransferable
& rTransferable
,
824 sal_uInt16 nInsertPosition
)
826 sal_uInt16 nInsertedPageCount
= ViewClipboard::InsertSlides (
830 // Remember the inserted pages so that they can be selected when the
831 // operation is finished.
832 maPagesToSelect
.clear();
833 SdDrawDocument
* pDocument
= mrSlideSorter
.GetModel().GetDocument();
834 if (pDocument
!= NULL
)
835 for (sal_Int32 i
=0; i
<=nInsertedPageCount
; i
+=2)
836 maPagesToSelect
.push_back(
837 dynamic_cast<SdPage
*>(pDocument
->GetPage(nInsertPosition
+i
)));
839 mbUpdateSelectionPending
|= (nInsertedPageCount
>0);
841 return nInsertedPageCount
;
844 Clipboard::DropType
Clipboard::IsDropAccepted (DropTargetHelper
&) const
846 const SdTransferable
* pDragTransferable
= SD_MOD()->pTransferDrag
;
847 if (pDragTransferable
== NULL
)
850 if (pDragTransferable
->IsPageTransferable())
852 if (mrSlideSorter
.GetModel().GetEditMode() != EM_MASTERPAGE
)
858 const SdPageObjsTLB::SdPageObjsTransferable
* pPageObjsTransferable
859 = dynamic_cast<const SdPageObjsTLB::SdPageObjsTransferable
*>(pDragTransferable
);
860 if (pPageObjsTransferable
!= NULL
)
861 return DT_PAGE_FROM_NAVIGATOR
;
866 sal_Int8
Clipboard::ExecuteOrAcceptShapeDrop (
867 DropCommand eCommand
,
868 const Point
& rPosition
,
869 const void* pDropEvent
,
870 DropTargetHelper
& rTargetHelper
,
871 ::sd::Window
* pTargetWindow
,
875 sal_Int8 nResult
= 0;
877 // The dropping of a shape is accepted or executed only when there is
878 // DrawViewShell available to which we can forward this call. This has
879 // technical reasons: The actual code to accept or execute a shape drop
880 // is implemented in the ViewShell class and uses the page view of the
881 // main edit view. This is not possible without a DrawViewShell.
882 ::boost::shared_ptr
<DrawViewShell
> pDrawViewShell
;
883 if (mrSlideSorter
.GetViewShell() != NULL
)
884 pDrawViewShell
= ::boost::dynamic_pointer_cast
<DrawViewShell
>(
885 mrSlideSorter
.GetViewShell()->GetViewShellBase().GetMainViewShell());
886 if (pDrawViewShell
.get() != NULL
887 && (pDrawViewShell
->GetShellType() == ViewShell::ST_IMPRESS
888 || pDrawViewShell
->GetShellType() == ViewShell::ST_DRAW
))
890 // The drop is only accepted or executed when it takes place over a
891 // page object. Therefore we replace a missing page number by the
892 // number of the page under the mouse.
893 if (nPage
== SDRPAGE_NOTFOUND
)
895 model::SharedPageDescriptor
pDescriptor (
896 mrSlideSorter
.GetModel().GetPageDescriptor(
897 mrSlideSorter
.GetView().GetPageIndexAtPoint(rPosition
)));
899 nPage
= pDescriptor
->GetPageIndex();
902 // Now comes the code that is different for the Execute and Accept:
903 // We simply forward the call to the AcceptDrop() or ExecuteDrop()
904 // methods of the DrawViewShell in the center pane.
905 if (nPage
!= SDRPAGE_NOTFOUND
)
909 nResult
= pDrawViewShell
->AcceptDrop(
910 *static_cast<const AcceptDropEvent
*>(pDropEvent
),
918 nResult
= pDrawViewShell
->ExecuteDrop(
919 *static_cast<const ExecuteDropEvent
*>(pDropEvent
),
931 } } } // end of namespace ::sd::slidesorter::controller
933 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */