bump product version to 6.3.0.0.beta1
[LibreOffice.git] / sd / source / ui / slidesorter / controller / SlsSelectionManager.cxx
blob478e065ae40ae823d86d38c6e3affeb348a14071
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/SlsSelectionManager.hxx>
22 #include <SlideSorter.hxx>
23 #include <controller/SlideSorterController.hxx>
24 #include <controller/SlsAnimator.hxx>
25 #include <controller/SlsAnimationFunction.hxx>
26 #include <controller/SlsCurrentSlideManager.hxx>
27 #include <controller/SlsFocusManager.hxx>
28 #include <controller/SlsPageSelector.hxx>
29 #include <controller/SlsProperties.hxx>
30 #include <controller/SlsScrollBarManager.hxx>
31 #include <controller/SlsSlotManager.hxx>
32 #include <controller/SlsSelectionObserver.hxx>
33 #include <model/SlideSorterModel.hxx>
34 #include <model/SlsPageEnumerationProvider.hxx>
35 #include <model/SlsPageDescriptor.hxx>
36 #include <view/SlideSorterView.hxx>
37 #include <view/SlsLayouter.hxx>
38 #include <drawdoc.hxx>
39 #include <sdpage.hxx>
40 #include <drawview.hxx>
41 #include <DrawViewShell.hxx>
42 #include <ViewShellBase.hxx>
43 #include <Window.hxx>
44 #include <svx/svxids.hrc>
45 #include <com/sun/star/drawing/XMasterPagesSupplier.hpp>
46 #include <com/sun/star/drawing/XDrawPagesSupplier.hpp>
49 #include <sdresid.hxx>
50 #include <strings.hrc>
51 #include <app.hrc>
53 using namespace ::com::sun::star;
54 using namespace ::com::sun::star::drawing;
55 using namespace ::com::sun::star::uno;
56 using namespace ::sd::slidesorter::model;
57 using namespace ::sd::slidesorter::view;
58 using namespace ::sd::slidesorter::controller;
60 namespace sd { namespace slidesorter { namespace controller {
62 SelectionManager::SelectionManager (SlideSorter& rSlideSorter)
63 : mrSlideSorter(rSlideSorter),
64 mrController(rSlideSorter.GetController()),
65 mnInsertionPosition(-1),
66 mpSelectionObserver(new SelectionObserver(rSlideSorter))
70 SelectionManager::~SelectionManager()
74 void SelectionManager::DeleteSelectedPages (const bool bSelectFollowingPage)
76 // Create some locks to prevent updates of the model, view, selection
77 // state while modifying any of them.
78 SlideSorterController::ModelChangeLock aLock (mrController);
79 SlideSorterView::DrawLock aDrawLock (mrSlideSorter);
80 PageSelector::UpdateLock aSelectionLock (mrSlideSorter);
82 // Hide focus.
83 bool bIsFocusShowing = mrController.GetFocusManager().IsFocusShowing();
84 if (bIsFocusShowing)
85 mrController.GetFocusManager().ToggleFocus();
87 // Store pointers to all selected page descriptors. This is necessary
88 // because the pages get deselected when the first one is deleted.
89 model::PageEnumeration aPageEnumeration (
90 PageEnumerationProvider::CreateSelectedPagesEnumeration(mrSlideSorter.GetModel()));
91 ::std::vector<SdPage*> aSelectedPages;
92 sal_Int32 nNewCurrentSlide (-1);
93 while (aPageEnumeration.HasMoreElements())
95 SharedPageDescriptor pDescriptor (aPageEnumeration.GetNextElement());
96 aSelectedPages.push_back(pDescriptor->GetPage());
97 if (bSelectFollowingPage || nNewCurrentSlide<0)
98 nNewCurrentSlide = pDescriptor->GetPageIndex();
100 if (aSelectedPages.empty())
101 return;
103 // Determine the slide to select (and thereby make the current slide)
104 // after the deletion.
105 if (bSelectFollowingPage)
106 nNewCurrentSlide -= aSelectedPages.size() - 1;
107 else
108 --nNewCurrentSlide;
110 const auto pViewShell = mrSlideSorter.GetViewShell();
111 const auto pDrawViewShell = pViewShell ? std::dynamic_pointer_cast<sd::DrawViewShell>(pViewShell->GetViewShellBase().GetMainViewShell()) : nullptr;
112 const auto pDrawView = pDrawViewShell ? pDrawViewShell->GetDrawView() : nullptr;
114 if (pDrawView)
115 pDrawView->BlockPageOrderChangedHint(true);
117 // The actual deletion of the selected pages is done in one of two
118 // helper functions. They are specialized for normal respectively for
119 // master pages.
120 mrSlideSorter.GetView().BegUndo (SdResId(STR_UNDO_DELETEPAGES));
121 if (mrSlideSorter.GetModel().GetEditMode() == EditMode::Page)
122 DeleteSelectedNormalPages(aSelectedPages);
123 else
124 DeleteSelectedMasterPages(aSelectedPages);
125 mrSlideSorter.GetView().EndUndo ();
127 mrController.HandleModelChange();
128 aLock.Release();
129 if (pDrawView)
131 assert(pDrawViewShell);
132 pDrawView->BlockPageOrderChangedHint(false);
133 pDrawViewShell->ResetActualPage();
136 // Show focus and move it to next valid location.
137 if (bIsFocusShowing)
138 mrController.GetFocusManager().ToggleFocus();
140 // Set the new current slide.
141 if (nNewCurrentSlide < 0)
142 nNewCurrentSlide = 0;
143 else if (nNewCurrentSlide >= mrSlideSorter.GetModel().GetPageCount())
144 nNewCurrentSlide = mrSlideSorter.GetModel().GetPageCount()-1;
145 mrController.GetPageSelector().CountSelectedPages();
146 mrController.GetPageSelector().SelectPage(nNewCurrentSlide);
147 mrController.GetFocusManager().SetFocusedPage(nNewCurrentSlide);
150 void SelectionManager::DeleteSelectedNormalPages (const ::std::vector<SdPage*>& rSelectedPages)
152 // Prepare the deletion via the UNO API.
153 OSL_ASSERT(mrSlideSorter.GetModel().GetEditMode() == EditMode::Page);
157 Reference<drawing::XDrawPagesSupplier> xDrawPagesSupplier( mrSlideSorter.GetModel().GetDocument()->getUnoModel(), UNO_QUERY_THROW );
158 Reference<drawing::XDrawPages> xPages( xDrawPagesSupplier->getDrawPages(), UNO_SET_THROW );
160 // Iterate over all pages that were selected when this method was called
161 // and delete the draw page the notes page. The iteration is done in
162 // reverse order so that when one slide is not deleted (to avoid an
163 // empty document) the remaining slide is the first one.
164 ::std::vector<SdPage*>::const_reverse_iterator aI;
165 for (aI=rSelectedPages.rbegin(); aI!=rSelectedPages.rend(); ++aI)
167 // Do not delete the last slide in the document.
168 if (xPages->getCount() <= 1)
169 break;
171 const sal_uInt16 nPage (model::FromCoreIndex((*aI)->GetPageNum()));
173 Reference< XDrawPage > xPage( xPages->getByIndex( nPage ), UNO_QUERY_THROW );
174 xPages->remove(xPage);
177 catch( Exception& )
179 OSL_FAIL("SelectionManager::DeleteSelectedNormalPages(), exception caught!");
183 void SelectionManager::DeleteSelectedMasterPages (const ::std::vector<SdPage*>& rSelectedPages)
185 // Prepare the deletion via the UNO API.
186 OSL_ASSERT(mrSlideSorter.GetModel().GetEditMode() == EditMode::MasterPage);
190 Reference<drawing::XMasterPagesSupplier> xDrawPagesSupplier( mrSlideSorter.GetModel().GetDocument()->getUnoModel(), UNO_QUERY_THROW );
191 Reference<drawing::XDrawPages> xPages( xDrawPagesSupplier->getMasterPages(), UNO_SET_THROW );
193 // Iterate over all pages that were selected when this method was called
194 // and delete the draw page the notes page. The iteration is done in
195 // reverse order so that when one slide is not deleted (to avoid an
196 // empty document) the remaining slide is the first one.
197 ::std::vector<SdPage*>::const_reverse_iterator aI;
198 for (aI=rSelectedPages.rbegin(); aI!=rSelectedPages.rend(); ++aI)
200 // Do not delete the last slide in the document.
201 if (xPages->getCount() <= 1)
202 break;
204 const sal_uInt16 nPage (model::FromCoreIndex((*aI)->GetPageNum()));
206 Reference< XDrawPage > xPage( xPages->getByIndex( nPage ), UNO_QUERY_THROW );
207 xPages->remove(xPage);
210 catch( Exception& )
212 OSL_FAIL("SelectionManager::DeleteSelectedMasterPages(), exception caught!");
216 void SelectionManager::SelectionHasChanged ()
218 ViewShell* pViewShell = mrSlideSorter.GetViewShell();
219 if (pViewShell == nullptr)
220 return;
222 pViewShell->Invalidate (SID_EXPAND_PAGE);
223 pViewShell->Invalidate (SID_SUMMARY_PAGE);
224 pViewShell->Invalidate(SID_SHOW_SLIDE);
225 pViewShell->Invalidate(SID_HIDE_SLIDE);
226 pViewShell->Invalidate(SID_DELETE_PAGE);
227 pViewShell->Invalidate(SID_DELETE_MASTER_PAGE);
228 pViewShell->Invalidate(SID_ASSIGN_LAYOUT);
230 // StatusBar
231 pViewShell->Invalidate (SID_STATUS_PAGE);
232 pViewShell->Invalidate (SID_STATUS_LAYOUT);
234 OSL_ASSERT(mrController.GetCurrentSlideManager());
235 SharedPageDescriptor pDescriptor(mrController.GetCurrentSlideManager()->GetCurrentSlide());
236 if (pDescriptor.get() != nullptr)
237 pViewShell->UpdatePreview(pDescriptor->GetPage());
239 // Tell the selection change listeners that the selection has changed.
240 for (auto& rLink : maSelectionChangeListeners)
242 rLink.Call(nullptr);
245 // Reset the insertion position: until set again it is calculated from
246 // the current selection.
247 mnInsertionPosition = -1;
250 void SelectionManager::AddSelectionChangeListener (const Link<LinkParamNone*,void>& rListener)
252 if (::std::find (
253 maSelectionChangeListeners.begin(),
254 maSelectionChangeListeners.end(),
255 rListener) == maSelectionChangeListeners.end())
257 maSelectionChangeListeners.push_back (rListener);
261 void SelectionManager::RemoveSelectionChangeListener(const Link<LinkParamNone*,void>& rListener)
263 maSelectionChangeListeners.erase (
264 ::std::find (
265 maSelectionChangeListeners.begin(),
266 maSelectionChangeListeners.end(),
267 rListener));
270 sal_Int32 SelectionManager::GetInsertionPosition() const
272 sal_Int32 nInsertionPosition (mnInsertionPosition);
273 if (nInsertionPosition < 0)
275 model::PageEnumeration aSelectedPages
276 (model::PageEnumerationProvider::CreateSelectedPagesEnumeration(
277 mrSlideSorter.GetModel()));
278 // Initialize (for the case of an empty selection) with the position
279 // at the end of the document.
280 nInsertionPosition = mrSlideSorter.GetModel().GetPageCount();
281 while (aSelectedPages.HasMoreElements())
283 const sal_Int32 nPosition (aSelectedPages.GetNextElement()->GetPage()->GetPageNum());
284 // Convert *2+1 index to straight index (n-1)/2 after the page
285 // (+1).
286 nInsertionPosition = model::FromCoreIndex(nPosition) + 1;
290 return nInsertionPosition;
293 void SelectionManager::SetInsertionPosition (const sal_Int32 nInsertionPosition)
295 if (nInsertionPosition < 0)
296 mnInsertionPosition = -1;
297 else if (nInsertionPosition > mrSlideSorter.GetModel().GetPageCount())
299 // Assert but then ignore invalid values.
300 OSL_ASSERT(nInsertionPosition<=mrSlideSorter.GetModel().GetPageCount());
301 return;
303 else
304 mnInsertionPosition = nInsertionPosition;
307 } } } // end of namespace ::sd::slidesorter
309 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */