1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <controller/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>
40 #include <drawview.hxx>
41 #include <DrawViewShell.hxx>
42 #include <ViewShellBase.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>
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
);
83 bool bIsFocusShowing
= mrController
.GetFocusManager().IsFocusShowing();
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())
103 // Determine the slide to select (and thereby make the current slide)
104 // after the deletion.
105 if (bSelectFollowingPage
)
106 nNewCurrentSlide
-= aSelectedPages
.size() - 1;
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;
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
120 mrSlideSorter
.GetView().BegUndo (SdResId(STR_UNDO_DELETEPAGES
));
121 if (mrSlideSorter
.GetModel().GetEditMode() == EditMode::Page
)
122 DeleteSelectedNormalPages(aSelectedPages
);
124 DeleteSelectedMasterPages(aSelectedPages
);
125 mrSlideSorter
.GetView().EndUndo ();
127 mrController
.HandleModelChange();
131 assert(pDrawViewShell
);
132 pDrawView
->BlockPageOrderChangedHint(false);
133 pDrawViewShell
->ResetActualPage();
136 // Show focus and move it to next valid location.
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)
171 const sal_uInt16
nPage (model::FromCoreIndex((*aI
)->GetPageNum()));
173 Reference
< XDrawPage
> xPage( xPages
->getByIndex( nPage
), UNO_QUERY_THROW
);
174 xPages
->remove(xPage
);
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)
204 const sal_uInt16
nPage (model::FromCoreIndex((*aI
)->GetPageNum()));
206 Reference
< XDrawPage
> xPage( xPages
->getByIndex( nPage
), UNO_QUERY_THROW
);
207 xPages
->remove(xPage
);
212 OSL_FAIL("SelectionManager::DeleteSelectedMasterPages(), exception caught!");
216 void SelectionManager::SelectionHasChanged ()
218 ViewShell
* pViewShell
= mrSlideSorter
.GetViewShell();
219 if (pViewShell
== nullptr)
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
);
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
)
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
)
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 (
265 maSelectionChangeListeners
.begin(),
266 maSelectionChangeListeners
.end(),
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
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());
304 mnInsertionPosition
= nInsertionPosition
;
307 } } } // end of namespace ::sd::slidesorter
309 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */