bump product version to 5.0.4.1
[LibreOffice.git] / sd / source / ui / slidesorter / controller / SlsSlotManager.cxx
blob1a7e4bc41eeafc0e5f167d0257864383bcf07af4
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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 <com/sun/star/presentation/XPresentation2.hpp>
21 #include <com/sun/star/beans/PropertyValue.hpp>
22 #include <com/sun/star/uno/Any.hxx>
24 #include <editeng/outlobj.hxx>
26 #include "controller/SlsSlotManager.hxx"
27 #include "SlideSorter.hxx"
28 #include "SlideSorterViewShell.hxx"
29 #include "controller/SlideSorterController.hxx"
30 #include "controller/SlsClipboard.hxx"
31 #include "controller/SlsCurrentSlideManager.hxx"
32 #include "controller/SlsFocusManager.hxx"
33 #include "controller/SlsInsertionIndicatorHandler.hxx"
34 #include "controller/SlsPageSelector.hxx"
35 #include "controller/SlsSelectionFunction.hxx"
36 #include "controller/SlsSelectionManager.hxx"
37 #include "controller/SlsSelectionObserver.hxx"
38 #include "model/SlideSorterModel.hxx"
39 #include "model/SlsPageEnumerationProvider.hxx"
40 #include "model/SlsPageDescriptor.hxx"
41 #include "view/SlideSorterView.hxx"
42 #include "view/SlsLayouter.hxx"
43 #include "framework/FrameworkHelper.hxx"
44 #include "Window.hxx"
45 #include "fupoor.hxx"
46 #include "fuzoom.hxx"
47 #include "fucushow.hxx"
48 #include "fusldlg.hxx"
49 #include "fuexpand.hxx"
50 #include "fusumry.hxx"
51 #include "fuscale.hxx"
52 #include "slideshow.hxx"
53 #include "app.hrc"
54 #include "strings.hrc"
55 #include "sdresid.hxx"
56 #include "drawdoc.hxx"
57 #include "DrawDocShell.hxx"
58 #include "ViewShellBase.hxx"
59 #include "ViewShellImplementation.hxx"
60 #include "sdattr.hxx"
61 #include "FrameView.hxx"
62 #include "zoomlist.hxx"
63 #include "sdpage.hxx"
64 #include "sdxfer.hxx"
65 #include "helpids.h"
66 #include "glob.hrc"
67 #include "unmodpg.hxx"
68 #include "DrawViewShell.hxx"
69 #include "sdabstdlg.hxx"
71 #include <sfx2/request.hxx>
72 #include <sfx2/viewfrm.hxx>
73 #include <sfx2/bindings.hxx>
74 #include <sfx2/dispatch.hxx>
75 #include <sfx2/sidebar/Sidebar.hxx>
76 #include <svx/svxids.hrc>
77 #include <sfx2/zoomitem.hxx>
78 #include <svx/svxdlg.hxx>
79 #include <svx/dialogs.hrc>
80 #include <vcl/msgbox.hxx>
81 #include <svl/intitem.hxx>
82 #include <svl/whiter.hxx>
83 #include <svl/itempool.hxx>
84 #include <svl/aeitem.hxx>
85 #include <com/sun/star/presentation/FadeEffect.hpp>
86 #include <com/sun/star/drawing/XMasterPagesSupplier.hpp>
87 #include <com/sun/star/drawing/XDrawPages.hpp>
88 #include <vcl/svapp.hxx>
90 #include <boost/bind.hpp>
91 #include <boost/scoped_ptr.hpp>
93 using namespace ::com::sun::star;
94 using namespace ::com::sun::star::uno;
95 using namespace ::com::sun::star::presentation;
96 using namespace ::com::sun::star::beans;
98 namespace sd { namespace slidesorter { namespace controller {
100 namespace {
102 /** The state of a set of slides with respect to being excluded from the
103 slide show.
105 enum SlideExclusionState {UNDEFINED, EXCLUDED, INCLUDED, MIXED};
107 /** Return for the given set of slides whether they included are
108 excluded from the slide show.
110 SlideExclusionState GetSlideExclusionState (model::PageEnumeration& rPageSet);
112 } // end of anonymous namespace
114 SlotManager::SlotManager (SlideSorter& rSlideSorter)
115 : mrSlideSorter(rSlideSorter),
116 maCommandQueue()
120 SlotManager::~SlotManager()
124 void SlotManager::FuTemporary (SfxRequest& rRequest)
126 SdDrawDocument* pDocument = mrSlideSorter.GetModel().GetDocument();
128 SlideSorterViewShell* pShell
129 = dynamic_cast<SlideSorterViewShell*>(mrSlideSorter.GetViewShell());
130 if (pShell == NULL)
131 return;
133 switch (rRequest.GetSlot())
135 case SID_PRESENTATION:
136 case SID_PRESENTATION_CURRENT_SLIDE:
137 case SID_REHEARSE_TIMINGS:
138 ShowSlideShow (rRequest);
139 pShell->Cancel();
140 rRequest.Done();
141 break;
143 case SID_HIDE_SLIDE:
144 ChangeSlideExclusionState(model::SharedPageDescriptor(), true);
145 break;
147 case SID_SHOW_SLIDE:
148 ChangeSlideExclusionState(model::SharedPageDescriptor(), false);
149 break;
151 case SID_PAGES_PER_ROW:
152 if (rRequest.GetArgs() != NULL)
154 SFX_REQUEST_ARG(rRequest, pPagesPerRow, SfxUInt16Item,
155 SID_PAGES_PER_ROW, false);
156 if (pPagesPerRow != NULL)
158 sal_Int32 nColumnCount = pPagesPerRow->GetValue();
159 // Force the given number of columns by setting
160 // the minimal and maximal number of columns to
161 // the same value.
162 mrSlideSorter.GetView().GetLayouter().SetColumnCount (
163 nColumnCount, nColumnCount);
164 // Force a repaint and re-layout.
165 pShell->ArrangeGUIElements ();
166 // Rearrange the UI-elements controlled by the
167 // controller and force a rearrangement of the
168 // view.
169 mrSlideSorter.GetController().Rearrange(true);
172 rRequest.Done();
173 break;
175 case SID_SELECTALL:
176 mrSlideSorter.GetController().GetPageSelector().SelectAllPages();
177 rRequest.Done();
178 break;
180 case SID_SLIDE_TRANSITIONS_PANEL:
182 // First make sure that the sidebar is visible
183 pShell->GetViewFrame()->ShowChildWindow(SID_SIDEBAR);
184 ::sfx2::sidebar::Sidebar::ShowPanel(
185 OUString("SlideTransitionPanel"),
186 pShell->GetViewFrame()->GetFrame().GetFrameInterface());
187 rRequest.Ignore ();
188 break;
191 case SID_PRESENTATION_DLG:
192 FuSlideShowDlg::Create (
193 pShell,
194 mrSlideSorter.GetContentWindow(),
195 &mrSlideSorter.GetView(),
196 pDocument,
197 rRequest);
198 break;
200 case SID_CUSTOMSHOW_DLG:
201 FuCustomShowDlg::Create (
202 pShell,
203 mrSlideSorter.GetContentWindow(),
204 &mrSlideSorter.GetView(),
205 pDocument,
206 rRequest);
207 break;
209 case SID_EXPAND_PAGE:
210 FuExpandPage::Create (
211 pShell,
212 mrSlideSorter.GetContentWindow(),
213 &mrSlideSorter.GetView(),
214 pDocument,
215 rRequest);
216 break;
218 case SID_SUMMARY_PAGE:
219 FuSummaryPage::Create (
220 pShell,
221 mrSlideSorter.GetContentWindow(),
222 &mrSlideSorter.GetView(),
223 pDocument,
224 rRequest);
225 break;
227 case SID_INSERTPAGE:
228 case SID_INSERT_MASTER_PAGE:
229 InsertSlide(rRequest);
230 rRequest.Done();
231 break;
233 case SID_DUPLICATE_PAGE:
234 DuplicateSelectedSlides(rRequest);
235 rRequest.Done();
236 break;
238 case SID_DELETE_PAGE:
239 case SID_DELETE_MASTER_PAGE:
240 case SID_DELETE: // we need SID_CUT to handle the delete key
241 // (DEL -> accelerator -> SID_CUT).
242 if (mrSlideSorter.GetModel().GetPageCount() > 1)
244 mrSlideSorter.GetController().GetSelectionManager()->DeleteSelectedPages();
247 rRequest.Done();
248 break;
250 case SID_RENAMEPAGE:
251 case SID_RENAME_MASTER_PAGE:
252 RenameSlide ();
253 rRequest.Done ();
254 break;
256 case SID_ASSIGN_LAYOUT:
258 pShell->mpImpl->AssignLayout( rRequest, mrSlideSorter.GetModel().GetPageType() );
259 rRequest.Done ();
261 break;
263 case SID_PHOTOALBUM:
265 SdAbstractDialogFactory* pFact = SdAbstractDialogFactory::Create();
266 boost::scoped_ptr<VclAbstractDialog> pDlg(pFact ? pFact->CreateSdPhotoAlbumDialog(
267 mrSlideSorter.GetContentWindow(),
268 pDocument) : 0);
270 if (pDlg)
272 pDlg->Execute();
273 pDlg.reset();
275 rRequest.Done ();
277 break;
279 case SID_REMOTE_DLG:
281 #ifdef ENABLE_SDREMOTE
282 SdAbstractDialogFactory* pFact = SdAbstractDialogFactory::Create();
283 VclAbstractDialog* pDlg = pFact ?
284 pFact->CreateRemoteDialog( mrSlideSorter.GetContentWindow() ) :
286 if (pDlg)
287 pDlg->Execute();
288 #endif
290 break;
292 default:
293 break;
297 void SlotManager::FuPermanent (SfxRequest& rRequest)
299 ViewShell* pShell = mrSlideSorter.GetViewShell();
300 if (pShell == NULL)
301 return;
303 if(pShell->GetCurrentFunction().is())
305 rtl::Reference<FuPoor> xEmpty;
306 if (pShell->GetOldFunction() == pShell->GetCurrentFunction())
307 pShell->SetOldFunction(xEmpty);
309 pShell->GetCurrentFunction()->Deactivate();
310 pShell->SetCurrentFunction(xEmpty);
313 switch(rRequest.GetSlot())
315 case SID_OBJECT_SELECT:
316 pShell->SetCurrentFunction( SelectionFunction::Create(mrSlideSorter, rRequest) );
317 rRequest.Done();
318 break;
320 default:
321 break;
324 if(pShell->GetOldFunction().is())
326 pShell->GetOldFunction()->Deactivate();
327 rtl::Reference<FuPoor> xEmpty;
328 pShell->SetOldFunction(xEmpty);
331 if(pShell->GetCurrentFunction().is())
333 pShell->GetCurrentFunction()->Activate();
334 pShell->SetOldFunction(pShell->GetCurrentFunction());
337 //! that's only until ENUM-Slots ?are
338 // Invalidate( SID_OBJECT_SELECT );
341 void SlotManager::FuSupport (SfxRequest& rRequest)
343 switch (rRequest.GetSlot())
345 case SID_STYLE_FAMILY:
346 if (rRequest.GetArgs() != NULL)
348 SdDrawDocument* pDocument
349 = mrSlideSorter.GetModel().GetDocument();
350 if (pDocument != NULL)
352 const SfxPoolItem& rItem (
353 rRequest.GetArgs()->Get(SID_STYLE_FAMILY));
354 pDocument->GetDocSh()->SetStyleFamily(
355 static_cast<const SfxUInt16Item&>(rItem).GetValue());
358 break;
360 case SID_PASTE:
362 SdTransferable* pTransferClip = SD_MOD()->pTransferClip;
363 if( pTransferClip )
365 SfxObjectShell* pTransferDocShell = pTransferClip->GetDocShell();
367 DrawDocShell* pDocShell = dynamic_cast<DrawDocShell*>(pTransferDocShell);
368 if (pDocShell && pDocShell->GetDoc()->GetPageCount() > 1)
370 mrSlideSorter.GetController().GetClipboard().HandleSlotCall(rRequest);
371 break;
374 ViewShellBase* pBase = mrSlideSorter.GetViewShellBase();
375 if (pBase != NULL)
377 ::boost::shared_ptr<DrawViewShell> pDrawViewShell (
378 ::boost::dynamic_pointer_cast<DrawViewShell>(pBase->GetMainViewShell()));
379 if (pDrawViewShell.get() != NULL)
380 pDrawViewShell->FuSupport(rRequest);
383 break;
385 case SID_CUT:
386 case SID_COPY:
387 case SID_DELETE:
388 mrSlideSorter.GetController().GetClipboard().HandleSlotCall(rRequest);
389 break;
391 case SID_DRAWINGMODE:
392 case SID_NOTESMODE:
393 case SID_HANDOUTMODE:
394 case SID_DIAMODE:
395 case SID_OUTLINEMODE:
397 ViewShellBase* pBase = mrSlideSorter.GetViewShellBase();
398 if (pBase != NULL)
400 framework::FrameworkHelper::Instance(*pBase)->HandleModeChangeSlot(
401 rRequest.GetSlot(), rRequest);
402 rRequest.Done();
404 break;
407 case SID_UNDO:
409 SlideSorterViewShell* pViewShell
410 = dynamic_cast<SlideSorterViewShell*>(mrSlideSorter.GetViewShell());
411 if (pViewShell != NULL)
413 view::SlideSorterView::DrawLock aDrawLock (mrSlideSorter);
414 SlideSorterController::ModelChangeLock aModelLock (mrSlideSorter.GetController());
415 PageSelector::UpdateLock aUpdateLock (mrSlideSorter);
416 SelectionObserver::Context aContext (mrSlideSorter);
417 pViewShell->ImpSidUndo (false, rRequest);
419 break;
422 case SID_REDO:
424 SlideSorterViewShell* pViewShell
425 = dynamic_cast<SlideSorterViewShell*>(mrSlideSorter.GetViewShell());
426 if (pViewShell != NULL)
428 view::SlideSorterView::DrawLock aDrawLock (mrSlideSorter);
429 SlideSorterController::ModelChangeLock aModelLock (mrSlideSorter.GetController());
430 PageSelector::UpdateLock aUpdateLock (mrSlideSorter);
431 SelectionObserver::Context aContext (mrSlideSorter);
432 pViewShell->ImpSidRedo (false, rRequest);
434 break;
437 default:
438 break;
442 void SlotManager::ExecCtrl (SfxRequest& rRequest)
444 ViewShell* pViewShell = mrSlideSorter.GetViewShell();
445 sal_uInt16 nSlot = rRequest.GetSlot();
446 switch (nSlot)
448 case SID_RELOAD:
450 // empty Undo-Manager
451 mrSlideSorter.GetModel().GetDocument()->GetDocSh()->ClearUndoBuffer();
453 // normal forwarding to ViewFrame for execution
454 if (pViewShell != NULL)
455 pViewShell->GetViewFrame()->ExecuteSlot(rRequest);
457 // has to be finished right away
458 return;
461 case SID_OUTPUT_QUALITY_COLOR:
462 case SID_OUTPUT_QUALITY_GRAYSCALE:
463 case SID_OUTPUT_QUALITY_BLACKWHITE:
464 case SID_OUTPUT_QUALITY_CONTRAST:
466 // flush page cache
467 if (pViewShell != NULL)
468 pViewShell->ExecReq (rRequest);
469 break;
472 case SID_MAIL_SCROLLBODY_PAGEDOWN:
474 if (pViewShell != NULL)
475 pViewShell->ExecReq (rRequest);
476 break;
479 case SID_OPT_LOCALE_CHANGED:
481 mrSlideSorter.GetController().UpdateAllPages();
482 if (pViewShell != NULL)
483 pViewShell->UpdatePreview (pViewShell->GetActualPage());
484 rRequest.Done();
485 break;
488 case SID_SEARCH_DLG:
489 // We have to handle the SID_SEARCH_DLG slot explicitly because
490 // in some cases (when the slide sorter is displayed in the
491 // center pane) we want to disable the search dialog. Therefore
492 // we have to handle the execution of that slot as well.
493 // We try to do that by forwarding the request to the view frame
494 // of the view shell.
495 if (pViewShell != NULL)
496 pViewShell->GetViewFrame()->ExecuteSlot(rRequest);
497 break;
499 default:
500 break;
504 void SlotManager::GetAttrState (SfxItemSet& rSet)
506 // Iterate over all items.
507 SfxWhichIter aIter (rSet);
508 sal_uInt16 nWhich = aIter.FirstWhich();
509 while (nWhich)
511 sal_uInt16 nSlotId (nWhich);
512 if (SfxItemPool::IsWhich(nWhich) && mrSlideSorter.GetViewShell()!=NULL)
513 nSlotId = mrSlideSorter.GetViewShell()->GetPool().GetSlotId(nWhich);
514 switch (nSlotId)
516 case SID_PAGES_PER_ROW:
517 rSet.Put (
518 SfxUInt16Item (
519 nSlotId,
520 (sal_uInt16)mrSlideSorter.GetView().GetLayouter().GetColumnCount()
523 break;
525 nWhich = aIter.NextWhich();
529 void SlotManager::GetMenuState (SfxItemSet& rSet)
531 EditMode eEditMode = mrSlideSorter.GetModel().GetEditMode();
532 ViewShell* pShell = mrSlideSorter.GetViewShell();
533 DrawDocShell* pDocShell = mrSlideSorter.GetModel().GetDocument()->GetDocSh();
535 if (pShell!=NULL && pShell->GetCurrentFunction().is())
537 sal_uInt16 nSId = pShell->GetCurrentFunction()->GetSlotID();
539 rSet.Put( SfxBoolItem( nSId, true ) );
541 rSet.Put( SfxBoolItem( SID_DRAWINGMODE, false ) );
542 rSet.Put( SfxBoolItem( SID_DIAMODE, true ) );
543 rSet.Put( SfxBoolItem( SID_OUTLINEMODE, false ) );
544 rSet.Put( SfxBoolItem( SID_NOTESMODE, false ) );
545 rSet.Put( SfxBoolItem( SID_HANDOUTMODE, false ) );
547 if (pShell!=NULL && pShell->IsMainViewShell())
549 rSet.DisableItem(SID_SPELL_DIALOG);
550 rSet.DisableItem(SID_SEARCH_DLG);
553 if (SfxItemState::DEFAULT == rSet.GetItemState(SID_EXPAND_PAGE))
555 bool bDisable = true;
556 if (eEditMode == EM_PAGE)
558 // At least one of the selected pages has to contain an outline
559 // presentation objects in order to enable the expand page menu
560 // entry.
561 model::PageEnumeration aSelectedPages (
562 model::PageEnumerationProvider::CreateSelectedPagesEnumeration(
563 mrSlideSorter.GetModel()));
564 while (aSelectedPages.HasMoreElements())
566 SdPage* pPage = aSelectedPages.GetNextElement()->GetPage();
567 SdrObject* pObj = pPage->GetPresObj(PRESOBJ_OUTLINE);
568 if (pObj!=NULL )
570 if( !pObj->IsEmptyPresObj() )
572 bDisable = false;
574 else
576 // check if the object is in edit, than its temporarily not empty
577 SdrTextObj* pTextObj = dynamic_cast< SdrTextObj* >( pObj );
578 if( pTextObj )
580 OutlinerParaObject* pParaObj = pTextObj->GetEditOutlinerParaObject();
581 if( pParaObj )
583 delete pParaObj;
584 bDisable = false;
592 if (bDisable)
593 rSet.DisableItem (SID_EXPAND_PAGE);
596 if (SfxItemState::DEFAULT == rSet.GetItemState(SID_SUMMARY_PAGE))
598 bool bDisable = true;
599 if (eEditMode == EM_PAGE)
601 // At least one of the selected pages has to contain a title
602 // presentation objects in order to enable the summary page menu
603 // entry.
604 model::PageEnumeration aSelectedPages (
605 model::PageEnumerationProvider::CreateSelectedPagesEnumeration(
606 mrSlideSorter.GetModel()));
607 while (aSelectedPages.HasMoreElements())
609 SdPage* pPage = aSelectedPages.GetNextElement()->GetPage();
610 SdrObject* pObj = pPage->GetPresObj(PRESOBJ_TITLE);
612 if (pObj!=NULL && !pObj->IsEmptyPresObj())
613 bDisable = false;
616 if (bDisable)
617 rSet.DisableItem (SID_SUMMARY_PAGE);
620 // starting of presentation possible?
621 if( SfxItemState::DEFAULT == rSet.GetItemState( SID_PRESENTATION ) ||
622 SfxItemState::DEFAULT == rSet.GetItemState( SID_REHEARSE_TIMINGS ) )
624 bool bDisable = true;
625 model::PageEnumeration aAllPages (
626 model::PageEnumerationProvider::CreateAllPagesEnumeration(mrSlideSorter.GetModel()));
627 while (aAllPages.HasMoreElements())
629 SdPage* pPage = aAllPages.GetNextElement()->GetPage();
631 if( !pPage->IsExcluded() )
632 bDisable = false;
634 if( bDisable || pDocShell->IsPreview())
636 rSet.DisableItem( SID_PRESENTATION );
637 rSet.DisableItem( SID_REHEARSE_TIMINGS );
641 // Disable the rename slots when there are no or more than one slides/master
642 // pages selected; disable the duplicate slot when there are no slides
643 // selected:
644 if (rSet.GetItemState(SID_RENAMEPAGE) == SfxItemState::DEFAULT
645 || rSet.GetItemState(SID_RENAME_MASTER_PAGE) == SfxItemState::DEFAULT
646 || rSet.GetItemState(SID_DUPLICATE_PAGE) == SfxItemState::DEFAULT)
648 int n = mrSlideSorter.GetController().GetPageSelector()
649 .GetSelectedPageCount();
650 if (n != 1)
652 rSet.DisableItem(SID_RENAMEPAGE);
653 rSet.DisableItem(SID_RENAME_MASTER_PAGE);
655 if (n == 0)
657 rSet.DisableItem(SID_DUPLICATE_PAGE);
661 if (rSet.GetItemState(SID_HIDE_SLIDE) == SfxItemState::DEFAULT
662 || rSet.GetItemState(SID_SHOW_SLIDE) == SfxItemState::DEFAULT)
664 model::PageEnumeration aSelectedPages (
665 model::PageEnumerationProvider::CreateSelectedPagesEnumeration(
666 mrSlideSorter.GetModel()));
667 const SlideExclusionState eState (GetSlideExclusionState(aSelectedPages));
668 switch (eState)
670 case MIXED:
671 // Show both entries.
672 break;
674 case EXCLUDED:
675 rSet.DisableItem(SID_HIDE_SLIDE);
676 break;
678 case INCLUDED:
679 rSet.DisableItem(SID_SHOW_SLIDE);
680 break;
682 case UNDEFINED:
683 rSet.DisableItem(SID_HIDE_SLIDE);
684 rSet.DisableItem(SID_SHOW_SLIDE);
685 break;
689 PageKind ePageKind = mrSlideSorter.GetModel().GetPageType();
690 if ((eEditMode == EM_MASTERPAGE) && (ePageKind != PK_HANDOUT))
692 rSet.DisableItem(SID_ASSIGN_LAYOUT);
695 if ((eEditMode == EM_MASTERPAGE) || (ePageKind==PK_NOTES))
697 rSet.DisableItem(SID_INSERTPAGE);
700 // Disable some slots when in master page mode.
701 if (eEditMode == EM_MASTERPAGE)
703 if (rSet.GetItemState(SID_INSERTPAGE) == SfxItemState::DEFAULT)
704 rSet.DisableItem(SID_INSERTPAGE);
705 if (rSet.GetItemState(SID_DUPLICATE_PAGE) == SfxItemState::DEFAULT)
706 rSet.DisableItem(SID_DUPLICATE_PAGE);
710 void SlotManager::GetClipboardState ( SfxItemSet& rSet)
712 SdTransferable* pTransferClip = SD_MOD()->pTransferClip;
714 if (rSet.GetItemState(SID_PASTE) == SfxItemState::DEFAULT
715 || rSet.GetItemState(SID_PASTE_SPECIAL) == SfxItemState::DEFAULT)
717 // no own clipboard data?
718 if ( !pTransferClip || !pTransferClip->GetDocShell() )
720 rSet.DisableItem(SID_PASTE);
721 rSet.DisableItem(SID_PASTE_SPECIAL);
723 else
725 SfxObjectShell* pTransferDocShell = pTransferClip->GetDocShell();
727 if( !pTransferDocShell || static_cast<DrawDocShell*>(pTransferDocShell)->GetDoc()->GetPageCount() <= 1 )
729 bool bIsPastingSupported (false);
731 // No or just one page. Check if there is anything that can be
732 // pasted via a DrawViewShell.
733 ViewShellBase* pBase = mrSlideSorter.GetViewShellBase();
734 if (pBase != NULL)
736 ::boost::shared_ptr<DrawViewShell> pDrawViewShell (
737 ::boost::dynamic_pointer_cast<DrawViewShell>(pBase->GetMainViewShell()));
738 if (pDrawViewShell.get() != NULL)
740 TransferableDataHelper aDataHelper (
741 TransferableDataHelper::CreateFromSystemClipboard(
742 pDrawViewShell->GetActiveWindow()));
743 if (aDataHelper.GetFormatCount() > 0)
744 bIsPastingSupported = true;
748 if ( ! bIsPastingSupported)
750 rSet.DisableItem(SID_PASTE);
751 rSet.DisableItem(SID_PASTE_SPECIAL);
757 // Cut, copy and paste of master pages is not yet implemented properly
758 if (rSet.GetItemState(SID_COPY) == SfxItemState::DEFAULT
759 || rSet.GetItemState(SID_PASTE) == SfxItemState::DEFAULT
760 || rSet.GetItemState(SID_PASTE_SPECIAL) == SfxItemState::DEFAULT
761 || rSet.GetItemState(SID_CUT) == SfxItemState::DEFAULT)
763 if (mrSlideSorter.GetModel().GetEditMode() == EM_MASTERPAGE)
765 if (rSet.GetItemState(SID_CUT) == SfxItemState::DEFAULT)
766 rSet.DisableItem(SID_CUT);
767 if (rSet.GetItemState(SID_COPY) == SfxItemState::DEFAULT)
768 rSet.DisableItem(SID_COPY);
769 if (rSet.GetItemState(SID_PASTE) == SfxItemState::DEFAULT)
770 rSet.DisableItem(SID_PASTE);
771 if (rSet.GetItemState(SID_PASTE_SPECIAL) == SfxItemState::DEFAULT)
772 rSet.DisableItem(SID_PASTE_SPECIAL);
776 // Cut, copy, and delete page are disabled when there is no selection.
777 if (rSet.GetItemState(SID_CUT) == SfxItemState::DEFAULT
778 || rSet.GetItemState(SID_COPY) == SfxItemState::DEFAULT
779 || rSet.GetItemState(SID_DELETE) == SfxItemState::DEFAULT
780 || rSet.GetItemState(SID_DELETE_PAGE) == SfxItemState::DEFAULT
781 || rSet.GetItemState(SID_DELETE_MASTER_PAGE) == SfxItemState::DEFAULT)
783 model::PageEnumeration aSelectedPages (
784 model::PageEnumerationProvider::CreateSelectedPagesEnumeration(
785 mrSlideSorter.GetModel()));
787 // For copy to work we have to have at least one selected page.
788 if ( ! aSelectedPages.HasMoreElements())
789 rSet.DisableItem(SID_COPY);
791 bool bDisable = false;
792 // The operations that lead to the deletion of a page are valid if
793 // a) there is at least one selected page
794 // b) deleting the selected pages leaves at least one page in the
795 // document
796 // c) selected master pages must not be used by slides.
798 // Test a).
799 if ( ! aSelectedPages.HasMoreElements())
800 bDisable = true;
801 // Test b): Count the number of selected pages. It has to be less
802 // than the number of all pages.
803 else if (mrSlideSorter.GetController().GetPageSelector().GetSelectedPageCount()
804 >= mrSlideSorter.GetController().GetPageSelector().GetPageCount())
805 bDisable = true;
806 // Test c): Iterate over the selected pages and look for a master
807 // page that is used by at least one page.
808 else while (aSelectedPages.HasMoreElements())
810 SdPage* pPage = aSelectedPages.GetNextElement()->GetPage();
811 int nUseCount (mrSlideSorter.GetModel().GetDocument()
812 ->GetMasterPageUserCount(pPage));
813 if (nUseCount > 0)
815 bDisable = true;
816 break;
820 if (bDisable)
822 rSet.DisableItem(SID_CUT);
823 rSet.DisableItem(SID_DELETE_PAGE);
824 rSet.DisableItem(SID_DELETE_MASTER_PAGE);
829 void SlotManager::GetStatusBarState (SfxItemSet& rSet)
831 // page view and layout
832 SdPage* pPage = NULL;
833 SdPage* pFirstPage = NULL;
834 sal_uInt16 nFirstPage;
835 sal_Int32 nPageCount;
836 sal_Int32 nActivePageCount;
837 sal_uInt16 nSelectedPages = mrSlideSorter.GetController().GetPageSelector().GetSelectedPageCount();
838 OUString aPageStr;
839 OUString aLayoutStr;
841 //Set number of slides
842 if (nSelectedPages > 0)
844 model::PageEnumeration aSelectedPages (
845 model::PageEnumerationProvider::CreateSelectedPagesEnumeration(
846 mrSlideSorter.GetModel()));
847 model::SharedPageDescriptor pDescriptor (aSelectedPages.GetNextElement());
848 if (pDescriptor)
850 pPage = pDescriptor->GetPage();
851 nFirstPage = (pPage->GetPageNum()/2) + 1;
852 nPageCount = mrSlideSorter.GetModel().GetPageCount();
853 nActivePageCount = static_cast<sal_Int32>(mrSlideSorter.GetModel().GetDocument()->GetActiveSdPageCount());
855 aPageStr = (nPageCount == nActivePageCount) ? SD_RESSTR(STR_SD_PAGE_COUNT) : SD_RESSTR(STR_SD_PAGE_COUNT_CUSTOM);
857 aPageStr = aPageStr.replaceFirst("%1", OUString::number(nFirstPage));
858 aPageStr = aPageStr.replaceFirst("%2", OUString::number(nPageCount));
859 if(nPageCount != nActivePageCount)
860 aPageStr = aPageStr.replaceFirst("%3", OUString::number(nActivePageCount));
862 rSet.Put( SfxStringItem( SID_STATUS_PAGE, aPageStr ) );
864 //Set layout
865 if (nSelectedPages == 1 && pPage != NULL)
867 pFirstPage = pPage;
868 aLayoutStr = pFirstPage->GetLayoutName();
869 sal_Int32 nIndex = aLayoutStr.indexOf( SD_LT_SEPARATOR );
870 if( nIndex != -1 )
871 aLayoutStr = aLayoutStr.copy(0, nIndex);
872 rSet.Put( SfxStringItem( SID_STATUS_LAYOUT, aLayoutStr ) );
876 void SlotManager::ShowSlideShow( SfxRequest& rReq)
878 slideshowhelp::ShowSlideShow(rReq, *mrSlideSorter.GetModel().GetDocument());
881 void SlotManager::RenameSlide()
883 PageKind ePageKind = mrSlideSorter.GetModel().GetPageType();
884 View* pDrView = &mrSlideSorter.GetView();
886 if (ePageKind==PK_STANDARD || ePageKind==PK_NOTES)
888 if ( pDrView->IsTextEdit() )
890 pDrView->SdrEndTextEdit();
893 SdPage* pSelectedPage = NULL;
894 model::PageEnumeration aSelectedPages (
895 model::PageEnumerationProvider::CreateSelectedPagesEnumeration(
896 mrSlideSorter.GetModel()));
897 if (aSelectedPages.HasMoreElements())
898 pSelectedPage = aSelectedPages.GetNextElement()->GetPage();
899 if (pSelectedPage != NULL)
901 OUString aTitle( SdResId( STR_TITLE_RENAMESLIDE ) );
902 OUString aDescr( SdResId( STR_DESC_RENAMESLIDE ) );
903 OUString aPageName = pSelectedPage->GetName();
905 SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create();
906 DBG_ASSERT(pFact, "Dialog creation failed!");
907 boost::scoped_ptr<AbstractSvxNameDialog> aNameDlg(pFact->CreateSvxNameDialog(
908 mrSlideSorter.GetContentWindow(),
909 aPageName, aDescr));
910 DBG_ASSERT(aNameDlg, "Dialog creation failed!");
911 aNameDlg->SetText( aTitle );
912 aNameDlg->SetCheckNameHdl( LINK( this, SlotManager, RenameSlideHdl ), true );
913 aNameDlg->SetEditHelpId( HID_SD_NAMEDIALOG_PAGE );
915 if( aNameDlg->Execute() == RET_OK )
917 OUString aNewName;
918 aNameDlg->GetName( aNewName );
919 if (aNewName != aPageName)
921 #ifdef DBG_UTIL
922 bool bResult =
923 #endif
924 RenameSlideFromDrawViewShell(
925 pSelectedPage->GetPageNum()/2, aNewName );
926 DBG_ASSERT( bResult, "Couldn't rename slide" );
929 aNameDlg.reset();
931 // Tell the slide sorter about the name change (necessary for
932 // accessibility.)
933 mrSlideSorter.GetController().PageNameHasChanged(
934 (pSelectedPage->GetPageNum()-1)/2, aPageName);
939 IMPL_LINK(SlotManager, RenameSlideHdl, AbstractSvxNameDialog*, pDialog)
941 if( ! pDialog )
942 return 0;
944 OUString aNewName;
945 pDialog->GetName( aNewName );
947 model::SharedPageDescriptor pDescriptor (
948 mrSlideSorter.GetController().GetCurrentSlideManager()->GetCurrentSlide());
949 SdPage* pCurrentPage = NULL;
950 if (pDescriptor.get() != NULL)
951 pCurrentPage = pDescriptor->GetPage();
953 return long( (pCurrentPage!=NULL && aNewName == pCurrentPage->GetName())
954 || (mrSlideSorter.GetViewShell()
955 && mrSlideSorter.GetViewShell()->GetDocSh()->IsNewPageNameValid( aNewName ) ));
958 bool SlotManager::RenameSlideFromDrawViewShell( sal_uInt16 nPageId, const OUString & rName )
960 bool bOutDummy;
961 SdDrawDocument* pDocument = mrSlideSorter.GetModel().GetDocument();
962 if( pDocument->GetPageByName( rName, bOutDummy ) != SDRPAGE_NOTFOUND )
963 return false;
965 SdPage* pPageToRename = NULL;
966 PageKind ePageKind = mrSlideSorter.GetModel().GetPageType();
968 ::svl::IUndoManager* pManager = pDocument->GetDocSh()->GetUndoManager();
970 if( mrSlideSorter.GetModel().GetEditMode() == EM_PAGE )
972 model::SharedPageDescriptor pDescriptor (
973 mrSlideSorter.GetController().GetCurrentSlideManager()->GetCurrentSlide());
974 if (pDescriptor.get() != NULL)
975 pPageToRename = pDescriptor->GetPage();
977 if (pPageToRename != NULL)
979 // Undo
980 SdPage* pUndoPage = pPageToRename;
981 SdrLayerAdmin & rLayerAdmin = pDocument->GetLayerAdmin();
982 sal_uInt8 nBackground = rLayerAdmin.GetLayerID( SD_RESSTR( STR_LAYER_BCKGRND ), false );
983 sal_uInt8 nBgObj = rLayerAdmin.GetLayerID( SD_RESSTR( STR_LAYER_BCKGRNDOBJ ), false );
984 SetOfByte aVisibleLayers = pPageToRename->TRG_GetMasterPageVisibleLayers();
986 // (#67720#)
987 ModifyPageUndoAction* pAction = new ModifyPageUndoAction(
988 pDocument, pUndoPage, rName, pUndoPage->GetAutoLayout(),
989 aVisibleLayers.IsSet( nBackground ),
990 aVisibleLayers.IsSet( nBgObj ));
991 pManager->AddUndoAction( pAction );
993 // rename
994 pPageToRename->SetName( rName );
996 if( ePageKind == PK_STANDARD )
998 // also rename notes-page
999 SdPage* pNotesPage = pDocument->GetSdPage( nPageId, PK_NOTES );
1000 if (pNotesPage != NULL)
1001 pNotesPage->SetName (rName);
1005 else
1007 // rename MasterPage -> rename LayoutTemplate
1008 pPageToRename = pDocument->GetMasterSdPage( nPageId, ePageKind );
1009 if (pPageToRename != NULL)
1011 const OUString aOldLayoutName( pPageToRename->GetLayoutName() );
1012 pManager->AddUndoAction( new RenameLayoutTemplateUndoAction( pDocument, aOldLayoutName, rName ) );
1013 pDocument->RenameLayoutTemplate( aOldLayoutName, rName );
1017 bool bSuccess = pPageToRename!=NULL && ( rName == pPageToRename->GetName() );
1019 if( bSuccess )
1021 // user edited page names may be changed by the page so update control
1022 // aTabControl.SetPageText( nPageId, rName );
1024 // set document to modified state
1025 pDocument->SetChanged( true );
1027 // inform navigator about change
1028 SfxBoolItem aItem( SID_NAVIGATOR_INIT, true );
1029 if (mrSlideSorter.GetViewShell() != NULL)
1030 mrSlideSorter.GetViewShell()->GetDispatcher()->Execute(
1031 SID_NAVIGATOR_INIT, SfxCallMode::ASYNCHRON | SfxCallMode::RECORD, &aItem, 0L );
1034 return bSuccess;
1037 /** Insert a slide. The insertion position depends on a) the selection and
1038 b) the mouse position when there is no selection.
1040 When there is a selection then insertion takes place after the last
1041 slide of the selection. For this to work all but the last selected
1042 slide are deselected first.
1044 Otherwise, when there is no selection but the insertion marker is visible
1045 the slide is inserted at that position. The slide before that marker is
1046 selected first.
1048 When both the selection and the insertion marker are not visible--can
1049 that happen?--the new slide is inserted after the last slide.
1051 void SlotManager::InsertSlide (SfxRequest& rRequest)
1053 const sal_Int32 nInsertionIndex (GetInsertionPosition());
1055 PageSelector::BroadcastLock aBroadcastLock (mrSlideSorter);
1057 SdPage* pNewPage = NULL;
1058 if (mrSlideSorter.GetModel().GetEditMode() == EM_PAGE)
1060 SlideSorterViewShell* pShell = dynamic_cast<SlideSorterViewShell*>(
1061 mrSlideSorter.GetViewShell());
1062 if (pShell != NULL)
1064 pNewPage = pShell->CreateOrDuplicatePage (
1065 rRequest,
1066 mrSlideSorter.GetModel().GetPageType(),
1067 nInsertionIndex>=0
1068 ? mrSlideSorter.GetModel().GetPageDescriptor(nInsertionIndex)->GetPage()
1069 : NULL);
1072 else
1074 // Use the API to create a new page.
1075 SdDrawDocument* pDocument = mrSlideSorter.GetModel().GetDocument();
1076 Reference<drawing::XMasterPagesSupplier> xMasterPagesSupplier (
1077 pDocument->getUnoModel(), UNO_QUERY);
1078 if (xMasterPagesSupplier.is())
1080 Reference<drawing::XDrawPages> xMasterPages (
1081 xMasterPagesSupplier->getMasterPages());
1082 if (xMasterPages.is())
1084 xMasterPages->insertNewByIndex (nInsertionIndex+1);
1086 // Create shapes for the default layout.
1087 pNewPage = pDocument->GetMasterSdPage(
1088 (sal_uInt16)(nInsertionIndex+1), PK_STANDARD);
1089 pNewPage->CreateTitleAndLayout (true,true);
1093 if (pNewPage == NULL)
1094 return;
1096 // When a new page has been inserted then select it, make it the
1097 // current page, and focus it.
1098 view::SlideSorterView::DrawLock aDrawLock (mrSlideSorter);
1099 PageSelector::UpdateLock aUpdateLock (mrSlideSorter);
1100 mrSlideSorter.GetController().GetPageSelector().DeselectAllPages();
1101 mrSlideSorter.GetController().GetPageSelector().SelectPage(pNewPage);
1104 void SlotManager::DuplicateSelectedSlides (SfxRequest& rRequest)
1106 // Create a list of the pages that are to be duplicated. The process of
1107 // duplication alters the selection.
1108 sal_Int32 nInsertPosition (0);
1109 ::std::vector<SdPage*> aPagesToDuplicate;
1110 model::PageEnumeration aSelectedPages (
1111 model::PageEnumerationProvider::CreateSelectedPagesEnumeration(mrSlideSorter.GetModel()));
1112 while (aSelectedPages.HasMoreElements())
1114 model::SharedPageDescriptor pDescriptor (aSelectedPages.GetNextElement());
1115 if (pDescriptor && pDescriptor->GetPage())
1117 aPagesToDuplicate.push_back(pDescriptor->GetPage());
1118 nInsertPosition = pDescriptor->GetPage()->GetPageNum()+2;
1122 // Duplicate the pages in aPagesToDuplicate and collect the newly
1123 // created pages in aPagesToSelect.
1124 const bool bUndo (aPagesToDuplicate.size()>1 && mrSlideSorter.GetView().IsUndoEnabled());
1125 if (bUndo)
1126 mrSlideSorter.GetView().BegUndo(SD_RESSTR(STR_INSERTPAGE));
1128 ::std::vector<SdPage*> aPagesToSelect;
1129 for(::std::vector<SdPage*>::const_iterator
1130 iPage(aPagesToDuplicate.begin()),
1131 iEnd(aPagesToDuplicate.end());
1132 iPage!=iEnd;
1133 ++iPage, nInsertPosition+=2)
1135 aPagesToSelect.push_back(
1136 mrSlideSorter.GetViewShell()->CreateOrDuplicatePage(
1137 rRequest, PK_STANDARD, *iPage, nInsertPosition));
1139 aPagesToDuplicate.clear();
1141 if (bUndo)
1142 mrSlideSorter.GetView().EndUndo();
1144 // Set the selection to the pages in aPagesToSelect.
1145 PageSelector& rSelector (mrSlideSorter.GetController().GetPageSelector());
1146 rSelector.DeselectAllPages();
1147 ::std::for_each (
1148 aPagesToSelect.begin(),
1149 aPagesToSelect.end(),
1150 ::boost::bind(
1151 static_cast<void (PageSelector::*)(const SdPage*)>(&PageSelector::SelectPage),
1152 ::boost::ref(rSelector),
1153 _1));
1156 void SlotManager::ChangeSlideExclusionState (
1157 const model::SharedPageDescriptor& rpDescriptor,
1158 const bool bExcludeSlide)
1160 if (rpDescriptor)
1162 mrSlideSorter.GetView().SetState(
1163 rpDescriptor,
1164 model::PageDescriptor::ST_Excluded,
1165 bExcludeSlide);
1167 else
1169 model::PageEnumeration aSelectedPages (
1170 model::PageEnumerationProvider::CreateSelectedPagesEnumeration(
1171 mrSlideSorter.GetModel()));
1172 while (aSelectedPages.HasMoreElements())
1174 model::SharedPageDescriptor pDescriptor (aSelectedPages.GetNextElement());
1175 mrSlideSorter.GetView().SetState(
1176 pDescriptor,
1177 model::PageDescriptor::ST_Excluded,
1178 bExcludeSlide);
1182 SfxBindings& rBindings (mrSlideSorter.GetViewShell()->GetViewFrame()->GetBindings());
1183 rBindings.Invalidate(SID_PRESENTATION);
1184 rBindings.Invalidate(SID_REHEARSE_TIMINGS);
1185 rBindings.Invalidate(SID_HIDE_SLIDE);
1186 rBindings.Invalidate(SID_SHOW_SLIDE);
1187 mrSlideSorter.GetModel().GetDocument()->SetChanged();
1190 sal_Int32 SlotManager::GetInsertionPosition()
1192 PageSelector& rSelector (mrSlideSorter.GetController().GetPageSelector());
1194 // The insertion indicator is preferred. After all the user explicitly
1195 // used it to define the insertion position.
1196 if (mrSlideSorter.GetController().GetInsertionIndicatorHandler()->IsActive())
1198 // Select the page before the insertion indicator.
1199 return mrSlideSorter.GetController().GetInsertionIndicatorHandler()->GetInsertionPageIndex()
1200 - 1;
1203 // Is there a stored insertion position?
1204 else if (mrSlideSorter.GetController().GetSelectionManager()->GetInsertionPosition() >= 0)
1206 return mrSlideSorter.GetController().GetSelectionManager()->GetInsertionPosition() - 1;
1209 // Use the index of the last selected slide.
1210 else if (rSelector.GetSelectedPageCount() > 0)
1212 for (int nIndex=rSelector.GetPageCount()-1; nIndex>=0; --nIndex)
1213 if (rSelector.IsPageSelected(nIndex))
1214 return nIndex;
1216 // We should never get here.
1217 OSL_ASSERT(false);
1218 return rSelector.GetPageCount() - 1;
1221 // Select the last page when there is at least one page.
1222 else if (rSelector.GetPageCount() > 0)
1224 return rSelector.GetPageCount() - 1;
1227 // Hope for the best that CreateOrDuplicatePage() can cope with an empty
1228 // selection.
1229 else
1231 // We should never get here because there has to be at least one page.
1232 OSL_ASSERT(false);
1233 return -1;
1237 void SlotManager::NotifyEditModeChange()
1239 SfxBindings& rBindings (mrSlideSorter.GetViewShell()->GetViewFrame()->GetBindings());
1240 rBindings.Invalidate(SID_PRESENTATION);
1241 rBindings.Invalidate(SID_INSERTPAGE);
1242 rBindings.Invalidate(SID_DUPLICATE_PAGE);
1245 namespace {
1247 SlideExclusionState GetSlideExclusionState (model::PageEnumeration& rPageSet)
1249 SlideExclusionState eState (UNDEFINED);
1251 // Get toggle state of the selected pages.
1252 while (rPageSet.HasMoreElements() && eState!=MIXED)
1254 const bool bState = rPageSet.GetNextElement()->GetPage()->IsExcluded();
1255 switch (eState)
1257 case UNDEFINED:
1258 // Use the first selected page to set the initial value.
1259 eState = bState ? EXCLUDED : INCLUDED;
1260 break;
1262 case EXCLUDED:
1263 // The pages before where all not part of the show,
1264 // this one is.
1265 if ( ! bState)
1266 eState = MIXED;
1267 break;
1269 case INCLUDED:
1270 // The pages before where all part of the show,
1271 // this one is not.
1272 if (bState)
1273 eState = MIXED;
1274 break;
1276 default:
1277 // No need to change anything.
1278 break;
1282 return eState;
1285 } // end of anonymous namespace
1287 } } } // end of namespace ::sd::slidesorter::controller
1289 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */