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