android: Update app-specific/MIME type icons
[LibreOffice.git] / sd / source / ui / slidesorter / controller / SlideSorterController.cxx
blob4a0328e3d415e3c1d6d88a969903b93f7d99c8ec
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 <controller/SlideSorterController.hxx>
22 #include <SlideSorter.hxx>
23 #include <controller/SlsPageSelector.hxx>
24 #include <controller/SlsSelectionFunction.hxx>
25 #include <controller/SlsProperties.hxx>
26 #include <controller/SlsCurrentSlideManager.hxx>
27 #include "SlsListener.hxx"
28 #include <controller/SlsFocusManager.hxx>
29 #include <controller/SlsAnimator.hxx>
30 #include <controller/SlsClipboard.hxx>
31 #include <controller/SlsInsertionIndicatorHandler.hxx>
32 #include <controller/SlsScrollBarManager.hxx>
33 #include <controller/SlsSelectionManager.hxx>
34 #include <controller/SlsSlotManager.hxx>
35 #include <controller/SlsVisibleAreaManager.hxx>
36 #include <model/SlideSorterModel.hxx>
37 #include <model/SlsPageEnumerationProvider.hxx>
38 #include <model/SlsPageDescriptor.hxx>
39 #include <view/SlideSorterView.hxx>
40 #include <view/SlsLayouter.hxx>
41 #include <view/SlsPageObjectLayouter.hxx>
42 #include <view/SlsTheme.hxx>
43 #include <view/SlsToolTip.hxx>
44 #include <cache/SlsPageCache.hxx>
45 #include <cache/SlsPageCacheManager.hxx>
46 #include <comphelper/diagnose_ex.hxx>
48 #include <drawdoc.hxx>
49 #include <ViewShellBase.hxx>
50 #include <Window.hxx>
51 #include <FrameView.hxx>
52 #include <sdpage.hxx>
54 #include <app.hrc>
55 #include <sdmod.hxx>
56 #include <ViewShellHint.hxx>
57 #include <AccessibleSlideSorterView.hxx>
58 #include <AccessibleSlideSorterObject.hxx>
60 #include <vcl/window.hxx>
61 #include <svx/svxids.hrc>
62 #include <sfx2/request.hxx>
63 #include <sfx2/viewfrm.hxx>
64 #include <sfx2/dispatch.hxx>
65 #include <tools/debug.hxx>
66 #include <vcl/commandevent.hxx>
67 #include <vcl/svapp.hxx>
68 #include <vcl/settings.hxx>
70 #include <com/sun/star/lang/XComponent.hpp>
71 #include <com/sun/star/accessibility/AccessibleEventId.hpp>
73 #include <memory>
75 using namespace ::com::sun::star;
76 using namespace ::com::sun::star::uno;
77 using namespace ::sd::slidesorter::model;
78 using namespace ::sd::slidesorter::view;
79 using namespace ::sd::slidesorter::controller;
80 using namespace ::basegfx;
82 namespace sd::slidesorter::controller {
84 SlideSorterController::SlideSorterController (SlideSorter& rSlideSorter)
85 : mrSlideSorter(rSlideSorter),
86 mrModel(mrSlideSorter.GetModel()),
87 mrView(mrSlideSorter.GetView()),
88 mpInsertionIndicatorHandler(std::make_shared<InsertionIndicatorHandler>(rSlideSorter)),
89 mpAnimator(std::make_shared<Animator>(rSlideSorter)),
90 mpVisibleAreaManager(new VisibleAreaManager(rSlideSorter)),
91 mnModelChangeLockCount(0),
92 mbIsForcedRearrangePending(false),
93 mbContextMenuOpen(false),
94 mbPostModelChangePending(false),
95 mnCurrentPageBeforeSwitch(0),
96 mpEditModeChangeMasterPage(nullptr),
97 mnPaintEntranceCount(0)
99 sd::Window *pWindow (mrSlideSorter.GetContentWindow().get());
100 OSL_ASSERT(pWindow);
101 if (!pWindow)
102 return;
104 // The whole background is painted by the view and controls.
105 vcl::Window* pParentWindow = pWindow->GetParent();
106 OSL_ASSERT(pParentWindow!=nullptr);
107 pParentWindow->SetBackground (Wallpaper());
109 // Connect the view with the window that has been created by our base
110 // class.
111 pWindow->SetBackground(Wallpaper());
112 pWindow->SetCenterAllowed(false);
113 pWindow->SetMapMode(MapMode(MapUnit::MapPixel));
114 pWindow->SetViewSize(mrView.GetModelArea().GetSize());
117 void SlideSorterController::Init()
119 mpCurrentSlideManager = std::make_shared<CurrentSlideManager>(mrSlideSorter);
120 mpPageSelector.reset(new PageSelector(mrSlideSorter));
121 mpFocusManager.reset(new FocusManager(mrSlideSorter));
122 mpSlotManager = std::make_shared<SlotManager>(mrSlideSorter);
123 mpScrollBarManager.reset(new ScrollBarManager(mrSlideSorter));
124 mpSelectionManager = std::make_shared<SelectionManager>(mrSlideSorter);
125 mpClipboard.reset(new Clipboard(mrSlideSorter));
127 // Create the selection function.
128 SfxRequest aRequest (
129 SID_OBJECT_SELECT,
130 SfxCallMode::SLOT,
131 mrModel.GetDocument()->GetItemPool());
132 mrSlideSorter.SetCurrentFunction(CreateSelectionFunction(aRequest));
134 mpListener = new Listener(mrSlideSorter);
136 mpPageSelector->GetCoreSelection();
137 GetSelectionManager()->SelectionHasChanged();
140 SlideSorterController::~SlideSorterController()
144 uno::Reference<lang::XComponent> xComponent = mpListener;
145 if (xComponent.is())
146 xComponent->dispose();
148 catch( uno::Exception& )
150 TOOLS_WARN_EXCEPTION( "sd", "sd::SlideSorterController::~SlideSorterController()" );
153 // dispose should have been called by now so that nothing is to be done
154 // to shut down cleanly.
157 void SlideSorterController::Dispose()
159 mpInsertionIndicatorHandler->End(Animator::AM_Immediate);
160 mpClipboard.reset();
161 mpSelectionManager.reset();
162 mpAnimator->Dispose();
165 model::SharedPageDescriptor SlideSorterController::GetPageAt (
166 const Point& aWindowPosition)
168 sal_Int32 nHitPageIndex (mrView.GetPageIndexAtPoint(aWindowPosition));
169 model::SharedPageDescriptor pDescriptorAtPoint;
170 if (nHitPageIndex >= 0)
172 pDescriptorAtPoint = mrModel.GetPageDescriptor(nHitPageIndex);
174 // Depending on a property we may have to check that the mouse is no
175 // just over the page object but over the preview area.
176 if (pDescriptorAtPoint
177 && ! pDescriptorAtPoint->HasState(PageDescriptor::ST_Selected))
179 // Make sure that the mouse is over the preview area.
180 if ( ! mrView.GetLayouter().GetPageObjectLayouter()->GetBoundingBox(
181 pDescriptorAtPoint,
182 view::PageObjectLayouter::Part::Preview,
183 view::PageObjectLayouter::WindowCoordinateSystem).Contains(aWindowPosition))
185 pDescriptorAtPoint.reset();
190 return pDescriptorAtPoint;
193 PageSelector& SlideSorterController::GetPageSelector()
195 OSL_ASSERT(mpPageSelector != nullptr);
196 return *mpPageSelector;
199 FocusManager& SlideSorterController::GetFocusManager()
201 OSL_ASSERT(mpFocusManager != nullptr);
202 return *mpFocusManager;
205 Clipboard& SlideSorterController::GetClipboard()
207 OSL_ASSERT(mpClipboard != nullptr);
208 return *mpClipboard;
211 ScrollBarManager& SlideSorterController::GetScrollBarManager()
213 OSL_ASSERT(mpScrollBarManager != nullptr);
214 return *mpScrollBarManager;
217 std::shared_ptr<CurrentSlideManager> const & SlideSorterController::GetCurrentSlideManager() const
219 OSL_ASSERT(mpCurrentSlideManager != nullptr);
220 return mpCurrentSlideManager;
223 std::shared_ptr<SlotManager> const & SlideSorterController::GetSlotManager() const
225 OSL_ASSERT(mpSlotManager != nullptr);
226 return mpSlotManager;
229 std::shared_ptr<SelectionManager> const & SlideSorterController::GetSelectionManager() const
231 OSL_ASSERT(mpSelectionManager != nullptr);
232 return mpSelectionManager;
235 std::shared_ptr<InsertionIndicatorHandler> const &
236 SlideSorterController::GetInsertionIndicatorHandler() const
238 OSL_ASSERT(mpInsertionIndicatorHandler != nullptr);
239 return mpInsertionIndicatorHandler;
242 void SlideSorterController::Paint (
243 const ::tools::Rectangle& rBBox,
244 vcl::Window* pWindow)
246 if (mnPaintEntranceCount != 0)
247 return;
249 ++mnPaintEntranceCount;
253 mrView.CompleteRedraw(pWindow->GetOutDev(), vcl::Region(rBBox));
255 catch (const Exception&)
257 // Ignore all exceptions.
260 --mnPaintEntranceCount;
263 void SlideSorterController::FuTemporary (SfxRequest& rRequest)
265 mpSlotManager->FuTemporary (rRequest);
268 void SlideSorterController::FuPermanent (SfxRequest &rRequest)
270 mpSlotManager->FuPermanent (rRequest);
273 void SlideSorterController::FuSupport (SfxRequest &rRequest)
275 mpSlotManager->FuSupport (rRequest);
278 bool SlideSorterController::Command (
279 const CommandEvent& rEvent,
280 ::sd::Window* pWindow)
282 bool bEventHasBeenHandled = false;
284 if (pWindow == nullptr)
285 return false;
287 ViewShell* pViewShell = mrSlideSorter.GetViewShell();
288 if (pViewShell == nullptr)
289 return false;
291 switch (rEvent.GetCommand())
293 case CommandEventId::ContextMenu:
295 SdPage* pPage = nullptr;
296 OUString aPopupId;
298 model::PageEnumeration aSelectedPages (
299 PageEnumerationProvider::CreateSelectedPagesEnumeration(mrModel));
300 if (aSelectedPages.HasMoreElements())
301 pPage = aSelectedPages.GetNextElement()->GetPage();
303 if (mrModel.GetEditMode() == EditMode::Page)
305 if (pPage != nullptr)
306 aPopupId = "pagepane";
307 else
308 aPopupId = "pagepanenosel";
310 else if (pPage != nullptr)
311 aPopupId = "pagepanemaster";
312 else
313 aPopupId = "pagepanenoselmaster";
315 std::unique_ptr<InsertionIndicatorHandler::ForceShowContext, o3tl::default_delete<InsertionIndicatorHandler::ForceShowContext>> xContext;
316 if (pPage == nullptr)
318 // When there is no selection, then we show the insertion
319 // indicator so that the user knows where a page insertion
320 // would take place.
321 mpInsertionIndicatorHandler->Start(false);
322 mpInsertionIndicatorHandler->UpdateIndicatorIcon(SD_MOD()->pTransferClip);
323 mpInsertionIndicatorHandler->UpdatePosition(
324 pWindow->PixelToLogic(rEvent.GetMousePosPixel()),
325 InsertionIndicatorHandler::MoveMode);
326 xContext.reset(new InsertionIndicatorHandler::ForceShowContext(
327 mpInsertionIndicatorHandler));
330 pWindow->ReleaseMouse();
332 Point aMenuLocation (0,0);
333 if (!rEvent.IsMouseEvent())
335 // The event is not a mouse event. Use the center of the
336 // focused page as top left position of the context menu.
337 model::SharedPageDescriptor pDescriptor (
338 GetFocusManager().GetFocusedPageDescriptor());
339 if (pDescriptor)
341 ::tools::Rectangle aBBox (
342 mrView.GetLayouter().GetPageObjectLayouter()->GetBoundingBox (
343 pDescriptor,
344 PageObjectLayouter::Part::PageObject,
345 PageObjectLayouter::ModelCoordinateSystem));
346 aMenuLocation = aBBox.Center();
350 if (SfxDispatcher* pDispatcher = pViewShell->GetDispatcher())
352 mbContextMenuOpen = true;
353 if (!rEvent.IsMouseEvent())
354 pDispatcher->ExecutePopup(aPopupId, pWindow, &aMenuLocation);
355 else
356 pDispatcher->ExecutePopup(aPopupId, pWindow);
357 mbContextMenuOpen = false;
358 mrSlideSorter.GetView().UpdatePageUnderMouse();
359 ::rtl::Reference<SelectionFunction> pFunction(GetCurrentSelectionFunction());
360 if (pFunction.is())
361 pFunction->ResetMouseAnchor();
363 if (pPage == nullptr)
365 // Remember the position of the insertion indicator before
366 // it is hidden, so that a pending slide insertion slot call
367 // finds the right place to insert a new slide.
368 GetSelectionManager()->SetInsertionPosition(
369 GetInsertionIndicatorHandler()->GetInsertionPageIndex());
371 xContext.reset();
372 bEventHasBeenHandled = true;
374 break;
376 case CommandEventId::Wheel:
378 const CommandWheelData* pData = rEvent.GetWheelData();
379 if (pData == nullptr)
380 return false;
381 if (pData->IsMod1())
383 // We do not support zooming with control+mouse wheel.
384 return false;
386 // Determine whether to scroll horizontally or vertically. This
387 // depends on the orientation of the scroll bar and the
388 // IsHoriz() flag of the event.
389 if ((mrSlideSorter.GetView().GetOrientation()==view::Layouter::HORIZONTAL)
390 == pData->IsHorz())
392 GetScrollBarManager().Scroll(
393 ScrollBarManager::Orientation_Vertical,
394 -pData->GetNotchDelta());
396 else
398 GetScrollBarManager().Scroll(
399 ScrollBarManager::Orientation_Horizontal,
400 -pData->GetNotchDelta());
402 mrSlideSorter.GetView().UpdatePageUnderMouse(rEvent.GetMousePosPixel());
404 bEventHasBeenHandled = true;
406 break;
408 default: break;
411 return bEventHasBeenHandled;
414 void SlideSorterController::LockModelChange()
416 mnModelChangeLockCount += 1;
419 void SlideSorterController::UnlockModelChange()
421 mnModelChangeLockCount -= 1;
422 if (mnModelChangeLockCount==0 && mbPostModelChangePending)
424 PostModelChange();
428 void SlideSorterController::PreModelChange()
430 // Prevent PreModelChange to execute more than once per model lock.
431 if (mbPostModelChangePending)
432 return;
434 if (mrSlideSorter.GetViewShell() != nullptr)
435 mrSlideSorter.GetViewShell()->Broadcast(
436 ViewShellHint(ViewShellHint::HINT_COMPLEX_MODEL_CHANGE_START));
438 GetCurrentSlideManager()->PrepareModelChange();
440 if (mrSlideSorter.GetContentWindow())
441 mrView.PreModelChange();
443 mbPostModelChangePending = true;
446 void SlideSorterController::PostModelChange()
448 mbPostModelChangePending = false;
449 mrModel.Resync();
451 sd::Window *pWindow (mrSlideSorter.GetContentWindow().get());
452 if (pWindow)
454 GetCurrentSlideManager()->HandleModelChange();
456 mrView.PostModelChange ();
458 pWindow->SetViewOrigin (Point (0,0));
459 pWindow->SetViewSize (mrView.GetModelArea().GetSize());
461 // The visibility of the scroll bars may have to be changed. Then
462 // the size of the view has to change, too. Let Rearrange() handle
463 // that.
464 Rearrange(mbIsForcedRearrangePending);
467 if (mrSlideSorter.GetViewShell() != nullptr)
468 mrSlideSorter.GetViewShell()->Broadcast(
469 ViewShellHint(ViewShellHint::HINT_COMPLEX_MODEL_CHANGE_END));
472 void SlideSorterController::HandleModelChange()
474 // Ignore this call when the document is not in a valid state, i.e. has
475 // not the same number of regular and notes pages.
476 bool bIsDocumentValid = (mrModel.GetDocument()->GetPageCount() % 2 == 1);
478 if (bIsDocumentValid)
480 ModelChangeLock aLock (*this);
481 PreModelChange();
485 IMPL_LINK(SlideSorterController, ApplicationEventHandler, VclSimpleEvent&, rEvent, void)
487 auto windowEvent = dynamic_cast<VclWindowEvent *>(&rEvent);
488 if (windowEvent != nullptr) {
489 WindowEventHandler(*windowEvent);
492 IMPL_LINK(SlideSorterController, WindowEventHandler, VclWindowEvent&, rEvent, void)
494 vcl::Window* pWindow = rEvent.GetWindow();
495 sd::Window *pActiveWindow (mrSlideSorter.GetContentWindow().get());
496 switch (rEvent.GetId())
498 case VclEventId::WindowActivate:
499 case VclEventId::WindowShow:
500 if (pActiveWindow && pWindow == pActiveWindow->GetParent())
501 mrView.RequestRepaint();
502 break;
504 case VclEventId::WindowHide:
505 if (pActiveWindow && pWindow == pActiveWindow->GetParent())
506 mrView.SetPageUnderMouse(SharedPageDescriptor());
507 break;
509 case VclEventId::WindowGetFocus:
510 if (pActiveWindow)
511 if (pWindow == pActiveWindow)
512 GetFocusManager().ShowFocus(false);
513 break;
515 case VclEventId::WindowLoseFocus:
516 if (pActiveWindow && pWindow == pActiveWindow)
518 GetFocusManager().HideFocus();
519 mrView.GetToolTip().Hide();
521 //don't scroll back to the selected slide when we lose
522 //focus due to a temporary active context menu
523 if (!mbContextMenuOpen)
525 // Select the current slide so that it is properly
526 // visualized when the focus is moved to the edit view.
527 GetPageSelector().SelectPage(GetCurrentSlideManager()->GetCurrentSlide());
530 break;
532 case VclEventId::ApplicationDataChanged:
534 // Invalidate the preview cache.
535 cache::PageCacheManager::Instance()->InvalidateAllCaches();
537 // Update the draw mode.
538 DrawModeFlags nDrawMode (Application::GetSettings().GetStyleSettings().GetHighContrastMode()
539 ? sd::OUTPUT_DRAWMODE_CONTRAST
540 : sd::OUTPUT_DRAWMODE_COLOR);
541 if (mrSlideSorter.GetViewShell() != nullptr)
542 mrSlideSorter.GetViewShell()->GetFrameView()->SetDrawMode(nDrawMode);
543 if (pActiveWindow != nullptr)
544 pActiveWindow->GetOutDev()->SetDrawMode(nDrawMode);
545 mrView.HandleDrawModeChange();
547 // When the system font has changed a layout has to be done.
548 mrView.Resize();
550 // Update theme colors.
551 mrSlideSorter.GetProperties()->HandleDataChangeEvent();
552 mrSlideSorter.GetTheme()->Update(mrSlideSorter.GetProperties());
553 mrView.HandleDataChangeEvent();
555 break;
557 default:
558 break;
562 void SlideSorterController::GetCtrlState (SfxItemSet& rSet)
564 if (rSet.GetItemState(SID_RELOAD) != SfxItemState::UNKNOWN)
566 // let SFx en-/disable "last version"
567 SfxViewFrame* pSlideViewFrame = SfxViewFrame::Current();
568 DBG_ASSERT(pSlideViewFrame!=nullptr,
569 "SlideSorterController::GetCtrlState: ViewFrame not found");
570 if (pSlideViewFrame)
572 pSlideViewFrame->GetSlotState (SID_RELOAD, nullptr, &rSet);
574 else // MI says: no MDIFrame --> disable
576 rSet.DisableItem(SID_RELOAD);
580 // Output quality.
581 if (rSet.GetItemState(SID_OUTPUT_QUALITY_COLOR)==SfxItemState::DEFAULT
582 ||rSet.GetItemState(SID_OUTPUT_QUALITY_GRAYSCALE)==SfxItemState::DEFAULT
583 ||rSet.GetItemState(SID_OUTPUT_QUALITY_BLACKWHITE)==SfxItemState::DEFAULT
584 ||rSet.GetItemState(SID_OUTPUT_QUALITY_CONTRAST)==SfxItemState::DEFAULT)
586 if (mrSlideSorter.GetContentWindow())
588 DrawModeFlags nMode = mrSlideSorter.GetContentWindow()->GetOutDev()->GetDrawMode();
589 sal_uInt16 nQuality = 0;
591 if (nMode == sd::OUTPUT_DRAWMODE_COLOR) {
592 nQuality = 0;
593 } else if (nMode == sd::OUTPUT_DRAWMODE_GRAYSCALE) {
594 nQuality = 1;
595 } else if (nMode == sd::OUTPUT_DRAWMODE_BLACKWHITE) {
596 nQuality = 2;
597 } else if (nMode == sd::OUTPUT_DRAWMODE_CONTRAST) {
598 nQuality = 3;
601 rSet.Put (SfxBoolItem (SID_OUTPUT_QUALITY_COLOR, nQuality==0));
602 rSet.Put (SfxBoolItem (SID_OUTPUT_QUALITY_GRAYSCALE, nQuality==1));
603 rSet.Put (SfxBoolItem (SID_OUTPUT_QUALITY_BLACKWHITE, nQuality==2));
604 rSet.Put (SfxBoolItem (SID_OUTPUT_QUALITY_CONTRAST, nQuality==3));
608 if (rSet.GetItemState(SID_MAIL_SCROLLBODY_PAGEDOWN) == SfxItemState::DEFAULT)
610 rSet.Put (SfxBoolItem( SID_MAIL_SCROLLBODY_PAGEDOWN, true));
614 void SlideSorterController::GetStatusBarState (SfxItemSet& rSet)
616 mpSlotManager->GetStatusBarState (rSet);
619 void SlideSorterController::ExecCtrl (SfxRequest& rRequest)
621 mpSlotManager->ExecCtrl (rRequest);
624 void SlideSorterController::GetAttrState (SfxItemSet& rSet)
626 mpSlotManager->GetAttrState (rSet);
629 void SlideSorterController::UpdateAllPages()
631 // Do a redraw.
632 mrSlideSorter.GetContentWindow()->Invalidate();
635 void SlideSorterController::Resize (const ::tools::Rectangle& rAvailableSpace)
637 if (maTotalWindowArea != rAvailableSpace)
639 maTotalWindowArea = rAvailableSpace;
640 Rearrange(true);
644 void SlideSorterController::Rearrange (bool bForce)
646 if (maTotalWindowArea.IsEmpty())
647 return;
649 if (mnModelChangeLockCount>0)
651 mbIsForcedRearrangePending |= bForce;
652 return;
654 else
655 mbIsForcedRearrangePending = false;
657 sd::Window *pWindow (mrSlideSorter.GetContentWindow().get());
658 if (!pWindow)
659 return;
661 if (bForce)
662 mrView.UpdateOrientation();
664 // Place the scroll bars.
665 ::tools::Rectangle aNewContentArea = GetScrollBarManager().PlaceScrollBars(
666 maTotalWindowArea,
667 mrView.GetOrientation() != view::Layouter::VERTICAL,
668 mrView.GetOrientation() != view::Layouter::HORIZONTAL);
670 bool bSizeHasChanged (false);
671 // Only when bForce is not true we have to test for a size change in
672 // order to determine whether the window and the view have to be resized.
673 if ( ! bForce)
675 ::tools::Rectangle aCurrentContentArea (pWindow->GetPosPixel(), pWindow->GetOutputSizePixel());
676 bSizeHasChanged = (aNewContentArea != aCurrentContentArea);
678 if (bForce || bSizeHasChanged)
680 // The browser window gets the remaining space.
681 pWindow->SetPosSizePixel (aNewContentArea.TopLeft(), aNewContentArea.GetSize());
682 mrView.Resize();
685 // Adapt the scroll bars to the new zoom factor of the browser
686 // window and the arrangement of the page objects.
687 GetScrollBarManager().UpdateScrollBars(!bForce);
689 // Keep the current slide in the visible area.
690 GetVisibleAreaManager().RequestCurrentSlideVisible();
692 mrView.RequestRepaint();
695 rtl::Reference<FuPoor> SlideSorterController::CreateSelectionFunction (SfxRequest& rRequest)
697 rtl::Reference<FuPoor> xFunc( SelectionFunction::Create(mrSlideSorter, rRequest) );
698 return xFunc;
701 ::rtl::Reference<SelectionFunction> SlideSorterController::GetCurrentSelectionFunction() const
703 rtl::Reference<FuPoor> pFunction (mrSlideSorter.GetViewShell()->GetCurrentFunction());
704 return ::rtl::Reference<SelectionFunction>(dynamic_cast<SelectionFunction*>(pFunction.get()));
707 void SlideSorterController::PrepareEditModeChange()
709 // Before we throw away the page descriptors we prepare for selecting
710 // descriptors in the other mode and for restoring the current
711 // selection when switching back to the current mode.
712 if (mrModel.GetEditMode() != EditMode::Page)
713 return;
715 maSelectionBeforeSwitch.clear();
717 // Search for the first selected page and determine the master page
718 // used by its page object. It will be selected after the switch.
719 // In the same loop the current selection is stored.
720 PageEnumeration aSelectedPages (
721 PageEnumerationProvider::CreateSelectedPagesEnumeration(mrModel));
722 while (aSelectedPages.HasMoreElements())
724 SharedPageDescriptor pDescriptor (aSelectedPages.GetNextElement());
725 SdPage* pPage = pDescriptor->GetPage();
726 // Remember the master page of the first selected descriptor.
727 if (pPage!=nullptr && mpEditModeChangeMasterPage==nullptr)
728 mpEditModeChangeMasterPage = &static_cast<SdPage&>(
729 pPage->TRG_GetMasterPage());
731 maSelectionBeforeSwitch.push_back(pPage);
734 // Remember the current page.
735 if (mrSlideSorter.GetViewShell() != nullptr)
736 mnCurrentPageBeforeSwitch = (mrSlideSorter.GetViewShell()->GetViewShellBase()
737 .GetMainViewShell()->GetActualPage()->GetPageNum()-1)/2;
740 void SlideSorterController::ChangeEditMode (EditMode eEditMode)
742 if (mrModel.GetEditMode() != eEditMode)
744 ModelChangeLock aLock (*this);
745 PreModelChange();
746 // Do the actual edit mode switching.
747 bool bResult = mrModel.SetEditMode(eEditMode);
748 if (bResult)
749 HandleModelChange();
753 void SlideSorterController::FinishEditModeChange()
755 if (mrModel.GetEditMode() == EditMode::MasterPage)
757 mpPageSelector->DeselectAllPages();
759 // Search for the master page that was determined in
760 // PrepareEditModeChange() and make it the current page.
761 PageEnumeration aAllPages (PageEnumerationProvider::CreateAllPagesEnumeration(mrModel));
762 while (aAllPages.HasMoreElements())
764 SharedPageDescriptor pDescriptor (aAllPages.GetNextElement());
765 if (pDescriptor->GetPage() == mpEditModeChangeMasterPage)
767 GetCurrentSlideManager()->SwitchCurrentSlide(pDescriptor);
768 mpPageSelector->SelectPage(pDescriptor);
769 break;
773 else
775 PageSelector::BroadcastLock aBroadcastLock (*mpPageSelector);
777 SharedPageDescriptor pDescriptor (mrModel.GetPageDescriptor(mnCurrentPageBeforeSwitch));
778 GetCurrentSlideManager()->SwitchCurrentSlide(pDescriptor);
780 // Restore the selection.
781 mpPageSelector->DeselectAllPages();
782 for (const auto& rpPage : maSelectionBeforeSwitch)
784 mpPageSelector->SelectPage(rpPage);
786 maSelectionBeforeSwitch.clear( );
788 mpEditModeChangeMasterPage = nullptr;
791 void SlideSorterController::PageNameHasChanged (int nPageIndex, const OUString& rsOldName)
793 // Request a repaint for the page object whose name has changed.
794 model::SharedPageDescriptor pDescriptor (mrModel.GetPageDescriptor(nPageIndex));
795 if (pDescriptor)
796 mrView.RequestRepaint(pDescriptor);
798 // Get a pointer to the corresponding accessible object and notify
799 // that of the name change.
800 sd::Window *pWindow (mrSlideSorter.GetContentWindow().get());
801 if ( ! pWindow)
802 return;
804 css::uno::Reference< css::accessibility::XAccessible >
805 xAccessible (pWindow->GetAccessible(false));
806 if ( ! xAccessible.is())
807 return;
809 // Now comes a small hack. We assume that the accessible object is
810 // an instantiation of AccessibleSlideSorterView and cast it to that
811 // class. The cleaner alternative to this cast would be a new member
812 // in which we would store the last AccessibleSlideSorterView object
813 // created by SlideSorterViewShell::CreateAccessibleDocumentView().
814 // But then there is no guaranty that the accessible object obtained
815 // from the window really is that instance last created by
816 // CreateAccessibleDocumentView().
817 // However, the dynamic cast together with the check of the result
818 // being NULL should be safe enough.
819 ::accessibility::AccessibleSlideSorterView* pAccessibleView
820 = dynamic_cast< ::accessibility::AccessibleSlideSorterView*>(xAccessible.get());
821 if (pAccessibleView == nullptr)
822 return;
824 ::accessibility::AccessibleSlideSorterObject* pChild
825 = pAccessibleView->GetAccessibleChildImplementation(nPageIndex);
826 if (pChild == nullptr || pChild->GetPage() == nullptr)
827 return;
829 OUString sNewName (pChild->GetPage()->GetName());
830 pChild->FireAccessibleEvent(
831 css::accessibility::AccessibleEventId::NAME_CHANGED,
832 Any(rsOldName),
833 Any(sNewName));
836 void SlideSorterController::SetDocumentSlides (const Reference<container::XIndexAccess>& rxSlides)
838 if (mrModel.GetDocumentSlides() != rxSlides)
840 ModelChangeLock aLock (*this);
841 PreModelChange();
843 mrModel.SetDocumentSlides(rxSlides);
847 VisibleAreaManager& SlideSorterController::GetVisibleAreaManager() const
849 OSL_ASSERT(mpVisibleAreaManager);
850 return *mpVisibleAreaManager;
853 void SlideSorterController::CheckForMasterPageAssignment()
855 if (mrModel.GetPageCount()%2==0)
856 return;
857 PageEnumeration aAllPages (PageEnumerationProvider::CreateAllPagesEnumeration(mrModel));
858 while (aAllPages.HasMoreElements())
860 SharedPageDescriptor pDescriptor (aAllPages.GetNextElement());
861 if (pDescriptor->UpdateMasterPage())
863 mrView.GetPreviewCache()->InvalidatePreviewBitmap (
864 pDescriptor->GetPage());
869 void SlideSorterController::CheckForSlideTransitionAssignment()
871 if (mrModel.GetPageCount()%2==0)
872 return;
873 PageEnumeration aAllPages (PageEnumerationProvider::CreateAllPagesEnumeration(mrModel));
874 while (aAllPages.HasMoreElements())
876 SharedPageDescriptor pDescriptor (aAllPages.GetNextElement());
877 if (pDescriptor->UpdateTransitionFlag())
879 mrView.GetPreviewCache()->InvalidatePreviewBitmap (
880 pDescriptor->GetPage());
885 //===== SlideSorterController::ModelChangeLock ================================
887 SlideSorterController::ModelChangeLock::ModelChangeLock (
888 SlideSorterController& rController)
889 : mpController(&rController)
891 mpController->LockModelChange();
894 SlideSorterController::ModelChangeLock::~ModelChangeLock() COVERITY_NOEXCEPT_FALSE
896 Release();
899 void SlideSorterController::ModelChangeLock::Release()
901 if (mpController != nullptr)
903 mpController->UnlockModelChange();
904 mpController = nullptr;
908 } // end of namespace ::sd::slidesorter
910 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */