1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24 #include "precompiled_sd.hxx"
25
26 #include "controller/SlsSelectionManager.hxx"
27
28 #include "SlideSorter.hxx"
29 #include "SlsCommand.hxx"
30 #include "controller/SlideSorterController.hxx"
31 #include "controller/SlsAnimator.hxx"
32 #include "controller/SlsAnimationFunction.hxx"
33 #include "controller/SlsCurrentSlideManager.hxx"
34 #include "controller/SlsFocusManager.hxx"
35 #include "controller/SlsPageSelector.hxx"
36 #include "controller/SlsProperties.hxx"
37 #include "controller/SlsScrollBarManager.hxx"
38 #include "controller/SlsSlotManager.hxx"
39 #include "controller/SlsSelectionObserver.hxx"
40 #include "model/SlideSorterModel.hxx"
41 #include "model/SlsPageEnumerationProvider.hxx"
42 #include "model/SlsPageDescriptor.hxx"
43 #include "view/SlideSorterView.hxx"
44 #include "view/SlsLayouter.hxx"
45 #include "drawdoc.hxx"
46 #include "Window.hxx"
47 #include <svx/svxids.hrc>
48 #include <com/sun/star/drawing/XMasterPagesSupplier.hpp>
49 #include <com/sun/star/drawing/XDrawPagesSupplier.hpp>
50
51 #include "res_bmp.hrc"
52 #include "sdresid.hxx"
53 #include "strings.hrc"
54 #include "app.hrc"
55 #include "glob.hrc"
56
57
58 using namespace ::com::sun::star;
59 using namespace ::com::sun::star::drawing;
60 using namespace ::com::sun::star::uno;
61 using namespace ::sd::slidesorter::model;
62 using namespace ::sd::slidesorter::view;
63 using namespace ::sd::slidesorter::controller;
64
65 namespace sd { namespace slidesorter { namespace controller {
66
67
68 class SelectionManager::PageInsertionListener
69 : public SfxListener
70 {
71 public:
72
73 };
74
75
SelectionManager(SlideSorter & rSlideSorter)76 SelectionManager::SelectionManager (SlideSorter& rSlideSorter)
77 : mrSlideSorter(rSlideSorter),
78 mrController(rSlideSorter.GetController()),
79 maSelectionBeforeSwitch(),
80 mbIsMakeSelectionVisiblePending(true),
81 mnInsertionPosition(-1),
82 mnAnimationId(Animator::NotAnAnimationId),
83 maRequestedTopLeft(),
84 mpPageInsertionListener(),
85 mpSelectionObserver(new SelectionObserver(rSlideSorter))
86 {
87 }
88
89
90
91
~SelectionManager(void)92 SelectionManager::~SelectionManager (void)
93 {
94 if (mnAnimationId != Animator::NotAnAnimationId)
95 mrController.GetAnimator()->RemoveAnimation(mnAnimationId);
96 }
97
98
99
100
DeleteSelectedPages(const bool bSelectFollowingPage)101 void SelectionManager::DeleteSelectedPages (const bool bSelectFollowingPage)
102 {
103 // Create some locks to prevent updates of the model, view, selection
104 // state while modifying any of them.
105 SlideSorterController::ModelChangeLock aLock (mrController);
106 SlideSorterView::DrawLock aDrawLock (mrSlideSorter);
107 PageSelector::UpdateLock aSelectionLock (mrSlideSorter);
108
109 // Hide focus.
110 bool bIsFocusShowing = mrController.GetFocusManager().IsFocusShowing();
111 if (bIsFocusShowing)
112 mrController.GetFocusManager().ToggleFocus();
113
114 // Store pointers to all selected page descriptors. This is necessary
115 // because the pages get deselected when the first one is deleted.
116 model::PageEnumeration aPageEnumeration (
117 PageEnumerationProvider::CreateSelectedPagesEnumeration(mrSlideSorter.GetModel()));
118 ::std::vector<SdPage*> aSelectedPages;
119 sal_Int32 nNewCurrentSlide (-1);
120 while (aPageEnumeration.HasMoreElements())
121 {
122 SharedPageDescriptor pDescriptor (aPageEnumeration.GetNextElement());
123 aSelectedPages.push_back(pDescriptor->GetPage());
124 if (bSelectFollowingPage || nNewCurrentSlide<0)
125 nNewCurrentSlide = pDescriptor->GetPageIndex();
126 }
127 if (aSelectedPages.empty())
128 return;
129
130 // Determine the slide to select (and thereby make the current slide)
131 // after the deletion.
132 if (bSelectFollowingPage)
133 nNewCurrentSlide -= aSelectedPages.size() - 1;
134 else
135 --nNewCurrentSlide;
136
137 // The actual deletion of the selected pages is done in one of two
138 // helper functions. They are specialized for normal respectively for
139 // master pages.
140 mrSlideSorter.GetView().BegUndo (SdResId(STR_UNDO_DELETEPAGES));
141 if (mrSlideSorter.GetModel().GetEditMode() == EM_PAGE)
142 DeleteSelectedNormalPages(aSelectedPages);
143 else
144 DeleteSelectedMasterPages(aSelectedPages);
145 mrSlideSorter.GetView().EndUndo ();
146
147 mrController.HandleModelChange();
148 aLock.Release();
149
150 // Show focus and move it to next valid location.
151 if (bIsFocusShowing)
152 mrController.GetFocusManager().ToggleFocus();
153
154 // Set the new current slide.
155 if (nNewCurrentSlide < 0)
156 nNewCurrentSlide = 0;
157 else if (nNewCurrentSlide >= mrSlideSorter.GetModel().GetPageCount())
158 nNewCurrentSlide = mrSlideSorter.GetModel().GetPageCount()-1;
159 mrController.GetPageSelector().CountSelectedPages();
160 mrController.GetPageSelector().SelectPage(nNewCurrentSlide);
161 mrController.GetFocusManager().SetFocusedPage(nNewCurrentSlide);
162 }
163
164
165
166
DeleteSelectedNormalPages(const::std::vector<SdPage * > & rSelectedPages)167 void SelectionManager::DeleteSelectedNormalPages (const ::std::vector<SdPage*>& rSelectedPages)
168 {
169 // Prepare the deletion via the UNO API.
170 OSL_ASSERT(mrSlideSorter.GetModel().GetEditMode() == EM_PAGE);
171
172 try
173 {
174 Reference<drawing::XDrawPagesSupplier> xDrawPagesSupplier( mrSlideSorter.GetModel().GetDocument()->getUnoModel(), UNO_QUERY_THROW );
175 Reference<drawing::XDrawPages> xPages( xDrawPagesSupplier->getDrawPages(), UNO_QUERY_THROW );
176
177 // Iterate over all pages that where seleted when this method was called
178 // and delete the draw page the notes page. The iteration is done in
179 // reverse order so that when one slide is not deleted (to avoid an
180 // empty document) the remaining slide is the first one.
181 ::std::vector<SdPage*>::const_reverse_iterator aI;
182 for (aI=rSelectedPages.rbegin(); aI!=rSelectedPages.rend(); aI++)
183 {
184 // Do not delete the last slide in the document.
185 if (xPages->getCount() <= 1)
186 break;
187
188 const sal_uInt16 nPage (model::FromCoreIndex((*aI)->GetPageNum()));
189
190 Reference< XDrawPage > xPage( xPages->getByIndex( nPage ), UNO_QUERY_THROW );
191 xPages->remove(xPage);
192 }
193 }
194 catch( Exception& )
195 {
196 DBG_ERROR("SelectionManager::DeleteSelectedNormalPages(), exception caught!");
197 }
198 }
199
200
201
202
DeleteSelectedMasterPages(const::std::vector<SdPage * > & rSelectedPages)203 void SelectionManager::DeleteSelectedMasterPages (const ::std::vector<SdPage*>& rSelectedPages)
204 {
205 // Prepare the deletion via the UNO API.
206 OSL_ASSERT(mrSlideSorter.GetModel().GetEditMode() == EM_MASTERPAGE);
207
208 try
209 {
210 Reference<drawing::XMasterPagesSupplier> xDrawPagesSupplier( mrSlideSorter.GetModel().GetDocument()->getUnoModel(), UNO_QUERY_THROW );
211 Reference<drawing::XDrawPages> xPages( xDrawPagesSupplier->getMasterPages(), UNO_QUERY_THROW );
212
213 // Iterate over all pages that where seleted when this method was called
214 // and delete the draw page the notes page. The iteration is done in
215 // reverse order so that when one slide is not deleted (to avoid an
216 // empty document) the remaining slide is the first one.
217 ::std::vector<SdPage*>::const_reverse_iterator aI;
218 for (aI=rSelectedPages.rbegin(); aI!=rSelectedPages.rend(); aI++)
219 {
220 // Do not delete the last slide in the document.
221 if (xPages->getCount() <= 1)
222 break;
223
224 const sal_uInt16 nPage (model::FromCoreIndex((*aI)->GetPageNum()));
225
226 Reference< XDrawPage > xPage( xPages->getByIndex( nPage ), UNO_QUERY_THROW );
227 xPages->remove(xPage);
228 }
229 }
230 catch( Exception& )
231 {
232 DBG_ERROR("SelectionManager::DeleteSelectedMasterPages(), exception caught!");
233 }
234 }
235
236
237
238
SelectionHasChanged(const bool bMakeSelectionVisible)239 void SelectionManager::SelectionHasChanged (const bool bMakeSelectionVisible)
240 {
241 if (bMakeSelectionVisible)
242 mbIsMakeSelectionVisiblePending = true;
243
244 ViewShell* pViewShell = mrSlideSorter.GetViewShell();
245 if (pViewShell != NULL)
246 {
247 pViewShell->Invalidate (SID_EXPAND_PAGE);
248 pViewShell->Invalidate (SID_SUMMARY_PAGE);
249 pViewShell->Invalidate(SID_SHOW_SLIDE);
250 pViewShell->Invalidate(SID_HIDE_SLIDE);
251 pViewShell->Invalidate(SID_DELETE_PAGE);
252 pViewShell->Invalidate(SID_DELETE_MASTER_PAGE);
253 pViewShell->Invalidate(SID_ASSIGN_LAYOUT);
254
255 // StatusBar
256 pViewShell->Invalidate (SID_STATUS_PAGE);
257 pViewShell->Invalidate (SID_STATUS_LAYOUT);
258
259 OSL_ASSERT(mrController.GetCurrentSlideManager());
260 SharedPageDescriptor pDescriptor(mrController.GetCurrentSlideManager()->GetCurrentSlide());
261 if (pDescriptor.get() != NULL)
262 pViewShell->UpdatePreview(pDescriptor->GetPage());
263
264 // Tell the slection change listeners that the selection has changed.
265 ::std::vector<Link>::iterator iListener (maSelectionChangeListeners.begin());
266 ::std::vector<Link>::iterator iEnd (maSelectionChangeListeners.end());
267 for (; iListener!=iEnd; ++iListener)
268 {
269 iListener->Call(NULL);
270 }
271
272 // Reset the insertion position: until set again it is calculated from
273 // the current selection.
274 mnInsertionPosition = -1;
275 }
276 }
277
278
279
280
AddSelectionChangeListener(const Link & rListener)281 void SelectionManager::AddSelectionChangeListener (const Link& rListener)
282 {
283 if (::std::find (
284 maSelectionChangeListeners.begin(),
285 maSelectionChangeListeners.end(),
286 rListener) == maSelectionChangeListeners.end())
287 {
288 maSelectionChangeListeners.push_back (rListener);
289 }
290 }
291
292
293
294
RemoveSelectionChangeListener(const Link & rListener)295 void SelectionManager::RemoveSelectionChangeListener(const Link&rListener)
296 {
297 maSelectionChangeListeners.erase (
298 ::std::find (
299 maSelectionChangeListeners.begin(),
300 maSelectionChangeListeners.end(),
301 rListener));
302 }
303
304
305
306
GetInsertionPosition(void) const307 sal_Int32 SelectionManager::GetInsertionPosition (void) const
308 {
309 sal_Int32 nInsertionPosition (mnInsertionPosition);
310 if (nInsertionPosition < 0)
311 {
312 model::PageEnumeration aSelectedPages
313 (model::PageEnumerationProvider::CreateSelectedPagesEnumeration(
314 mrSlideSorter.GetModel()));
315 // Initialize (for the case of an empty selection) with the position
316 // at the end of the document.
317 nInsertionPosition = mrSlideSorter.GetModel().GetPageCount();
318 while (aSelectedPages.HasMoreElements())
319 {
320 const sal_Int32 nPosition (aSelectedPages.GetNextElement()->GetPage()->GetPageNum());
321 // Convert *2+1 index to straight index (n-1)/2 after the page
322 // (+1).
323 nInsertionPosition = model::FromCoreIndex(nPosition) + 1;
324 }
325
326 }
327 return nInsertionPosition;
328 }
329
330
331
332
SetInsertionPosition(const sal_Int32 nInsertionPosition)333 void SelectionManager::SetInsertionPosition (const sal_Int32 nInsertionPosition)
334 {
335 if (nInsertionPosition < 0)
336 mnInsertionPosition = -1;
337 else if (nInsertionPosition > mrSlideSorter.GetModel().GetPageCount())
338 {
339 // Assert but then ignore invalid values.
340 OSL_ASSERT(nInsertionPosition<=mrSlideSorter.GetModel().GetPageCount());
341 return;
342 }
343 else
344 mnInsertionPosition = nInsertionPosition;
345 }
346
347
348
349
GetSelectionObserver(void) const350 ::boost::shared_ptr<SelectionObserver> SelectionManager::GetSelectionObserver (void) const
351 {
352 return mpSelectionObserver;
353 }
354
355 } } } // end of namespace ::sd::slidesorter
356