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/SlsPageSelector.hxx"
27
28 #include "SlideSorter.hxx"
29 #include "SlideSorterViewShell.hxx"
30 #include "controller/SlideSorterController.hxx"
31 #include "controller/SlsSelectionManager.hxx"
32 #include "controller/SlsAnimator.hxx"
33 #include "controller/SlsCurrentSlideManager.hxx"
34 #include "controller/SlsVisibleAreaManager.hxx"
35 #include "model/SlsPageDescriptor.hxx"
36 #include "model/SlsPageEnumerationProvider.hxx"
37 #include "model/SlideSorterModel.hxx"
38 #include "view/SlideSorterView.hxx"
39
40 #include "sdpage.hxx"
41 #include "ViewShell.hxx"
42 #include "DrawViewShell.hxx"
43 #include "ViewShellBase.hxx"
44 #include <com/sun/star/drawing/XDrawView.hpp>
45 #include <com/sun/star/beans/XPropertySet.hpp>
46 #include <boost/bind.hpp>
47
48
49 using namespace ::com::sun::star;
50 using namespace ::com::sun::star::uno;
51 using namespace ::sd::slidesorter::model;
52 using namespace ::sd::slidesorter::view;
53
54
55 namespace sd { namespace slidesorter { namespace controller {
56
PageSelector(SlideSorter & rSlideSorter)57 PageSelector::PageSelector (SlideSorter& rSlideSorter)
58 : mrModel(rSlideSorter.GetModel()),
59 mrSlideSorter(rSlideSorter),
60 mrController(mrSlideSorter.GetController()),
61 mnSelectedPageCount(0),
62 mnBroadcastDisableLevel(0),
63 mbSelectionChangeBroadcastPending(false),
64 mpMostRecentlySelectedPage(),
65 mpSelectionAnchor(),
66 mpCurrentPage(),
67 mnUpdateLockCount(0),
68 mbIsUpdateCurrentPagePending(true)
69 {
70 CountSelectedPages ();
71 }
72
73
74
75
SelectAllPages(void)76 void PageSelector::SelectAllPages (void)
77 {
78 VisibleAreaManager::TemporaryDisabler aDisabler (mrSlideSorter);
79 PageSelector::UpdateLock aLock (*this);
80
81 int nPageCount = mrModel.GetPageCount();
82 for (int nPageIndex=0; nPageIndex<nPageCount; nPageIndex++)
83 SelectPage(nPageIndex);
84 }
85
86
87
88
DeselectAllPages(void)89 void PageSelector::DeselectAllPages (void)
90 {
91 VisibleAreaManager::TemporaryDisabler aDisabler (mrSlideSorter);
92 PageSelector::UpdateLock aLock (*this);
93
94 int nPageCount = mrModel.GetPageCount();
95 for (int nPageIndex=0; nPageIndex<nPageCount; nPageIndex++)
96 DeselectPage(nPageIndex);
97
98 DBG_ASSERT (mnSelectedPageCount==0,
99 "PageSelector::DeselectAllPages: the selected pages counter is not 0");
100 mnSelectedPageCount = 0;
101 mpSelectionAnchor.reset();
102 }
103
104
105
106
GetCoreSelection(void)107 void PageSelector::GetCoreSelection (void)
108 {
109 PageSelector::UpdateLock aLock (*this);
110
111 bool bSelectionHasChanged (true);
112 mnSelectedPageCount = 0;
113 model::PageEnumeration aAllPages (
114 model::PageEnumerationProvider::CreateAllPagesEnumeration(mrModel));
115 while (aAllPages.HasMoreElements())
116 {
117 model::SharedPageDescriptor pDescriptor (aAllPages.GetNextElement());
118 if (pDescriptor->GetCoreSelection())
119 {
120 mrSlideSorter.GetController().GetVisibleAreaManager().RequestVisible(pDescriptor);
121 mrSlideSorter.GetView().RequestRepaint(pDescriptor);
122 bSelectionHasChanged = true;
123 }
124
125 if (pDescriptor->HasState(PageDescriptor::ST_Selected))
126 mnSelectedPageCount++;
127 }
128
129 if (bSelectionHasChanged)
130 {
131 if (mnBroadcastDisableLevel > 0)
132 mbSelectionChangeBroadcastPending = true;
133 else
134 mrController.GetSelectionManager()->SelectionHasChanged();
135 }
136 }
137
138
139
140
SetCoreSelection(void)141 void PageSelector::SetCoreSelection (void)
142 {
143 model::PageEnumeration aAllPages (
144 model::PageEnumerationProvider::CreateAllPagesEnumeration(mrModel));
145 while (aAllPages.HasMoreElements())
146 {
147 model::SharedPageDescriptor pDescriptor (aAllPages.GetNextElement());
148 pDescriptor->SetCoreSelection();
149 }
150 }
151
152
153
154
SelectPage(int nPageIndex)155 void PageSelector::SelectPage (int nPageIndex)
156 {
157 SharedPageDescriptor pDescriptor (mrModel.GetPageDescriptor(nPageIndex));
158 if (pDescriptor.get() != NULL)
159 SelectPage(pDescriptor);
160 }
161
162
163
164
SelectPage(const SdPage * pPage)165 void PageSelector::SelectPage (const SdPage* pPage)
166 {
167 const sal_Int32 nPageIndex (mrModel.GetIndex(pPage));
168 SharedPageDescriptor pDescriptor (mrModel.GetPageDescriptor(nPageIndex));
169 if (pDescriptor.get()!=NULL && pDescriptor->GetPage()==pPage)
170 SelectPage(pDescriptor);
171 }
172
173
174
175
SelectPage(const SharedPageDescriptor & rpDescriptor)176 void PageSelector::SelectPage (const SharedPageDescriptor& rpDescriptor)
177 {
178 if (rpDescriptor.get()!=NULL
179 && mrSlideSorter.GetView().SetState(rpDescriptor, PageDescriptor::ST_Selected, true))
180 {
181 ++mnSelectedPageCount;
182 mrSlideSorter.GetController().GetVisibleAreaManager().RequestVisible(rpDescriptor,true);
183 mrSlideSorter.GetView().RequestRepaint(rpDescriptor);
184
185 mpMostRecentlySelectedPage = rpDescriptor;
186 if( !bool(mpSelectionAnchor) )
187 mpSelectionAnchor = rpDescriptor;
188
189 if (mnBroadcastDisableLevel > 0)
190 mbSelectionChangeBroadcastPending = true;
191 else
192 mrController.GetSelectionManager()->SelectionHasChanged();
193 UpdateCurrentPage();
194
195 CheckConsistency();
196 }
197 }
198
199
200
201
DeselectPage(int nPageIndex,const bool bUpdateCurrentPage)202 void PageSelector::DeselectPage (
203 int nPageIndex,
204 const bool bUpdateCurrentPage)
205 {
206 model::SharedPageDescriptor pDescriptor (mrModel.GetPageDescriptor(nPageIndex));
207 if (pDescriptor.get() != NULL)
208 DeselectPage(pDescriptor, bUpdateCurrentPage);
209 }
210
211
212
213
DeselectPage(const SdPage * pPage,const bool bUpdateCurrentPage)214 void PageSelector::DeselectPage (
215 const SdPage* pPage,
216 const bool bUpdateCurrentPage)
217 {
218 const sal_Int32 nPageIndex (mrModel.GetIndex(pPage));
219 SharedPageDescriptor pDescriptor (mrModel.GetPageDescriptor(nPageIndex));
220 if (pDescriptor.get()!=NULL && pDescriptor->GetPage()==pPage)
221 DeselectPage(pDescriptor, bUpdateCurrentPage);
222 }
223
224
225
226
DeselectPage(const SharedPageDescriptor & rpDescriptor,const bool bUpdateCurrentPage)227 void PageSelector::DeselectPage (
228 const SharedPageDescriptor& rpDescriptor,
229 const bool bUpdateCurrentPage)
230 {
231 if (rpDescriptor.get()!=NULL
232 && mrSlideSorter.GetView().SetState(rpDescriptor, PageDescriptor::ST_Selected, false))
233 {
234 --mnSelectedPageCount;
235 mrSlideSorter.GetController().GetVisibleAreaManager().RequestVisible(rpDescriptor);
236 mrSlideSorter.GetView().RequestRepaint(rpDescriptor);
237 if (mpMostRecentlySelectedPage == rpDescriptor)
238 mpMostRecentlySelectedPage.reset();
239 if (mnBroadcastDisableLevel > 0)
240 mbSelectionChangeBroadcastPending = true;
241 else
242 mrController.GetSelectionManager()->SelectionHasChanged();
243 if (bUpdateCurrentPage)
244 UpdateCurrentPage();
245
246 CheckConsistency();
247 }
248 }
249
250
251
252
CheckConsistency(void) const253 void PageSelector::CheckConsistency (void) const
254 {
255 int nSelectionCount (0);
256 for (int nPageIndex=0,nPageCount=mrModel.GetPageCount(); nPageIndex<nPageCount; nPageIndex++)
257 {
258 SharedPageDescriptor pDescriptor (mrModel.GetPageDescriptor(nPageIndex));
259 assert(pDescriptor);
260 if (pDescriptor->HasState(PageDescriptor::ST_Selected))
261 ++nSelectionCount;
262 }
263 if (nSelectionCount!=mnSelectedPageCount)
264 {
265 // #120020# The former call to assert(..) internally calls
266 // SlideSorterModel::GetPageDescriptor which will crash in this situation
267 // (only in non-pro code). All what is wanted there is to assert it (the
268 // error is already detected), so do this directly.
269 OSL_ENSURE(false, "PageSelector: Consistency error (!)");
270 }
271 }
272
273
274
275
IsPageSelected(int nPageIndex)276 bool PageSelector::IsPageSelected (int nPageIndex)
277 {
278 SharedPageDescriptor pDescriptor (mrModel.GetPageDescriptor(nPageIndex));
279 if (pDescriptor.get() != NULL)
280 return pDescriptor->HasState(PageDescriptor::ST_Selected);
281 else
282 return false;
283 }
284
285
286
287
GetPageCount(void) const288 int PageSelector::GetPageCount (void) const
289 {
290 return mrModel.GetPageCount();
291 }
292
293
294
295
GetSelectedPageCount(void) const296 int PageSelector::GetSelectedPageCount (void) const
297 {
298 return mnSelectedPageCount;
299 }
300
301
302
303
GetSelectionAnchor(void) const304 SharedPageDescriptor PageSelector::GetSelectionAnchor (void) const
305 {
306 return mpSelectionAnchor;
307 }
308
309
310
311
CountSelectedPages(void)312 void PageSelector::CountSelectedPages (void)
313 {
314 mnSelectedPageCount = 0;
315 model::PageEnumeration aSelectedPages (
316 model::PageEnumerationProvider::CreateSelectedPagesEnumeration(mrModel));
317 while (aSelectedPages.HasMoreElements())
318 {
319 mnSelectedPageCount++;
320 aSelectedPages.GetNextElement();
321 }
322 }
323
324
325
326
EnableBroadcasting(void)327 void PageSelector::EnableBroadcasting (void)
328 {
329 if (mnBroadcastDisableLevel > 0)
330 mnBroadcastDisableLevel --;
331 if (mnBroadcastDisableLevel==0 && mbSelectionChangeBroadcastPending)
332 {
333 mrController.GetSelectionManager()->SelectionHasChanged();
334 mbSelectionChangeBroadcastPending = false;
335 }
336 }
337
338
339
340
DisableBroadcasting(void)341 void PageSelector::DisableBroadcasting (void)
342 {
343 mnBroadcastDisableLevel ++;
344 }
345
346
347
348
GetPageSelection(void) const349 ::boost::shared_ptr<PageSelector::PageSelection> PageSelector::GetPageSelection (void) const
350 {
351 ::boost::shared_ptr<PageSelection> pSelection (new PageSelection());
352 pSelection->reserve(GetSelectedPageCount());
353
354 int nPageCount = GetPageCount();
355 for (int nIndex=0; nIndex<nPageCount; nIndex++)
356 {
357 SharedPageDescriptor pDescriptor (mrModel.GetPageDescriptor(nIndex));
358 if (pDescriptor.get()!=NULL && pDescriptor->HasState(PageDescriptor::ST_Selected))
359 pSelection->push_back(pDescriptor->GetPage());
360 }
361
362 return pSelection;
363 }
364
365
366
367
SetPageSelection(const::boost::shared_ptr<PageSelection> & rpSelection,const bool bUpdateCurrentPage)368 void PageSelector::SetPageSelection (
369 const ::boost::shared_ptr<PageSelection>& rpSelection,
370 const bool bUpdateCurrentPage)
371 {
372 PageSelection::const_iterator iPage;
373 for (iPage=rpSelection->begin(); iPage!=rpSelection->end(); ++iPage)
374 SelectPage(*iPage);
375 if (bUpdateCurrentPage)
376 UpdateCurrentPage();
377 }
378
379
380
381
UpdateCurrentPage(const bool bUpdateOnlyWhenPending)382 void PageSelector::UpdateCurrentPage (const bool bUpdateOnlyWhenPending)
383 {
384 if (mnUpdateLockCount > 0)
385 {
386 mbIsUpdateCurrentPagePending = true;
387 return;
388 }
389
390 if ( ! mbIsUpdateCurrentPagePending && bUpdateOnlyWhenPending)
391 return;
392
393 mbIsUpdateCurrentPagePending = false;
394
395 // Make the first selected page the current page.
396 SharedPageDescriptor pCurrentPageDescriptor;
397 const sal_Int32 nPageCount (GetPageCount());
398 for (sal_Int32 nIndex=0; nIndex<nPageCount; ++nIndex)
399 {
400 SharedPageDescriptor pDescriptor (mrModel.GetPageDescriptor(nIndex));
401 if ( ! pDescriptor)
402 continue;
403 if (pDescriptor->HasState(PageDescriptor::ST_Selected))
404 {
405 pCurrentPageDescriptor = pDescriptor;
406 break;
407 }
408 }
409
410 if (pCurrentPageDescriptor)
411 {
412 // Switching the current slide normally sets also the
413 // selection to just the new current slide. To prevent that,
414 // we store (and at the end of this scope restore) the current
415 // selection.
416 ::boost::shared_ptr<PageSelection> pSelection (GetPageSelection());
417
418 mrController.GetCurrentSlideManager()->SwitchCurrentSlide(pCurrentPageDescriptor);
419
420 // Restore the selection and prevent a recursive call to
421 // UpdateCurrentPage().
422 SetPageSelection(pSelection, false);
423 }
424 }
425
426
427
428
429 //===== PageSelector::UpdateLock ==============================================
430
UpdateLock(SlideSorter & rSlideSorter)431 PageSelector::UpdateLock::UpdateLock (SlideSorter& rSlideSorter)
432 : mpSelector(&rSlideSorter.GetController().GetPageSelector())
433 {
434 ++mpSelector->mnUpdateLockCount;
435 }
436
437
438
439
UpdateLock(PageSelector & rSelector)440 PageSelector::UpdateLock::UpdateLock (PageSelector& rSelector)
441 : mpSelector(&rSelector)
442 {
443 ++mpSelector->mnUpdateLockCount;
444 }
445
446
447
448
~UpdateLock(void)449 PageSelector::UpdateLock::~UpdateLock (void)
450 {
451 Release();
452 }
453
Release(void)454 void PageSelector::UpdateLock::Release (void)
455 {
456 if (mpSelector != NULL)
457 {
458 --mpSelector->mnUpdateLockCount;
459 OSL_ASSERT(mpSelector->mnUpdateLockCount >= 0);
460 if (mpSelector->mnUpdateLockCount == 0)
461 mpSelector->UpdateCurrentPage(true);
462
463 mpSelector = NULL;
464 }
465 }
466
467
468
469
470 //===== PageSelector::BroadcastLock ==============================================
471
BroadcastLock(SlideSorter & rSlideSorter)472 PageSelector::BroadcastLock::BroadcastLock (SlideSorter& rSlideSorter)
473 : mrSelector(rSlideSorter.GetController().GetPageSelector())
474 {
475 mrSelector.DisableBroadcasting();
476 }
477
478
479
480
BroadcastLock(PageSelector & rSelector)481 PageSelector::BroadcastLock::BroadcastLock (PageSelector& rSelector)
482 : mrSelector(rSelector)
483 {
484 mrSelector.DisableBroadcasting();
485 }
486
487
488
489
~BroadcastLock(void)490 PageSelector::BroadcastLock::~BroadcastLock (void)
491 {
492 mrSelector.EnableBroadcasting();
493 }
494
495 } } } // end of namespace ::sd::slidesorter::controller
496