Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*************************************************************************
3 : : *
4 : : * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 : : *
6 : : * Copyright 2000, 2010 Oracle and/or its affiliates.
7 : : *
8 : : * OpenOffice.org - a multi-platform office productivity suite
9 : : *
10 : : * This file is part of OpenOffice.org.
11 : : *
12 : : * OpenOffice.org is free software: you can redistribute it and/or modify
13 : : * it under the terms of the GNU Lesser General Public License version 3
14 : : * only, as published by the Free Software Foundation.
15 : : *
16 : : * OpenOffice.org is distributed in the hope that it will be useful,
17 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 : : * GNU Lesser General Public License version 3 for more details
20 : : * (a copy is included in the LICENSE file that accompanied this code).
21 : : *
22 : : * You should have received a copy of the GNU Lesser General Public License
23 : : * version 3 along with OpenOffice.org. If not, see
24 : : * <http://www.openoffice.org/license.html>
25 : : * for a copy of the LGPLv3 License.
26 : : *
27 : : ************************************************************************/
28 : :
29 : :
30 : : #include "controller/SlsClipboard.hxx"
31 : :
32 : : #include "SlideSorterViewShell.hxx"
33 : : #include "SlideSorter.hxx"
34 : : #include "model/SlideSorterModel.hxx"
35 : : #include "model/SlsPageDescriptor.hxx"
36 : : #include "model/SlsPageEnumerationProvider.hxx"
37 : : #include "view/SlideSorterView.hxx"
38 : : #include "view/SlsTheme.hxx"
39 : : #include "controller/SlideSorterController.hxx"
40 : : #include "controller/SlsInsertionIndicatorHandler.hxx"
41 : : #include "controller/SlsPageSelector.hxx"
42 : : #include "controller/SlsSelectionFunction.hxx"
43 : : #include "controller/SlsCurrentSlideManager.hxx"
44 : : #include "controller/SlsScrollBarManager.hxx"
45 : : #include "controller/SlsFocusManager.hxx"
46 : : #include "controller/SlsSelectionManager.hxx"
47 : : #include "controller/SlsTransferable.hxx"
48 : : #include "controller/SlsSelectionObserver.hxx"
49 : : #include "controller/SlsVisibleAreaManager.hxx"
50 : : #include "cache/SlsPageCache.hxx"
51 : :
52 : : #include "ViewShellBase.hxx"
53 : : #include "DrawViewShell.hxx"
54 : : #include "Window.hxx"
55 : : #include "fupoor.hxx"
56 : : #include "fuzoom.hxx"
57 : : #include "fucushow.hxx"
58 : : #include "fusldlg.hxx"
59 : : #include "fuexpand.hxx"
60 : : #include "fusumry.hxx"
61 : : #include "app.hrc"
62 : : #include "glob.hrc"
63 : : #include "strings.hrc"
64 : : #include "sdresid.hxx"
65 : : #include "sdxfer.hxx"
66 : : #include "sdmod.hxx"
67 : : #include "ins_paste.hxx"
68 : : #include "drawdoc.hxx"
69 : : #include "DrawDocShell.hxx"
70 : : #include "sdpage.hxx"
71 : :
72 : : #include <com/sun/star/datatransfer/dnd/DNDConstants.hpp>
73 : : #include <sfx2/request.hxx>
74 : : #include <sfx2/viewfrm.hxx>
75 : : #include <sfx2/bindings.hxx>
76 : : #include <sfx2/docfile.hxx>
77 : : #include <svx/svxids.hrc>
78 : : #include <svx/svdstr.hrc>
79 : : #include <vcl/msgbox.hxx>
80 : : #include <tools/urlobj.hxx>
81 : : #include <rtl/ustring.hxx>
82 : : #include <osl/mutex.hxx>
83 : : #include <vcl/svapp.hxx>
84 : :
85 : : namespace sd { namespace slidesorter { namespace controller {
86 : :
87 : : namespace {
88 : : /** Temporarily deactivate slide tracking of the VisibleAreaManager.
89 : : This is used as a workaround to avoid unwanted repositioning of
90 : : the visible area when the selection of slides is copied to the
91 : : clipboard (cloning of slides leads to model change notifications
92 : : for the original model.)
93 : : */
94 : : class TemporarySlideTrackingDeactivator
95 : : {
96 : : public:
97 : 0 : TemporarySlideTrackingDeactivator (SlideSorterController& rController)
98 : : : mrController(rController),
99 : : mbIsCurrentSlideTrackingActive (
100 : 0 : mrController.GetVisibleAreaManager().IsCurrentSlideTrackingActive())
101 : : {
102 [ # # ]: 0 : if (mbIsCurrentSlideTrackingActive)
103 : 0 : mrController.GetVisibleAreaManager().DeactivateCurrentSlideTracking();
104 : 0 : }
105 : 0 : ~TemporarySlideTrackingDeactivator (void)
106 : : {
107 [ # # ]: 0 : if (mbIsCurrentSlideTrackingActive)
108 : 0 : mrController.GetVisibleAreaManager().ActivateCurrentSlideTracking();
109 : 0 : }
110 : :
111 : : private:
112 : : SlideSorterController& mrController;
113 : : const bool mbIsCurrentSlideTrackingActive;
114 : : };
115 : : } // end of anonymous namespace
116 : :
117 : :
118 : : class Clipboard::UndoContext
119 : : {
120 : : public:
121 : 0 : UndoContext (
122 : : SdDrawDocument* pDocument,
123 : : const ::boost::shared_ptr<ViewShell>& rpMainViewShell)
124 : : : mpDocument(pDocument),
125 : 0 : mpMainViewShell(rpMainViewShell)
126 : : {
127 [ # # ][ # # ]: 0 : if (mpDocument!=NULL && mpDocument->IsUndoEnabled())
[ # # ][ # # ]
128 : : {
129 [ # # ][ # # ]: 0 : if (mpMainViewShell && mpMainViewShell->GetShellType() == ViewShell::ST_DRAW)
[ # # ][ # # ]
130 [ # # ][ # # ]: 0 : mpDocument->BegUndo(String(SdResId(STRING_DRAG_AND_DROP_PAGES)));
[ # # ][ # # ]
131 : : else
132 [ # # ][ # # ]: 0 : mpDocument->BegUndo(String(SdResId(STRING_DRAG_AND_DROP_SLIDES)));
[ # # ][ # # ]
133 : : }
134 : 0 : }
135 : :
136 : 0 : ~UndoContext (void)
137 : 0 : {
138 [ # # ][ # # ]: 0 : if (mpDocument!=NULL && mpDocument->IsUndoEnabled())
[ # # ][ # # ]
139 [ # # ]: 0 : mpDocument->EndUndo();
140 [ # # ][ # # ]: 0 : if (mpMainViewShell && mpMainViewShell->GetViewFrame()!=NULL)
[ # # ][ # # ]
141 : : {
142 [ # # ]: 0 : SfxBindings& rBindings = mpMainViewShell->GetViewFrame()->GetBindings();
143 [ # # ]: 0 : rBindings.Invalidate(SID_UNDO);
144 [ # # ]: 0 : rBindings.Invalidate(SID_REDO);
145 : : }
146 : 0 : }
147 : : private:
148 : : SdDrawDocument* mpDocument;
149 : : ::boost::shared_ptr<ViewShell> mpMainViewShell;
150 : : };
151 : :
152 : :
153 : :
154 : :
155 : 130 : Clipboard::Clipboard (SlideSorter& rSlideSorter)
156 : 130 : : ViewClipboard(rSlideSorter.GetView()),
157 : : mrSlideSorter(rSlideSorter),
158 [ + - ]: 130 : mrController(mrSlideSorter.GetController()),
159 : : maPagesToRemove(),
160 : : maPagesToSelect(),
161 : : mbUpdateSelectionPending(false),
162 : : mpUndoContext(),
163 : : mpSelectionObserverContext(),
164 [ + - ][ + - ]: 260 : mnDragFinishedUserEventId(0)
165 : : {
166 : 130 : }
167 : :
168 : :
169 : :
170 : :
171 [ + - ][ + - ]: 130 : Clipboard::~Clipboard (void)
172 : : {
173 [ - + ]: 130 : if (mnDragFinishedUserEventId != 0)
174 [ # # ]: 0 : Application::RemoveUserEvent(mnDragFinishedUserEventId);
175 [ - + ]: 260 : }
176 : :
177 : :
178 : :
179 : :
180 : : /** With the current implementation the forwarded calls to the current
181 : : function will come back eventually to call the local Do(Cut|Copy|Paste)
182 : : methods. A shortcut is possible but would be an unclean hack.
183 : : */
184 : 0 : void Clipboard::HandleSlotCall (SfxRequest& rRequest)
185 : : {
186 [ # # ]: 0 : ViewShell* pViewShell = mrSlideSorter.GetViewShell();
187 : 0 : FunctionReference xFunc;
188 [ # # ]: 0 : if (pViewShell != NULL)
189 [ # # ][ # # ]: 0 : xFunc = pViewShell->GetCurrentFunction();
[ # # ]
190 [ # # # # : 0 : switch (rRequest.GetSlot())
# ]
191 : : {
192 : : case SID_CUT:
193 [ # # ][ # # ]: 0 : if (mrSlideSorter.GetModel().GetEditMode() != EM_MASTERPAGE)
[ # # ]
194 : : {
195 [ # # ]: 0 : if(xFunc.is())
196 [ # # ]: 0 : xFunc->DoCut();
197 : : else
198 [ # # ]: 0 : DoCut();
199 : : }
200 [ # # ]: 0 : rRequest.Done();
201 : 0 : break;
202 : :
203 : : case SID_COPY:
204 [ # # ][ # # ]: 0 : if (mrSlideSorter.GetModel().GetEditMode() != EM_MASTERPAGE)
[ # # ]
205 : : {
206 [ # # ]: 0 : if(xFunc.is())
207 [ # # ]: 0 : xFunc->DoCopy();
208 : : else
209 [ # # ]: 0 : DoCopy();
210 : : }
211 [ # # ]: 0 : rRequest.Done();
212 : 0 : break;
213 : :
214 : : case SID_PASTE:
215 : : // Prevent redraws while inserting pages from the clipboard
216 : : // because the intermediate inconsistent state might lead to
217 : : // a crash.
218 [ # # ][ # # ]: 0 : if (mrSlideSorter.GetModel().GetEditMode() != EM_MASTERPAGE)
[ # # ]
219 : : {
220 [ # # ]: 0 : view::SlideSorterView::DrawLock aLock (mrSlideSorter);
221 [ # # ]: 0 : SelectionObserver::Context aContext (mrSlideSorter);
222 [ # # ]: 0 : if(xFunc.is())
223 [ # # ]: 0 : xFunc->DoPaste();
224 : : else
225 [ # # ][ # # ]: 0 : DoPaste();
[ # # ]
226 : : }
227 [ # # ]: 0 : rRequest.Done();
228 : 0 : break;
229 : :
230 : : case SID_DELETE:
231 [ # # ]: 0 : DoDelete();
232 [ # # ]: 0 : rRequest.Done();
233 : 0 : break;
234 [ # # ]: 0 : }
235 : 0 : }
236 : :
237 : :
238 : :
239 : :
240 : 0 : void Clipboard::DoCut (::Window* pWindow)
241 : : {
242 [ # # ]: 0 : if (mrSlideSorter.GetModel().GetPageCount() > 1)
243 : : {
244 : 0 : DoCopy(pWindow);
245 : 0 : DoDelete(pWindow);
246 : : }
247 : 0 : }
248 : :
249 : :
250 : :
251 : :
252 : 0 : void Clipboard::DoDelete (::Window* )
253 : : {
254 [ # # ]: 0 : if (mrSlideSorter.GetModel().GetPageCount() > 1)
255 : : {
256 [ # # ]: 0 : mrController.GetSelectionManager()->DeleteSelectedPages();
257 : : }
258 : 0 : }
259 : :
260 : :
261 : :
262 : :
263 : 0 : void Clipboard::DoCopy (::Window* pWindow )
264 : : {
265 : 0 : CreateSlideTransferable( pWindow, sal_False );
266 : 0 : }
267 : :
268 : :
269 : :
270 : :
271 : 0 : void Clipboard::DoPaste (::Window* pWindow)
272 : : {
273 : 0 : SdTransferable* pClipTransferable = SD_MOD()->pTransferClip;
274 : :
275 [ # # ][ # # ]: 0 : if (pClipTransferable!=NULL && pClipTransferable->IsPageTransferable())
[ # # ]
276 : : {
277 : 0 : sal_Int32 nInsertPosition = GetInsertionPosition(pWindow);
278 : :
279 [ # # ]: 0 : if (nInsertPosition >= 0)
280 : : {
281 : : // Paste the pages from the clipboard.
282 : 0 : sal_Int32 nInsertPageCount = PasteTransferable(nInsertPosition);
283 : : // Select the pasted pages and make the first of them the
284 : : // current page.
285 [ # # ]: 0 : mrSlideSorter.GetContentWindow()->GrabFocus();
286 : 0 : SelectPageRange(nInsertPosition, nInsertPageCount);
287 : : }
288 : : }
289 : 0 : }
290 : :
291 : :
292 : :
293 : :
294 : 0 : sal_Int32 Clipboard::GetInsertionPosition (::Window* pWindow)
295 : : {
296 : 0 : sal_Int32 nInsertPosition = -1;
297 : :
298 : : // Determine the insertion position:
299 : : // a) When the insertion indicator is visible, then at that position.
300 : : // b) When the focus indicator is visible, then before or after the
301 : : // focused page, depending on user input to a dialog.
302 : : // c) When there is a selection but no focus, then after the
303 : : // selection.
304 : : // d) After the last page when there is no selection and no focus.
305 : :
306 : : ::boost::shared_ptr<controller::InsertionIndicatorHandler> pInsertionIndicatorHandler (
307 [ # # ]: 0 : mrController.GetInsertionIndicatorHandler());
308 [ # # ][ # # ]: 0 : if (pInsertionIndicatorHandler->IsActive())
309 : : {
310 : : // Use the insertion index of an active insertion indicator.
311 [ # # ]: 0 : nInsertPosition = pInsertionIndicatorHandler->GetInsertionPageIndex();
312 : : }
313 [ # # ][ # # ]: 0 : else if (mrController.GetSelectionManager()->GetInsertionPosition() >= 0)
[ # # ][ # # ]
314 : : {
315 : : // Use the insertion index of an insertion indicator that has been
316 : : // deactivated a short while ago.
317 [ # # ][ # # ]: 0 : nInsertPosition = mrController.GetSelectionManager()->GetInsertionPosition();
[ # # ]
318 : : }
319 [ # # ][ # # ]: 0 : else if (mrController.GetFocusManager().IsFocusShowing())
[ # # ]
320 : : {
321 : : // Use the focus to determine the insertion position.
322 [ # # ]: 0 : SdInsertPasteDlg aDialog (pWindow);
323 [ # # ][ # # ]: 0 : if (aDialog.Execute() == RET_OK)
324 : : {
325 [ # # ][ # # ]: 0 : nInsertPosition = mrController.GetFocusManager().GetFocusedPageIndex();
326 [ # # ][ # # ]: 0 : if ( ! aDialog.IsInsertBefore())
327 : 0 : nInsertPosition ++;
328 [ # # ]: 0 : }
329 : : }
330 : :
331 [ # # ]: 0 : return nInsertPosition;
332 : : }
333 : :
334 : :
335 : :
336 : :
337 : 0 : sal_Int32 Clipboard::PasteTransferable (sal_Int32 nInsertPosition)
338 : : {
339 : 0 : SdTransferable* pClipTransferable = SD_MOD()->pTransferClip;
340 : 0 : model::SlideSorterModel& rModel (mrSlideSorter.GetModel());
341 : 0 : bool bMergeMasterPages = !pClipTransferable->HasSourceDoc (rModel.GetDocument());
342 : 0 : sal_uInt16 nInsertIndex (rModel.GetCoreIndex(nInsertPosition));
343 : 0 : sal_Int32 nInsertPageCount (0);
344 [ # # ]: 0 : if (pClipTransferable->HasPageBookmarks())
345 : : {
346 : 0 : const std::vector<rtl::OUString> &rBookmarkList = pClipTransferable->GetPageBookmarks();
347 [ # # ]: 0 : const SolarMutexGuard aGuard;
348 : :
349 : 0 : nInsertPageCount = (sal_uInt16) rBookmarkList.size();
350 : : rModel.GetDocument()->InsertBookmarkAsPage(
351 : : rBookmarkList,
352 : : NULL,
353 : : sal_False,
354 : : sal_False,
355 : : nInsertIndex,
356 : : sal_False,
357 : : pClipTransferable->GetPageDocShell(),
358 : : sal_True,
359 : : bMergeMasterPages,
360 [ # # ][ # # ]: 0 : sal_False);
[ # # ]
361 : : }
362 : : else
363 : : {
364 : 0 : SfxObjectShell* pShell = pClipTransferable->GetDocShell();
365 : 0 : DrawDocShell* pDataDocSh = (DrawDocShell*)pShell;
366 : 0 : SdDrawDocument* pDataDoc = pDataDocSh->GetDoc();
367 : :
368 [ # # ]: 0 : if (pDataDoc!=NULL
[ # # # # ]
369 : 0 : && pDataDoc->GetSdPageCount(PK_STANDARD))
370 : : {
371 [ # # ]: 0 : const SolarMutexGuard aGuard;
372 : :
373 [ # # ]: 0 : bMergeMasterPages = (pDataDoc != rModel.GetDocument());
374 [ # # ]: 0 : nInsertPageCount = pDataDoc->GetSdPageCount( PK_STANDARD );
375 : : rModel.GetDocument()->InsertBookmarkAsPage(
376 : : std::vector<rtl::OUString>(),
377 : : NULL,
378 : : sal_False,
379 : : sal_False,
380 : : nInsertIndex,
381 : : sal_False,
382 : : pDataDocSh,
383 : : sal_True,
384 : : bMergeMasterPages,
385 [ # # ][ # # ]: 0 : sal_False);
[ # # ][ # # ]
386 : : }
387 : : }
388 : 0 : mrController.HandleModelChange();
389 : 0 : return nInsertPageCount;
390 : : }
391 : :
392 : :
393 : :
394 : :
395 : 0 : void Clipboard::SelectPageRange (sal_Int32 nFirstIndex, sal_Int32 nPageCount)
396 : : {
397 : : // Select the newly inserted pages. That are the nInsertPageCount pages
398 : : // after the nInsertIndex position.
399 : 0 : PageSelector& rSelector (mrController.GetPageSelector());
400 : 0 : rSelector.DeselectAllPages();
401 [ # # ]: 0 : for (sal_uInt16 i=0; i<nPageCount; i++)
402 : : {
403 : : model::SharedPageDescriptor pDescriptor (
404 [ # # ][ # # ]: 0 : mrSlideSorter.GetModel().GetPageDescriptor(nFirstIndex + i));
405 [ # # ]: 0 : if (pDescriptor.get() != NULL)
406 : : {
407 [ # # ]: 0 : rSelector.SelectPage(pDescriptor);
408 : : // The first page of the new selection is made the current page.
409 [ # # ]: 0 : if (i == 0)
410 : : {
411 [ # # ][ # # ]: 0 : mrController.GetCurrentSlideManager()->SwitchCurrentSlide(pDescriptor);
[ # # ]
412 : : }
413 : : }
414 [ # # ]: 0 : }
415 : 0 : }
416 : :
417 : :
418 : :
419 : :
420 : 0 : void Clipboard::CreateSlideTransferable (
421 : : ::Window* pWindow,
422 : : bool bDrag)
423 : : {
424 [ # # ]: 0 : std::vector<rtl::OUString> aBookmarkList;
425 : :
426 : : // Insert all selected pages into a bookmark list and remember them in
427 : : // maPagesToRemove for possible later removal.
428 : : model::PageEnumeration aSelectedPages
429 : : (model::PageEnumerationProvider::CreateSelectedPagesEnumeration(
430 [ # # ][ # # ]: 0 : mrSlideSorter.GetModel()));
431 [ # # ][ # # ]: 0 : while (aSelectedPages.HasMoreElements())
432 : : {
433 [ # # ]: 0 : model::SharedPageDescriptor pDescriptor (aSelectedPages.GetNextElement());
434 [ # # ][ # # ]: 0 : aBookmarkList.push_back(pDescriptor->GetPage()->GetName());
[ # # ][ # # ]
435 [ # # ][ # # ]: 0 : maPagesToRemove.push_back (pDescriptor->GetPage());
436 [ # # ]: 0 : }
437 : :
438 : : // Create a small set of representatives of the selection for which
439 : : // previews are included into the transferable so that an insertion
440 : : // indicator can be rendered.
441 [ # # ]: 0 : aSelectedPages.Rewind();
442 [ # # ]: 0 : ::std::vector<Transferable::Representative> aRepresentatives;
443 [ # # ]: 0 : aRepresentatives.reserve(3);
444 : : ::boost::shared_ptr<cache::PageCache> pPreviewCache (
445 [ # # ][ # # ]: 0 : mrSlideSorter.GetView().GetPreviewCache());
446 [ # # ][ # # ]: 0 : while (aSelectedPages.HasMoreElements())
447 : : {
448 [ # # ]: 0 : model::SharedPageDescriptor pDescriptor (aSelectedPages.GetNextElement());
449 [ # # ][ # # ]: 0 : if ( ! pDescriptor || pDescriptor->GetPage()==NULL)
[ # # ][ # # ]
450 : 0 : continue;
451 [ # # ][ # # ]: 0 : Bitmap aPreview (pPreviewCache->GetPreviewBitmap(pDescriptor->GetPage(), false));
452 : : aRepresentatives.push_back(Transferable::Representative(
453 : : aPreview,
454 [ # # ][ # # ]: 0 : pDescriptor->HasState(model::PageDescriptor::ST_Excluded)));
[ # # ][ # # ]
455 [ # # ]: 0 : if (aRepresentatives.size() >= 3)
456 : : break;
457 [ # # ][ # # ]: 0 : }
[ # # ]
[ # # # ]
458 : :
459 [ # # ]: 0 : if (!aBookmarkList.empty())
460 : : {
461 [ # # ][ # # ]: 0 : mrSlideSorter.GetView().BrkAction();
462 [ # # ][ # # ]: 0 : SdDrawDocument* pDocument = mrSlideSorter.GetModel().GetDocument();
463 : : SdTransferable* pTransferable = new Transferable (
464 : : pDocument,
465 : : NULL,
466 : : sal_False,
467 [ # # ]: 0 : dynamic_cast<SlideSorterViewShell*>(mrSlideSorter.GetViewShell()),
468 [ # # ][ # # ]: 0 : aRepresentatives);
469 : :
470 [ # # ]: 0 : if (bDrag)
471 [ # # ]: 0 : SD_MOD()->pTransferDrag = pTransferable;
472 : : else
473 [ # # ]: 0 : SD_MOD()->pTransferClip = pTransferable;
474 : :
475 : 0 : pDocument->CreatingDataObj (pTransferable);
476 [ # # ][ # # ]: 0 : pTransferable->SetWorkDocument( dynamic_cast<SdDrawDocument*>(pDocument->AllocModel()) );
477 : 0 : pDocument->CreatingDataObj (NULL);
478 [ # # ]: 0 : TransferableObjectDescriptor aObjDesc;
479 : 0 : pTransferable->GetWorkDocument()->GetDocSh()
480 [ # # ]: 0 : ->FillTransferableObjectDescriptor (aObjDesc);
481 : :
482 [ # # ]: 0 : if (pDocument->GetDocSh() != NULL)
483 : 0 : aObjDesc.maDisplayName = pDocument->GetDocSh()
484 [ # # ][ # # ]: 0 : ->GetMedium()->GetURLObject().GetURLNoPass();
[ # # ]
485 : :
486 : 0 : ::Window* pActionWindow = pWindow;
487 [ # # ]: 0 : if (pActionWindow == NULL)
488 : : {
489 [ # # ]: 0 : ViewShell* pViewShell = mrSlideSorter.GetViewShell();
490 [ # # ]: 0 : if (pViewShell != NULL)
491 [ # # ]: 0 : pActionWindow = pViewShell->GetActiveWindow();
492 : : }
493 : :
494 : : pTransferable->SetStartPos (pActionWindow->PixelToLogic(
495 [ # # ][ # # ]: 0 : pActionWindow->GetPointerPosPixel()));
496 [ # # ]: 0 : pTransferable->SetObjectDescriptor (aObjDesc);
497 : :
498 : : {
499 [ # # ]: 0 : TemporarySlideTrackingDeactivator aDeactivator (mrController);
500 [ # # ][ # # ]: 0 : pTransferable->SetPageBookmarks (aBookmarkList, !bDrag);
501 : : }
502 : :
503 [ # # ]: 0 : if (bDrag)
504 : : {
505 [ # # ]: 0 : pTransferable->SetView (&mrSlideSorter.GetView());
506 : 0 : sal_Int8 nDragSourceActions (DND_ACTION_COPY);
507 : : // The move action is available only when not all pages would be
508 : : // moved. Otherwise an empty document would remain. Crash.
509 [ # # ][ # # ]: 0 : sal_Int32 nRemainingPages = mrSlideSorter.GetModel().GetPageCount() - aBookmarkList.size();
510 [ # # ]: 0 : if (nRemainingPages > 0)
511 : 0 : nDragSourceActions |= DND_ACTION_MOVE;
512 [ # # ]: 0 : pTransferable->StartDrag (pActionWindow, nDragSourceActions);
513 : : }
514 : : else
515 [ # # ][ # # ]: 0 : pTransferable->CopyToClipboard (pActionWindow);
516 [ # # ][ # # ]: 0 : }
517 : 0 : }
518 : :
519 : :
520 : :
521 : :
522 : 0 : void Clipboard::StartDrag (
523 : : const Point& rPosition,
524 : : ::Window* pWindow)
525 : : {
526 : 0 : maPagesToRemove.clear();
527 : 0 : maPagesToSelect.clear();
528 : 0 : mbUpdateSelectionPending = false;
529 : 0 : CreateSlideTransferable(pWindow, sal_True);
530 : :
531 : : mrController.GetInsertionIndicatorHandler()->UpdatePosition(
532 : : rPosition,
533 [ # # ]: 0 : InsertionIndicatorHandler::UnknownMode);
534 : 0 : }
535 : :
536 : :
537 : :
538 : :
539 : 0 : void Clipboard::DragFinished (sal_Int8 nDropAction)
540 : : {
541 : 0 : SdTransferable* pDragTransferable = SD_MOD()->pTransferDrag;
542 [ # # ]: 0 : if (pDragTransferable != NULL)
543 : 0 : pDragTransferable->SetView (NULL);
544 : :
545 [ # # ]: 0 : if (mnDragFinishedUserEventId == 0)
546 : : {
547 [ # # ]: 0 : if ( ! Application::PostUserEvent(
548 : : mnDragFinishedUserEventId,
549 : : LINK(this, Clipboard, ProcessDragFinished),
550 [ # # ]: 0 : reinterpret_cast<void*>(nDropAction)))
551 : : {
552 : 0 : mnDragFinishedUserEventId = 0;
553 : : }
554 : : }
555 : 0 : }
556 : :
557 : :
558 : :
559 : :
560 : 0 : IMPL_LINK(Clipboard, ProcessDragFinished, void*, pUserData)
561 : : {
562 : 0 : const sal_Int8 nDropAction (static_cast<sal_Int8>(reinterpret_cast<sal_IntPtr>(pUserData)));
563 : :
564 : 0 : mnDragFinishedUserEventId = 0;
565 : :
566 : : // Hide the substitution display and insertion indicator.
567 [ # # ]: 0 : ::rtl::Reference<SelectionFunction> pFunction (mrController.GetCurrentSelectionFunction());
568 [ # # ]: 0 : if (pFunction.is())
569 [ # # ]: 0 : pFunction->NotifyDragFinished();
570 : :
571 [ # # ]: 0 : PageSelector& rSelector (mrController.GetPageSelector());
572 [ # # # # ]: 0 : if ((nDropAction & DND_ACTION_MOVE) != 0
[ # # ]
573 : 0 : && ! maPagesToRemove.empty())
574 : : {
575 : : // Remove the pages that have been moved to another place (possibly
576 : : // in the same document.)
577 [ # # ]: 0 : rSelector.DeselectAllPages();
578 : 0 : PageList::iterator aDraggedPage;
579 [ # # ][ # # ]: 0 : for (aDraggedPage=maPagesToRemove.begin();
580 : 0 : aDraggedPage!=maPagesToRemove.end();
581 : : ++aDraggedPage)
582 : : {
583 [ # # ]: 0 : rSelector.SelectPage(*aDraggedPage);
584 : : }
585 [ # # ][ # # ]: 0 : mrController.GetSelectionManager()->DeleteSelectedPages();
[ # # ]
586 : : }
587 [ # # ]: 0 : mpUndoContext.reset();
588 [ # # ]: 0 : mpSelectionObserverContext.reset();
589 : :
590 [ # # ]: 0 : return 1;
591 : : }
592 : :
593 : :
594 : :
595 : :
596 : 0 : sal_Int8 Clipboard::AcceptDrop (
597 : : const AcceptDropEvent& rEvent,
598 : : DropTargetHelper& rTargetHelper,
599 : : ::sd::Window* pTargetWindow,
600 : : sal_uInt16 nPage,
601 : : sal_uInt16 nLayer)
602 : : {
603 : 0 : sal_Int8 nAction (DND_ACTION_NONE);
604 : :
605 : 0 : const Clipboard::DropType eDropType (IsDropAccepted());
606 : :
607 [ # # # ]: 0 : switch (eDropType)
608 : : {
609 : : case DT_PAGE:
610 : : {
611 : : // Accept a drop.
612 : 0 : nAction = rEvent.mnAction;
613 : :
614 : : // Use the copy action when the drop action is the default, i.e. not
615 : : // explicitly set to move or link, and when the source and
616 : : // target models are not the same.
617 : 0 : const SdTransferable* pDragTransferable = SD_MOD()->pTransferDrag;
618 [ # # # # ]: 0 : if (pDragTransferable != NULL
[ # # ]
[ # # # # ]
619 : 0 : && pDragTransferable->IsPageTransferable()
620 : : && ((rEvent.maDragEvent.DropAction
621 : : & ::com::sun::star::datatransfer::dnd::DNDConstants::ACTION_DEFAULT) != 0)
622 : 0 : && (mrSlideSorter.GetModel().GetDocument()->GetDocSh()
623 : 0 : != pDragTransferable->GetPageDocShell()))
624 : : {
625 : 0 : nAction = DND_ACTION_COPY;
626 : : }
627 [ # # ][ # # ]: 0 : else if (mrController.GetInsertionIndicatorHandler()->IsInsertionTrivial(nAction))
628 : : {
629 : 0 : nAction = DND_ACTION_NONE;
630 : : }
631 : :
632 : : // Show the insertion marker and the substitution for a drop.
633 : : SelectionFunction* pSelectionFunction = dynamic_cast<SelectionFunction*>(
634 [ # # ]: 0 : mrSlideSorter.GetViewShell()->GetCurrentFunction().get());
635 [ # # ]: 0 : if (pSelectionFunction != NULL)
636 : 0 : pSelectionFunction->MouseDragged(rEvent, nAction);
637 : :
638 : : // Scroll the window when the mouse reaches the window border.
639 : : // mrController.GetScrollBarManager().AutoScroll (rEvent.maPosPixel);
640 : : }
641 : 0 : break;
642 : :
643 : : case DT_SHAPE:
644 : : nAction = ExecuteOrAcceptShapeDrop(
645 : : DC_ACCEPT,
646 : : rEvent.maPosPixel,
647 : : &rEvent,
648 : : rTargetHelper,
649 : : pTargetWindow,
650 : : nPage,
651 : 0 : nLayer);
652 : 0 : break;
653 : :
654 : : default:
655 : 0 : nAction = DND_ACTION_NONE;
656 : 0 : break;
657 : : }
658 : :
659 : 0 : return nAction;
660 : : }
661 : :
662 : :
663 : :
664 : :
665 : 0 : sal_Int8 Clipboard::ExecuteDrop (
666 : : const ExecuteDropEvent& rEvent,
667 : : DropTargetHelper& rTargetHelper,
668 : : ::sd::Window* pTargetWindow,
669 : : sal_uInt16 nPage,
670 : : sal_uInt16 nLayer)
671 : : {
672 : 0 : sal_Int8 nResult = DND_ACTION_NONE;
673 : 0 : mpUndoContext.reset();
674 : :
675 [ # # # ]: 0 : switch (IsDropAccepted())
676 : : {
677 : : case DT_PAGE:
678 : : {
679 [ # # ]: 0 : const SdTransferable* pDragTransferable = SD_MOD()->pTransferDrag;
680 : : const Point aEventModelPosition (
681 [ # # ]: 0 : pTargetWindow->PixelToLogic (rEvent.maPosPixel));
682 : 0 : const sal_Int32 nXOffset (labs (pDragTransferable->GetStartPos().X()
683 : 0 : - aEventModelPosition.X()));
684 : 0 : const sal_Int32 nYOffset (labs (pDragTransferable->GetStartPos().Y()
685 : 0 : - aEventModelPosition.Y()));
686 : : bool bContinue =
687 [ # # ]: 0 : ( pDragTransferable->GetView() != &mrSlideSorter.GetView() )
688 [ # # ][ # # ]: 0 : || ( nXOffset >= 2 && nYOffset >= 2 );
[ # # ]
689 : :
690 : : ::boost::shared_ptr<InsertionIndicatorHandler> pInsertionIndicatorHandler(
691 [ # # ]: 0 : mrController.GetInsertionIndicatorHandler());
692 : : // Get insertion position and then turn off the insertion indicator.
693 [ # # ]: 0 : pInsertionIndicatorHandler->UpdatePosition(aEventModelPosition, rEvent.mnAction);
694 : : // sal_uInt16 nIndex = DetermineInsertPosition(*pDragTransferable);
695 : :
696 : : // Do not process the insertion when it is trivial,
697 : : // i.e. would insert pages at their original place.
698 [ # # ][ # # ]: 0 : if (pInsertionIndicatorHandler->IsInsertionTrivial(rEvent.mnAction))
699 : 0 : bContinue = false;
700 : :
701 : : // Tell the insertion indicator handler to hide before the model
702 : : // is modified. Doing it later may result in page objects whose
703 : : // animation state is not properly reset because they are then
704 : : // in another run then before the model change.
705 [ # # ]: 0 : pInsertionIndicatorHandler->End(Animator::AM_Immediate);
706 : :
707 [ # # ]: 0 : if (bContinue)
708 : : {
709 [ # # ]: 0 : SlideSorterController::ModelChangeLock aModelChangeLock (mrController);
710 : :
711 : : // Handle a general drop operation.
712 : : mpUndoContext.reset(new UndoContext (
713 [ # # ]: 0 : mrSlideSorter.GetModel().GetDocument(),
714 [ # # ][ # # ]: 0 : mrSlideSorter.GetViewShell()->GetViewShellBase().GetMainViewShell()));
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
715 [ # # ][ # # ]: 0 : mpSelectionObserverContext.reset(new SelectionObserver::Context(mrSlideSorter));
[ # # ]
716 : :
717 [ # # ]: 0 : HandlePageDrop(*pDragTransferable);
718 [ # # ]: 0 : nResult = rEvent.mnAction;
719 : :
720 : : // We leave the undo context alive for when moving or
721 : : // copying inside one view then the actions in
722 : : // NotifyDragFinished should be covered as well as
723 : : // well as the ones above.
724 : : }
725 : :
726 : : // Notify the receiving selection function that drag-and-drop is
727 : : // finished and the substitution handler can be released.
728 : : ::rtl::Reference<SelectionFunction> pFunction (
729 [ # # ]: 0 : mrController.GetCurrentSelectionFunction());
730 [ # # ]: 0 : if (pFunction.is())
731 [ # # ][ # # ]: 0 : pFunction->NotifyDragFinished();
[ # # ]
732 : : }
733 : 0 : break;
734 : :
735 : : case DT_SHAPE:
736 : : nResult = ExecuteOrAcceptShapeDrop(
737 : : DC_EXECUTE,
738 : : rEvent.maPosPixel,
739 : : &rEvent,
740 : : rTargetHelper,
741 : : pTargetWindow,
742 : : nPage,
743 : 0 : nLayer);
744 : 0 : break;
745 : : default:
746 : 0 : break;
747 : : }
748 : :
749 : 0 : return nResult;
750 : : }
751 : :
752 : :
753 : :
754 : :
755 : 0 : void Clipboard::Abort (void)
756 : : {
757 [ # # ]: 0 : if (mpSelectionObserverContext)
758 : : {
759 : 0 : mpSelectionObserverContext->Abort();
760 : 0 : mpSelectionObserverContext.reset();
761 : : }
762 : 0 : }
763 : :
764 : :
765 : :
766 : :
767 : 0 : sal_uInt16 Clipboard::DetermineInsertPosition (const SdTransferable& )
768 : : {
769 : : // Tell the model to move the dragged pages behind the one with the
770 : : // index nInsertionIndex which first has to be transformed into an index
771 : : // understandable by the document.
772 : : const sal_Int32 nInsertionIndex (
773 [ # # ]: 0 : mrController.GetInsertionIndicatorHandler()->GetInsertionPageIndex());
774 : :
775 : : // Convert to insertion index to that of an SdModel.
776 [ # # ]: 0 : if (nInsertionIndex >= 0)
777 : 0 : return mrSlideSorter.GetModel().GetCoreIndex(nInsertionIndex);
778 : : else
779 : 0 : return 0;
780 : : }
781 : :
782 : :
783 : :
784 : :
785 : 0 : sal_uInt16 Clipboard::InsertSlides (
786 : : const SdTransferable& rTransferable,
787 : : sal_uInt16 nInsertPosition)
788 : : {
789 : : sal_uInt16 nInsertedPageCount = ViewClipboard::InsertSlides (
790 : : rTransferable,
791 : 0 : nInsertPosition);
792 : :
793 : : // Remember the inserted pages so that they can be selected when the
794 : : // operation is finished.
795 : 0 : maPagesToSelect.clear();
796 : 0 : SdDrawDocument* pDocument = mrSlideSorter.GetModel().GetDocument();
797 [ # # ]: 0 : if (pDocument != NULL)
798 [ # # ]: 0 : for (sal_Int32 i=0; i<=nInsertedPageCount; i+=2)
799 : : maPagesToSelect.push_back(
800 [ # # ][ # # ]: 0 : dynamic_cast<SdPage*>(pDocument->GetPage(nInsertPosition+i)));
801 : :
802 : 0 : mbUpdateSelectionPending |= (nInsertedPageCount>0);
803 : :
804 : 0 : return nInsertedPageCount;
805 : : }
806 : :
807 : :
808 : :
809 : :
810 : 0 : Clipboard::DropType Clipboard::IsDropAccepted (void) const
811 : : {
812 : 0 : DropType eResult (DT_NONE);
813 : :
814 : 0 : const SdTransferable* pDragTransferable = SD_MOD()->pTransferDrag;
815 [ # # ]: 0 : if (pDragTransferable != NULL)
816 : : {
817 [ # # ]: 0 : if (pDragTransferable->IsPageTransferable())
818 : : {
819 [ # # ]: 0 : if (mrSlideSorter.GetModel().GetEditMode() != EM_MASTERPAGE)
820 : 0 : eResult = DT_PAGE;
821 : : }
822 : : else
823 : : {
824 : 0 : eResult = DT_SHAPE;
825 : : }
826 : : }
827 : :
828 : 0 : return eResult;
829 : : }
830 : :
831 : :
832 : :
833 : :
834 : 0 : sal_Int8 Clipboard::ExecuteOrAcceptShapeDrop (
835 : : DropCommand eCommand,
836 : : const Point& rPosition,
837 : : const void* pDropEvent,
838 : : DropTargetHelper& rTargetHelper,
839 : : ::sd::Window* pTargetWindow,
840 : : sal_uInt16 nPage,
841 : : sal_uInt16 nLayer)
842 : : {
843 : 0 : sal_Int8 nResult = 0;
844 : :
845 : : // The dropping of a shape is accepted or executed only when there is
846 : : // DrawViewShell available to which we can forward this call. This has
847 : : // technical reasons: The actual code to accept or execute a shape drop
848 : : // is implemented in the ViewShell class and uses the page view of the
849 : : // main edit view. This is not possible without a DrawViewShell.
850 [ # # ]: 0 : ::boost::shared_ptr<DrawViewShell> pDrawViewShell;
851 [ # # ][ # # ]: 0 : if (mrSlideSorter.GetViewShell() != NULL)
852 : : pDrawViewShell = ::boost::dynamic_pointer_cast<DrawViewShell>(
853 [ # # ][ # # ]: 0 : mrSlideSorter.GetViewShell()->GetViewShellBase().GetMainViewShell());
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
854 [ # # ][ # # ]: 0 : if (pDrawViewShell.get() != NULL
[ # # ][ # # ]
855 [ # # ]: 0 : && (pDrawViewShell->GetShellType() == ViewShell::ST_IMPRESS
856 [ # # ]: 0 : || pDrawViewShell->GetShellType() == ViewShell::ST_DRAW))
857 : : {
858 : : // The drop is only accepted or executed when it takes place over a
859 : : // page object. Therefore we replace a missing page number by the
860 : : // number of the page under the mouse.
861 [ # # ]: 0 : if (nPage == SDRPAGE_NOTFOUND)
862 : : {
863 : : model::SharedPageDescriptor pDescriptor (
864 [ # # ]: 0 : mrSlideSorter.GetModel().GetPageDescriptor(
865 [ # # ][ # # ]: 0 : mrSlideSorter.GetView().GetPageIndexAtPoint(rPosition)));
[ # # ]
866 [ # # ]: 0 : if (pDescriptor)
867 [ # # ][ # # ]: 0 : nPage = pDescriptor->GetPageIndex();
868 : : }
869 : :
870 : : // Now comes the code that is different for the Execute and Accept:
871 : : // We simply forward the call to the AcceptDrop() or ExecuteDrop()
872 : : // methods of the DrawViewShell in the center pane.
873 [ # # ]: 0 : if (nPage != SDRPAGE_NOTFOUND)
874 [ # # # ]: 0 : switch (eCommand)
875 : : {
876 : : case DC_ACCEPT:
877 : 0 : nResult = pDrawViewShell->AcceptDrop(
878 : : *reinterpret_cast<const AcceptDropEvent*>(pDropEvent),
879 : : rTargetHelper,
880 : : pTargetWindow,
881 : : nPage,
882 [ # # ]: 0 : nLayer);
883 : 0 : break;
884 : :
885 : : case DC_EXECUTE:
886 : 0 : nResult = pDrawViewShell->ExecuteDrop(
887 : : *reinterpret_cast<const ExecuteDropEvent*>(pDropEvent),
888 : : rTargetHelper,
889 : : pTargetWindow,
890 : : nPage,
891 [ # # ]: 0 : nLayer);
892 : 0 : break;
893 : : }
894 : : }
895 : :
896 [ # # ]: 0 : return nResult;
897 : : }
898 : :
899 : :
900 : :
901 : : } } } // end of namespace ::sd::slidesorter::controller
902 : :
903 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|