1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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/SlsPageSelector.hxx>
22 #include <SlideSorter.hxx>
23 #include <controller/SlideSorterController.hxx>
24 #include <controller/SlsSelectionManager.hxx>
25 #include <controller/SlsCurrentSlideManager.hxx>
26 #include <controller/SlsVisibleAreaManager.hxx>
27 #include <model/SlsPageDescriptor.hxx>
28 #include <model/SlsPageEnumerationProvider.hxx>
29 #include <model/SlideSorterModel.hxx>
30 #include <view/SlideSorterView.hxx>
31 #include <osl/diagnose.h>
34 #include <tools/debug.hxx>
37 using namespace ::com::sun::star
;
38 using namespace ::sd::slidesorter::model
;
39 using namespace ::sd::slidesorter::view
;
41 namespace sd::slidesorter::controller
{
43 PageSelector::PageSelector (SlideSorter
& rSlideSorter
)
44 : mrModel(rSlideSorter
.GetModel()),
45 mrSlideSorter(rSlideSorter
),
46 mrController(mrSlideSorter
.GetController()),
47 mnSelectedPageCount(0),
48 mnBroadcastDisableLevel(0),
49 mbSelectionChangeBroadcastPending(false),
51 mbIsUpdateCurrentPagePending(true)
53 CountSelectedPages ();
56 void PageSelector::SelectAllPages()
58 VisibleAreaManager::TemporaryDisabler
aDisabler (mrSlideSorter
);
59 PageSelector::UpdateLock
aLock (*this);
61 int nPageCount
= mrModel
.GetPageCount();
62 for (int nPageIndex
=0; nPageIndex
<nPageCount
; nPageIndex
++)
63 SelectPage(nPageIndex
);
66 void PageSelector::DeselectAllPages()
68 VisibleAreaManager::TemporaryDisabler
aDisabler (mrSlideSorter
);
69 PageSelector::UpdateLock
aLock (*this);
71 int nPageCount
= mrModel
.GetPageCount();
72 for (int nPageIndex
=0; nPageIndex
<nPageCount
; nPageIndex
++)
73 DeselectPage(nPageIndex
);
75 DBG_ASSERT (mnSelectedPageCount
==0,
76 "PageSelector::DeselectAllPages: the selected pages counter is not 0");
77 mnSelectedPageCount
= 0;
78 mpSelectionAnchor
.reset();
81 void PageSelector::GetCoreSelection()
83 PageSelector::UpdateLock
aLock (*this);
85 bool bSelectionHasChanged (true);
86 mnSelectedPageCount
= 0;
87 model::PageEnumeration
aAllPages (
88 model::PageEnumerationProvider::CreateAllPagesEnumeration(mrModel
));
89 while (aAllPages
.HasMoreElements())
91 model::SharedPageDescriptor
pDescriptor (aAllPages
.GetNextElement());
92 if (pDescriptor
->GetCoreSelection())
94 mrSlideSorter
.GetController().GetVisibleAreaManager().RequestVisible(pDescriptor
);
95 mrSlideSorter
.GetView().RequestRepaint(pDescriptor
);
96 bSelectionHasChanged
= true;
99 if (pDescriptor
->HasState(PageDescriptor::ST_Selected
))
100 mnSelectedPageCount
++;
103 if (bSelectionHasChanged
)
105 if (mnBroadcastDisableLevel
> 0)
106 mbSelectionChangeBroadcastPending
= true;
108 mrController
.GetSelectionManager()->SelectionHasChanged();
112 void PageSelector::SetCoreSelection()
114 model::PageEnumeration
aAllPages (
115 model::PageEnumerationProvider::CreateAllPagesEnumeration(mrModel
));
116 while (aAllPages
.HasMoreElements())
118 model::SharedPageDescriptor
pDescriptor (aAllPages
.GetNextElement());
119 pDescriptor
->SetCoreSelection();
123 void PageSelector::SelectPage (int nPageIndex
)
125 SharedPageDescriptor
pDescriptor (mrModel
.GetPageDescriptor(nPageIndex
));
127 SelectPage(pDescriptor
);
130 void PageSelector::SelectPage (const SdPage
* pPage
)
132 const sal_Int32
nPageIndex (mrModel
.GetIndex(pPage
));
133 SharedPageDescriptor
pDescriptor (mrModel
.GetPageDescriptor(nPageIndex
));
134 if (pDescriptor
&& pDescriptor
->GetPage()==pPage
)
135 SelectPage(pDescriptor
);
138 void PageSelector::SelectPage (const SharedPageDescriptor
& rpDescriptor
)
141 || !mrSlideSorter
.GetView().SetState(rpDescriptor
, PageDescriptor::ST_Selected
, true))
144 ++mnSelectedPageCount
;
145 mrSlideSorter
.GetController().GetVisibleAreaManager().RequestVisible(rpDescriptor
,true);
146 mrSlideSorter
.GetView().RequestRepaint(rpDescriptor
);
148 mpMostRecentlySelectedPage
= rpDescriptor
;
149 if (mpSelectionAnchor
== nullptr)
150 mpSelectionAnchor
= rpDescriptor
;
152 if (mnBroadcastDisableLevel
> 0)
153 mbSelectionChangeBroadcastPending
= true;
155 mrController
.GetSelectionManager()->SelectionHasChanged();
161 void PageSelector::DeselectPage (int nPageIndex
)
163 model::SharedPageDescriptor
pDescriptor (mrModel
.GetPageDescriptor(nPageIndex
));
165 DeselectPage(pDescriptor
);
168 void PageSelector::DeselectPage (
169 const SharedPageDescriptor
& rpDescriptor
,
170 const bool bUpdateCurrentPage
)
173 || !mrSlideSorter
.GetView().SetState(rpDescriptor
, PageDescriptor::ST_Selected
, false))
176 --mnSelectedPageCount
;
177 mrSlideSorter
.GetController().GetVisibleAreaManager().RequestVisible(rpDescriptor
);
178 mrSlideSorter
.GetView().RequestRepaint(rpDescriptor
);
179 if (mpMostRecentlySelectedPage
== rpDescriptor
)
180 mpMostRecentlySelectedPage
.reset();
181 if (mnBroadcastDisableLevel
> 0)
182 mbSelectionChangeBroadcastPending
= true;
184 mrController
.GetSelectionManager()->SelectionHasChanged();
185 if (bUpdateCurrentPage
)
191 void PageSelector::CheckConsistency() const
193 int nSelectionCount (0);
194 for (int nPageIndex
=0,nPageCount
=mrModel
.GetPageCount(); nPageIndex
<nPageCount
; nPageIndex
++)
196 SharedPageDescriptor
pDescriptor (mrModel
.GetPageDescriptor(nPageIndex
));
198 if (pDescriptor
->HasState(PageDescriptor::ST_Selected
))
201 if (nSelectionCount
!=mnSelectedPageCount
)
203 // #i120020# The former call to assert(..) internally calls
204 // SlideSorterModel::GetPageDescriptor which will crash in this situation
205 // (only in non-pro code). All what is wanted there is to assert it (the
206 // error is already detected), so do this directly.
207 OSL_ENSURE(false, "PageSelector: Consistency error (!)");
211 bool PageSelector::IsPageSelected(int nPageIndex
)
213 SharedPageDescriptor
pDescriptor (mrModel
.GetPageDescriptor(nPageIndex
));
215 return pDescriptor
->HasState(PageDescriptor::ST_Selected
);
220 bool PageSelector::IsPageExcluded(int nPageIndex
)
222 SharedPageDescriptor
pDescriptor(mrModel
.GetPageDescriptor(nPageIndex
));
224 return pDescriptor
->HasState(PageDescriptor::ST_Excluded
);
229 int PageSelector::GetPageCount() const
231 return mrModel
.GetPageCount();
234 void PageSelector::CountSelectedPages()
236 mnSelectedPageCount
= 0;
237 model::PageEnumeration
aSelectedPages (
238 model::PageEnumerationProvider::CreateSelectedPagesEnumeration(mrModel
));
239 while (aSelectedPages
.HasMoreElements())
241 mnSelectedPageCount
++;
242 aSelectedPages
.GetNextElement();
246 void PageSelector::EnableBroadcasting()
248 if (mnBroadcastDisableLevel
> 0)
249 mnBroadcastDisableLevel
--;
250 if (mnBroadcastDisableLevel
==0 && mbSelectionChangeBroadcastPending
)
252 mrController
.GetSelectionManager()->SelectionHasChanged();
253 mbSelectionChangeBroadcastPending
= false;
257 void PageSelector::DisableBroadcasting()
259 mnBroadcastDisableLevel
++;
262 std::shared_ptr
<PageSelector::PageSelection
> PageSelector::GetPageSelection() const
264 auto pSelection
= std::make_shared
<PageSelection
>();
265 pSelection
->reserve(GetSelectedPageCount());
267 int nPageCount
= GetPageCount();
268 for (int nIndex
=0; nIndex
<nPageCount
; nIndex
++)
270 SharedPageDescriptor
pDescriptor (mrModel
.GetPageDescriptor(nIndex
));
271 if (pDescriptor
&& pDescriptor
->HasState(PageDescriptor::ST_Selected
))
272 pSelection
->push_back(pDescriptor
->GetPage());
278 void PageSelector::SetPageSelection (
279 const std::shared_ptr
<PageSelection
>& rpSelection
,
280 const bool bUpdateCurrentPage
)
282 for (const auto& rpPage
: *rpSelection
)
284 if (bUpdateCurrentPage
)
288 void PageSelector::UpdateCurrentPage (const bool bUpdateOnlyWhenPending
)
290 if (mnUpdateLockCount
> 0)
292 mbIsUpdateCurrentPagePending
= true;
296 if ( ! mbIsUpdateCurrentPagePending
&& bUpdateOnlyWhenPending
)
299 mbIsUpdateCurrentPagePending
= false;
301 // Make the first selected page the current page.
302 SharedPageDescriptor pCurrentPageDescriptor
;
303 const sal_Int32
nPageCount (GetPageCount());
304 for (sal_Int32 nIndex
=0; nIndex
<nPageCount
; ++nIndex
)
306 SharedPageDescriptor
pDescriptor (mrModel
.GetPageDescriptor(nIndex
));
309 if (pDescriptor
->HasState(PageDescriptor::ST_Selected
))
311 pCurrentPageDescriptor
= std::move(pDescriptor
);
316 if (!pCurrentPageDescriptor
)
319 // Switching the current slide normally sets also the
320 // selection to just the new current slide. To prevent that,
321 // we store (and at the end of this scope restore) the current
323 std::shared_ptr
<PageSelection
> pSelection (GetPageSelection());
325 mrController
.GetCurrentSlideManager()->SwitchCurrentSlide(pCurrentPageDescriptor
);
327 // Restore the selection and prevent a recursive call to
328 // UpdateCurrentPage().
329 SetPageSelection(pSelection
, false);
332 //===== PageSelector::UpdateLock ==============================================
334 PageSelector::UpdateLock::UpdateLock (SlideSorter
const & rSlideSorter
)
335 : mpSelector(&rSlideSorter
.GetController().GetPageSelector())
337 ++mpSelector
->mnUpdateLockCount
;
340 PageSelector::UpdateLock::UpdateLock (PageSelector
& rSelector
)
341 : mpSelector(&rSelector
)
343 ++mpSelector
->mnUpdateLockCount
;
346 PageSelector::UpdateLock::~UpdateLock()
351 void PageSelector::UpdateLock::Release()
353 if (mpSelector
!= nullptr)
355 --mpSelector
->mnUpdateLockCount
;
356 OSL_ASSERT(mpSelector
->mnUpdateLockCount
>= 0);
357 if (mpSelector
->mnUpdateLockCount
== 0)
358 mpSelector
->UpdateCurrentPage(true);
360 mpSelector
= nullptr;
364 //===== PageSelector::BroadcastLock ==============================================
366 PageSelector::BroadcastLock::BroadcastLock (SlideSorter
const & rSlideSorter
)
367 : mrSelector(rSlideSorter
.GetController().GetPageSelector())
369 mrSelector
.DisableBroadcasting();
372 PageSelector::BroadcastLock::BroadcastLock (PageSelector
& rSelector
)
373 : mrSelector(rSelector
)
375 mrSelector
.DisableBroadcasting();
378 PageSelector::BroadcastLock::~BroadcastLock()
380 mrSelector
.EnableBroadcasting();
383 } // end of namespace ::sd::slidesorter::controller
385 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */