Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
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/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
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 .
18 : */
19 :
20 : #include "controller/SlsPageSelector.hxx"
21 :
22 : #include "SlideSorter.hxx"
23 : #include "SlideSorterViewShell.hxx"
24 : #include "controller/SlideSorterController.hxx"
25 : #include "controller/SlsSelectionManager.hxx"
26 : #include "controller/SlsAnimator.hxx"
27 : #include "controller/SlsCurrentSlideManager.hxx"
28 : #include "controller/SlsVisibleAreaManager.hxx"
29 : #include "model/SlsPageDescriptor.hxx"
30 : #include "model/SlsPageEnumerationProvider.hxx"
31 : #include "model/SlideSorterModel.hxx"
32 : #include "view/SlideSorterView.hxx"
33 :
34 : #include "sdpage.hxx"
35 : #include "ViewShell.hxx"
36 : #include "DrawViewShell.hxx"
37 : #include "ViewShellBase.hxx"
38 : #include <com/sun/star/drawing/XDrawView.hpp>
39 : #include <com/sun/star/beans/XPropertySet.hpp>
40 : #include <boost/shared_ptr.hpp>
41 :
42 : using namespace ::com::sun::star;
43 : using namespace ::com::sun::star::uno;
44 : using namespace ::sd::slidesorter::model;
45 : using namespace ::sd::slidesorter::view;
46 :
47 : namespace sd { namespace slidesorter { namespace controller {
48 :
49 126 : PageSelector::PageSelector (SlideSorter& rSlideSorter)
50 126 : : mrModel(rSlideSorter.GetModel()),
51 : mrSlideSorter(rSlideSorter),
52 126 : mrController(mrSlideSorter.GetController()),
53 : mnSelectedPageCount(0),
54 : mnBroadcastDisableLevel(0),
55 : mbSelectionChangeBroadcastPending(false),
56 : mpMostRecentlySelectedPage(),
57 : mpSelectionAnchor(),
58 : mpCurrentPage(),
59 : mnUpdateLockCount(0),
60 378 : mbIsUpdateCurrentPagePending(true)
61 : {
62 126 : CountSelectedPages ();
63 126 : }
64 :
65 0 : void PageSelector::SelectAllPages (void)
66 : {
67 0 : VisibleAreaManager::TemporaryDisabler aDisabler (mrSlideSorter);
68 0 : PageSelector::UpdateLock aLock (*this);
69 :
70 0 : int nPageCount = mrModel.GetPageCount();
71 0 : for (int nPageIndex=0; nPageIndex<nPageCount; nPageIndex++)
72 0 : SelectPage(nPageIndex);
73 0 : }
74 :
75 134 : void PageSelector::DeselectAllPages (void)
76 : {
77 134 : VisibleAreaManager::TemporaryDisabler aDisabler (mrSlideSorter);
78 268 : PageSelector::UpdateLock aLock (*this);
79 :
80 134 : int nPageCount = mrModel.GetPageCount();
81 276 : for (int nPageIndex=0; nPageIndex<nPageCount; nPageIndex++)
82 142 : DeselectPage(nPageIndex);
83 :
84 : DBG_ASSERT (mnSelectedPageCount==0,
85 : "PageSelector::DeselectAllPages: the selected pages counter is not 0");
86 134 : mnSelectedPageCount = 0;
87 268 : mpSelectionAnchor.reset();
88 134 : }
89 :
90 126 : void PageSelector::GetCoreSelection (void)
91 : {
92 126 : PageSelector::UpdateLock aLock (*this);
93 :
94 126 : bool bSelectionHasChanged (true);
95 126 : mnSelectedPageCount = 0;
96 : model::PageEnumeration aAllPages (
97 252 : model::PageEnumerationProvider::CreateAllPagesEnumeration(mrModel));
98 252 : while (aAllPages.HasMoreElements())
99 : {
100 0 : model::SharedPageDescriptor pDescriptor (aAllPages.GetNextElement());
101 0 : if (pDescriptor->GetCoreSelection())
102 : {
103 0 : mrSlideSorter.GetController().GetVisibleAreaManager().RequestVisible(pDescriptor);
104 0 : mrSlideSorter.GetView().RequestRepaint(pDescriptor);
105 0 : bSelectionHasChanged = true;
106 : }
107 :
108 0 : if (pDescriptor->HasState(PageDescriptor::ST_Selected))
109 0 : mnSelectedPageCount++;
110 0 : }
111 :
112 126 : if (bSelectionHasChanged)
113 : {
114 126 : if (mnBroadcastDisableLevel > 0)
115 0 : mbSelectionChangeBroadcastPending = true;
116 : else
117 126 : mrController.GetSelectionManager()->SelectionHasChanged();
118 126 : }
119 126 : }
120 :
121 0 : void PageSelector::SetCoreSelection (void)
122 : {
123 : model::PageEnumeration aAllPages (
124 0 : model::PageEnumerationProvider::CreateAllPagesEnumeration(mrModel));
125 0 : while (aAllPages.HasMoreElements())
126 : {
127 0 : model::SharedPageDescriptor pDescriptor (aAllPages.GetNextElement());
128 0 : pDescriptor->SetCoreSelection();
129 0 : }
130 0 : }
131 :
132 8 : void PageSelector::SelectPage (int nPageIndex)
133 : {
134 8 : SharedPageDescriptor pDescriptor (mrModel.GetPageDescriptor(nPageIndex));
135 8 : if (pDescriptor.get() != NULL)
136 8 : SelectPage(pDescriptor);
137 8 : }
138 :
139 134 : void PageSelector::SelectPage (const SdPage* pPage)
140 : {
141 134 : const sal_Int32 nPageIndex (mrModel.GetIndex(pPage));
142 134 : SharedPageDescriptor pDescriptor (mrModel.GetPageDescriptor(nPageIndex));
143 134 : if (pDescriptor.get()!=NULL && pDescriptor->GetPage()==pPage)
144 134 : SelectPage(pDescriptor);
145 134 : }
146 :
147 276 : void PageSelector::SelectPage (const SharedPageDescriptor& rpDescriptor)
148 : {
149 552 : if (rpDescriptor.get()!=NULL
150 276 : && mrSlideSorter.GetView().SetState(rpDescriptor, PageDescriptor::ST_Selected, true))
151 : {
152 134 : ++mnSelectedPageCount;
153 134 : mrSlideSorter.GetController().GetVisibleAreaManager().RequestVisible(rpDescriptor,true);
154 134 : mrSlideSorter.GetView().RequestRepaint(rpDescriptor);
155 :
156 134 : mpMostRecentlySelectedPage = rpDescriptor;
157 134 : if (mpSelectionAnchor == 0)
158 134 : mpSelectionAnchor = rpDescriptor;
159 :
160 134 : if (mnBroadcastDisableLevel > 0)
161 134 : mbSelectionChangeBroadcastPending = true;
162 : else
163 0 : mrController.GetSelectionManager()->SelectionHasChanged();
164 134 : UpdateCurrentPage();
165 :
166 134 : CheckConsistency();
167 : }
168 276 : }
169 :
170 142 : void PageSelector::DeselectPage (
171 : int nPageIndex,
172 : const bool bUpdateCurrentPage)
173 : {
174 142 : model::SharedPageDescriptor pDescriptor (mrModel.GetPageDescriptor(nPageIndex));
175 142 : if (pDescriptor.get() != NULL)
176 142 : DeselectPage(pDescriptor, bUpdateCurrentPage);
177 142 : }
178 :
179 142 : void PageSelector::DeselectPage (
180 : const SharedPageDescriptor& rpDescriptor,
181 : const bool bUpdateCurrentPage)
182 : {
183 284 : if (rpDescriptor.get()!=NULL
184 142 : && mrSlideSorter.GetView().SetState(rpDescriptor, PageDescriptor::ST_Selected, false))
185 : {
186 134 : --mnSelectedPageCount;
187 134 : mrSlideSorter.GetController().GetVisibleAreaManager().RequestVisible(rpDescriptor);
188 134 : mrSlideSorter.GetView().RequestRepaint(rpDescriptor);
189 134 : if (mpMostRecentlySelectedPage == rpDescriptor)
190 8 : mpMostRecentlySelectedPage.reset();
191 134 : if (mnBroadcastDisableLevel > 0)
192 134 : mbSelectionChangeBroadcastPending = true;
193 : else
194 0 : mrController.GetSelectionManager()->SelectionHasChanged();
195 134 : if (bUpdateCurrentPage)
196 134 : UpdateCurrentPage();
197 :
198 134 : CheckConsistency();
199 : }
200 142 : }
201 :
202 268 : void PageSelector::CheckConsistency (void) const
203 : {
204 268 : int nSelectionCount (0);
205 552 : for (int nPageIndex=0,nPageCount=mrModel.GetPageCount(); nPageIndex<nPageCount; nPageIndex++)
206 : {
207 284 : SharedPageDescriptor pDescriptor (mrModel.GetPageDescriptor(nPageIndex));
208 : assert(pDescriptor);
209 284 : if (pDescriptor->HasState(PageDescriptor::ST_Selected))
210 134 : ++nSelectionCount;
211 284 : }
212 268 : if (nSelectionCount!=mnSelectedPageCount)
213 : {
214 : // #i120020# The former call to assert(..) internally calls
215 : // SlideSorterModel::GetPageDescriptor which will crash in this situation
216 : // (only in non-pro code). All what is wanted there is to assert it (the
217 : // error is already detected), so do this directly.
218 : OSL_ENSURE(false, "PageSelector: Consistency error (!)");
219 : }
220 268 : }
221 :
222 0 : bool PageSelector::IsPageSelected (int nPageIndex)
223 : {
224 0 : SharedPageDescriptor pDescriptor (mrModel.GetPageDescriptor(nPageIndex));
225 0 : if (pDescriptor.get() != NULL)
226 0 : return pDescriptor->HasState(PageDescriptor::ST_Selected);
227 : else
228 0 : return false;
229 : }
230 :
231 528 : int PageSelector::GetPageCount (void) const
232 : {
233 528 : return mrModel.GetPageCount();
234 : }
235 :
236 252 : void PageSelector::CountSelectedPages (void)
237 : {
238 252 : mnSelectedPageCount = 0;
239 : model::PageEnumeration aSelectedPages (
240 252 : model::PageEnumerationProvider::CreateSelectedPagesEnumeration(mrModel));
241 630 : while (aSelectedPages.HasMoreElements())
242 : {
243 126 : mnSelectedPageCount++;
244 126 : aSelectedPages.GetNextElement();
245 252 : }
246 252 : }
247 :
248 134 : void PageSelector::EnableBroadcasting (void)
249 : {
250 134 : if (mnBroadcastDisableLevel > 0)
251 134 : mnBroadcastDisableLevel --;
252 134 : if (mnBroadcastDisableLevel==0 && mbSelectionChangeBroadcastPending)
253 : {
254 134 : mrController.GetSelectionManager()->SelectionHasChanged();
255 134 : mbSelectionChangeBroadcastPending = false;
256 : }
257 134 : }
258 :
259 134 : void PageSelector::DisableBroadcasting (void)
260 : {
261 134 : mnBroadcastDisableLevel ++;
262 134 : }
263 :
264 134 : ::boost::shared_ptr<PageSelector::PageSelection> PageSelector::GetPageSelection (void) const
265 : {
266 134 : ::boost::shared_ptr<PageSelection> pSelection (new PageSelection());
267 134 : pSelection->reserve(GetSelectedPageCount());
268 :
269 134 : int nPageCount = GetPageCount();
270 276 : for (int nIndex=0; nIndex<nPageCount; nIndex++)
271 : {
272 142 : SharedPageDescriptor pDescriptor (mrModel.GetPageDescriptor(nIndex));
273 142 : if (pDescriptor.get()!=NULL && pDescriptor->HasState(PageDescriptor::ST_Selected))
274 134 : pSelection->push_back(pDescriptor->GetPage());
275 142 : }
276 :
277 134 : return pSelection;
278 : }
279 :
280 134 : void PageSelector::SetPageSelection (
281 : const ::boost::shared_ptr<PageSelection>& rpSelection,
282 : const bool bUpdateCurrentPage)
283 : {
284 134 : PageSelection::const_iterator iPage;
285 268 : for (iPage=rpSelection->begin(); iPage!=rpSelection->end(); ++iPage)
286 134 : SelectPage(*iPage);
287 134 : if (bUpdateCurrentPage)
288 0 : UpdateCurrentPage();
289 134 : }
290 :
291 528 : void PageSelector::UpdateCurrentPage (const bool bUpdateOnlyWhenPending)
292 : {
293 528 : if (mnUpdateLockCount > 0)
294 : {
295 134 : mbIsUpdateCurrentPagePending = true;
296 268 : return;
297 : }
298 :
299 394 : if ( ! mbIsUpdateCurrentPagePending && bUpdateOnlyWhenPending)
300 0 : return;
301 :
302 394 : mbIsUpdateCurrentPagePending = false;
303 :
304 : // Make the first selected page the current page.
305 394 : SharedPageDescriptor pCurrentPageDescriptor;
306 394 : const sal_Int32 nPageCount (GetPageCount());
307 540 : for (sal_Int32 nIndex=0; nIndex<nPageCount; ++nIndex)
308 : {
309 280 : SharedPageDescriptor pDescriptor (mrModel.GetPageDescriptor(nIndex));
310 280 : if ( ! pDescriptor)
311 0 : continue;
312 280 : if (pDescriptor->HasState(PageDescriptor::ST_Selected))
313 : {
314 134 : pCurrentPageDescriptor = pDescriptor;
315 134 : break;
316 : }
317 146 : }
318 :
319 394 : if (pCurrentPageDescriptor)
320 : {
321 : // Switching the current slide normally sets also the
322 : // selection to just the new current slide. To prevent that,
323 : // we store (and at the end of this scope restore) the current
324 : // selection.
325 134 : ::boost::shared_ptr<PageSelection> pSelection (GetPageSelection());
326 :
327 134 : mrController.GetCurrentSlideManager()->SwitchCurrentSlide(pCurrentPageDescriptor);
328 :
329 : // Restore the selection and prevent a recursive call to
330 : // UpdateCurrentPage().
331 134 : SetPageSelection(pSelection, false);
332 394 : }
333 : }
334 :
335 : //===== PageSelector::UpdateLock ==============================================
336 :
337 0 : PageSelector::UpdateLock::UpdateLock (SlideSorter& rSlideSorter)
338 0 : : mpSelector(&rSlideSorter.GetController().GetPageSelector())
339 : {
340 0 : ++mpSelector->mnUpdateLockCount;
341 0 : }
342 :
343 260 : PageSelector::UpdateLock::UpdateLock (PageSelector& rSelector)
344 260 : : mpSelector(&rSelector)
345 : {
346 260 : ++mpSelector->mnUpdateLockCount;
347 260 : }
348 :
349 260 : PageSelector::UpdateLock::~UpdateLock (void)
350 : {
351 260 : Release();
352 260 : }
353 :
354 260 : void PageSelector::UpdateLock::Release (void)
355 : {
356 260 : if (mpSelector != NULL)
357 : {
358 260 : --mpSelector->mnUpdateLockCount;
359 : OSL_ASSERT(mpSelector->mnUpdateLockCount >= 0);
360 260 : if (mpSelector->mnUpdateLockCount == 0)
361 260 : mpSelector->UpdateCurrentPage(true);
362 :
363 260 : mpSelector = NULL;
364 : }
365 260 : }
366 :
367 : //===== PageSelector::BroadcastLock ==============================================
368 :
369 0 : PageSelector::BroadcastLock::BroadcastLock (SlideSorter& rSlideSorter)
370 0 : : mrSelector(rSlideSorter.GetController().GetPageSelector())
371 : {
372 0 : mrSelector.DisableBroadcasting();
373 0 : }
374 :
375 134 : PageSelector::BroadcastLock::BroadcastLock (PageSelector& rSelector)
376 134 : : mrSelector(rSelector)
377 : {
378 134 : mrSelector.DisableBroadcasting();
379 134 : }
380 :
381 134 : PageSelector::BroadcastLock::~BroadcastLock (void)
382 : {
383 134 : mrSelector.EnableBroadcasting();
384 134 : }
385 :
386 114 : } } } // end of namespace ::sd::slidesorter::controller
387 :
388 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|