Move setting of LD_LIBRARY_PATH closer to invocation of cppunittester
[LibreOffice.git] / sd / source / ui / slidesorter / controller / SlsSelectionManager.cxx
blob71865af5727f34e63a9c6b141efacfdf50748ddf
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/SlsCurrentSlideManager.hxx>
25 #include <controller/SlsFocusManager.hxx>
26 #include <controller/SlsPageSelector.hxx>
27 #include <controller/SlsSelectionObserver.hxx>
28 #include <model/SlideSorterModel.hxx>
29 #include <model/SlsPageEnumerationProvider.hxx>
30 #include <model/SlsPageDescriptor.hxx>
31 #include <view/SlideSorterView.hxx>
32 #include <comphelper/diagnose_ex.hxx>
33 #include <drawdoc.hxx>
34 #include <sdpage.hxx>
35 #include <unomodel.hxx>
36 #include <drawview.hxx>
37 #include <DrawViewShell.hxx>
38 #include <ViewShellBase.hxx>
39 #include <svx/svxids.hrc>
40 #include <com/sun/star/drawing/XMasterPagesSupplier.hpp>
41 #include <com/sun/star/drawing/XDrawPagesSupplier.hpp>
44 #include <sdresid.hxx>
45 #include <strings.hrc>
46 #include <app.hrc>
48 using namespace ::com::sun::star;
49 using namespace ::com::sun::star::drawing;
50 using namespace ::com::sun::star::uno;
51 using namespace ::sd::slidesorter::model;
52 using namespace ::sd::slidesorter::view;
53 using namespace ::sd::slidesorter::controller;
55 namespace sd::slidesorter::controller {
57 SelectionManager::SelectionManager (SlideSorter& rSlideSorter)
58 : mrSlideSorter(rSlideSorter),
59 mrController(rSlideSorter.GetController()),
60 mnInsertionPosition(-1),
61 mpSelectionObserver(std::make_shared<SelectionObserver>(rSlideSorter))
65 SelectionManager::~SelectionManager()
69 void SelectionManager::DeleteSelectedPages (const bool bSelectFollowingPage)
71 // Create some locks to prevent updates of the model, view, selection
72 // state while modifying any of them.
73 SlideSorterController::ModelChangeLock aLock (mrController);
74 SlideSorterView::DrawLock aDrawLock (mrSlideSorter);
75 PageSelector::UpdateLock aSelectionLock (mrSlideSorter);
77 // Hide focus.
78 bool bIsFocusShowing = mrController.GetFocusManager().IsFocusShowing();
79 if (bIsFocusShowing)
80 mrController.GetFocusManager().ToggleFocus();
82 // Store pointers to all selected page descriptors. This is necessary
83 // because the pages get deselected when the first one is deleted.
84 model::PageEnumeration aPageEnumeration (
85 PageEnumerationProvider::CreateSelectedPagesEnumeration(mrSlideSorter.GetModel()));
86 ::std::vector<SdPage*> aSelectedPages;
87 sal_Int32 nNewCurrentSlide (-1);
88 while (aPageEnumeration.HasMoreElements())
90 SharedPageDescriptor pDescriptor (aPageEnumeration.GetNextElement());
91 aSelectedPages.push_back(pDescriptor->GetPage());
92 if (bSelectFollowingPage || nNewCurrentSlide<0)
93 nNewCurrentSlide = pDescriptor->GetPageIndex();
95 if (aSelectedPages.empty())
96 return;
98 // Determine the slide to select (and thereby make the current slide)
99 // after the deletion.
100 if (bSelectFollowingPage)
101 nNewCurrentSlide -= aSelectedPages.size() - 1;
102 else
103 --nNewCurrentSlide;
105 const auto pViewShell = mrSlideSorter.GetViewShell();
106 const auto pDrawViewShell = pViewShell ? std::dynamic_pointer_cast<sd::DrawViewShell>(pViewShell->GetViewShellBase().GetMainViewShell()) : nullptr;
107 const auto pDrawView = pDrawViewShell ? pDrawViewShell->GetDrawView() : nullptr;
109 if (pDrawView)
110 pDrawView->BlockPageOrderChangedHint(true);
112 // Proper naming for the undo action
113 OUString sUndoComment(SdResId(STR_UNDO_DELETEPAGES));
114 if (mrSlideSorter.GetView().GetDoc().GetDocumentType() == DocumentType::Draw)
115 sUndoComment = SdResId(STR_UNDO_DELETEPAGES_DRAW);
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 (sUndoComment);
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 rtl::Reference<SdXImpressDocument> xDrawPagesSupplier( mrSlideSorter.GetModel().GetDocument()->getUnoModel() );
158 if (!xDrawPagesSupplier)
159 return;
160 Reference<drawing::XDrawPages> xPages( xDrawPagesSupplier->getDrawPages(), UNO_SET_THROW );
162 // Iterate over all pages that were selected when this method was called
163 // and delete the draw page the notes page. The iteration is done in
164 // reverse order so that when one slide is not deleted (to avoid an
165 // empty document) the remaining slide is the first one.
166 ::std::vector<SdPage*>::const_reverse_iterator aI;
167 for (aI=rSelectedPages.rbegin(); aI!=rSelectedPages.rend(); ++aI)
169 // Do not delete the last slide in the document.
170 if (xPages->getCount() <= 1)
171 break;
173 const sal_uInt16 nPage (model::FromCoreIndex((*aI)->GetPageNum()));
175 Reference< XDrawPage > xPage( xPages->getByIndex( nPage ), UNO_QUERY_THROW );
176 xPages->remove(xPage);
179 catch( Exception& )
181 TOOLS_WARN_EXCEPTION( "sd", "SelectionManager::DeleteSelectedNormalPages()");
185 void SelectionManager::DeleteSelectedMasterPages (const ::std::vector<SdPage*>& rSelectedPages)
187 // Prepare the deletion via the UNO API.
188 OSL_ASSERT(mrSlideSorter.GetModel().GetEditMode() == EditMode::MasterPage);
192 rtl::Reference<SdXImpressDocument> xDrawPagesSupplier( mrSlideSorter.GetModel().GetDocument()->getUnoModel() );
193 if (!xDrawPagesSupplier)
194 return;
195 Reference<drawing::XDrawPages> xPages( xDrawPagesSupplier->getMasterPages(), UNO_SET_THROW );
197 // Iterate over all pages that were selected when this method was called
198 // and delete the draw page the notes page. The iteration is done in
199 // reverse order so that when one slide is not deleted (to avoid an
200 // empty document) the remaining slide is the first one.
201 ::std::vector<SdPage*>::const_reverse_iterator aI;
202 for (aI=rSelectedPages.rbegin(); aI!=rSelectedPages.rend(); ++aI)
204 // Do not delete the last slide in the document.
205 if (xPages->getCount() <= 1)
206 break;
208 const sal_uInt16 nPage (model::FromCoreIndex((*aI)->GetPageNum()));
210 Reference< XDrawPage > xPage( xPages->getByIndex( nPage ), UNO_QUERY_THROW );
211 xPages->remove(xPage);
214 catch( Exception& )
216 TOOLS_WARN_EXCEPTION( "sd", "SelectionManager::DeleteSelectedMasterPages()");
220 void SelectionManager::SelectionHasChanged ()
222 ViewShell* pViewShell = mrSlideSorter.GetViewShell();
223 if (pViewShell == nullptr)
224 return;
226 pViewShell->Invalidate (SID_EXPAND_PAGE);
227 pViewShell->Invalidate (SID_SUMMARY_PAGE);
228 pViewShell->Invalidate(SID_SHOW_SLIDE);
229 pViewShell->Invalidate(SID_HIDE_SLIDE);
230 pViewShell->Invalidate(SID_DELETE_PAGE);
231 pViewShell->Invalidate(SID_DELETE_MASTER_PAGE);
232 pViewShell->Invalidate(SID_ASSIGN_LAYOUT);
234 // StatusBar
235 pViewShell->Invalidate (SID_STATUS_PAGE);
236 pViewShell->Invalidate (SID_STATUS_LAYOUT);
237 pViewShell->Invalidate (SID_SCALE);
239 OSL_ASSERT(mrController.GetCurrentSlideManager());
240 SharedPageDescriptor pDescriptor(mrController.GetCurrentSlideManager()->GetCurrentSlide());
241 if (pDescriptor)
242 pViewShell->UpdatePreview(pDescriptor->GetPage());
244 // Tell the selection change listeners that the selection has changed.
245 for (const auto& rLink : maSelectionChangeListeners)
247 rLink.Call(nullptr);
250 // Reset the insertion position: until set again it is calculated from
251 // the current selection.
252 mnInsertionPosition = -1;
255 void SelectionManager::AddSelectionChangeListener (const Link<LinkParamNone*,void>& rListener)
257 if (::std::find (
258 maSelectionChangeListeners.begin(),
259 maSelectionChangeListeners.end(),
260 rListener) == maSelectionChangeListeners.end())
262 maSelectionChangeListeners.push_back (rListener);
266 void SelectionManager::RemoveSelectionChangeListener(const Link<LinkParamNone*,void>& rListener)
268 maSelectionChangeListeners.erase (
269 ::std::find (
270 maSelectionChangeListeners.begin(),
271 maSelectionChangeListeners.end(),
272 rListener));
275 sal_Int32 SelectionManager::GetInsertionPosition() const
277 sal_Int32 nInsertionPosition (mnInsertionPosition);
278 if (nInsertionPosition < 0)
280 model::PageEnumeration aSelectedPages
281 (model::PageEnumerationProvider::CreateSelectedPagesEnumeration(
282 mrSlideSorter.GetModel()));
283 // Initialize (for the case of an empty selection) with the position
284 // at the end of the document.
285 nInsertionPosition = mrSlideSorter.GetModel().GetPageCount();
286 while (aSelectedPages.HasMoreElements())
288 const sal_Int32 nPosition (aSelectedPages.GetNextElement()->GetPage()->GetPageNum());
289 // Convert *2+1 index to straight index (n-1)/2 after the page
290 // (+1).
291 nInsertionPosition = model::FromCoreIndex(nPosition) + 1;
295 return nInsertionPosition;
298 void SelectionManager::SetInsertionPosition (const sal_Int32 nInsertionPosition)
300 if (nInsertionPosition < 0)
301 mnInsertionPosition = -1;
302 else if (nInsertionPosition > mrSlideSorter.GetModel().GetPageCount())
304 // Assert but then ignore invalid values.
305 OSL_ASSERT(nInsertionPosition<=mrSlideSorter.GetModel().GetPageCount());
306 return;
308 else
309 mnInsertionPosition = nInsertionPosition;
312 } // end of namespace ::sd::slidesorter::controller
314 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */