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 <sal/config.h>
21 :
22 : #include <cstdlib>
23 :
24 : #include "controller/SlsVisibleAreaManager.hxx"
25 : #include "controller/SlideSorterController.hxx"
26 : #include "controller/SlsProperties.hxx"
27 : #include "controller/SlsAnimationFunction.hxx"
28 : #include "controller/SlsScrollBarManager.hxx"
29 : #include "controller/SlsCurrentSlideManager.hxx"
30 :
31 :
32 : namespace sd { namespace slidesorter { namespace controller {
33 :
34 : namespace {
35 0 : class VisibleAreaScroller
36 : {
37 : public:
38 : VisibleAreaScroller (
39 : SlideSorter& rSlideSorter,
40 : const Point aStart,
41 : const Point aEnd);
42 : void operator() (const double nValue);
43 : private:
44 : SlideSorter& mrSlideSorter;
45 : Point maStart;
46 : const Point maEnd;
47 : const ::boost::function<double(double)> maAccelerationFunction;
48 : };
49 :
50 : } // end of anonymous namespace
51 :
52 :
53 :
54 0 : VisibleAreaManager::VisibleAreaManager (SlideSorter& rSlideSorter)
55 : : mrSlideSorter(rSlideSorter),
56 : maVisibleRequests(),
57 : mnScrollAnimationId(Animator::NotAnAnimationId),
58 : maRequestedVisibleTopLeft(),
59 : meRequestedAnimationMode(Animator::AM_Immediate),
60 : mbIsCurrentSlideTrackingActive(true),
61 0 : mnDisableCount(0)
62 : {
63 0 : }
64 :
65 :
66 :
67 :
68 0 : VisibleAreaManager::~VisibleAreaManager (void)
69 : {
70 0 : }
71 :
72 :
73 :
74 :
75 0 : void VisibleAreaManager::ActivateCurrentSlideTracking (void)
76 : {
77 0 : mbIsCurrentSlideTrackingActive = true;
78 0 : }
79 :
80 :
81 :
82 :
83 0 : void VisibleAreaManager::DeactivateCurrentSlideTracking (void)
84 : {
85 0 : mbIsCurrentSlideTrackingActive = false;
86 0 : }
87 :
88 :
89 :
90 :
91 0 : bool VisibleAreaManager::IsCurrentSlideTrackingActive (void) const
92 : {
93 0 : return mbIsCurrentSlideTrackingActive;
94 : }
95 :
96 :
97 :
98 :
99 0 : void VisibleAreaManager::RequestVisible (
100 : const model::SharedPageDescriptor& rpDescriptor,
101 : const bool bForce)
102 : {
103 0 : if (rpDescriptor)
104 : {
105 0 : if (mnDisableCount == 0)
106 : {
107 : maVisibleRequests.push_back(
108 0 : mrSlideSorter.GetView().GetLayouter().GetPageObjectBox(
109 : rpDescriptor->GetPageIndex(),
110 0 : true));
111 : }
112 0 : if (bForce && ! mbIsCurrentSlideTrackingActive)
113 0 : ActivateCurrentSlideTracking();
114 0 : MakeVisible();
115 : }
116 0 : }
117 :
118 :
119 :
120 :
121 0 : void VisibleAreaManager::RequestCurrentSlideVisible (void)
122 : {
123 0 : if (mbIsCurrentSlideTrackingActive && mnDisableCount==0)
124 : RequestVisible(
125 0 : mrSlideSorter.GetController().GetCurrentSlideManager()->GetCurrentSlide());
126 0 : }
127 :
128 :
129 :
130 :
131 0 : void VisibleAreaManager::MakeVisible (void)
132 : {
133 0 : if (maVisibleRequests.empty())
134 0 : return;
135 :
136 0 : SharedSdWindow pWindow (mrSlideSorter.GetContentWindow());
137 0 : if ( ! pWindow)
138 0 : return;
139 0 : const Point aCurrentTopLeft (pWindow->PixelToLogic(Point(0,0)));
140 :
141 0 : const ::boost::optional<Point> aNewVisibleTopLeft (GetRequestedTopLeft());
142 0 : maVisibleRequests.clear();
143 0 : if ( ! aNewVisibleTopLeft)
144 0 : return;
145 :
146 : // We now know what the visible area shall be. Scroll accordingly
147 : // unless that is not already the visible area or a running scroll
148 : // animation has it as its target area.
149 0 : if (mnScrollAnimationId!=Animator::NotAnAnimationId
150 0 : && maRequestedVisibleTopLeft==aNewVisibleTopLeft)
151 0 : return;
152 :
153 : // Stop a running animation.
154 0 : if (mnScrollAnimationId != Animator::NotAnAnimationId)
155 0 : mrSlideSorter.GetController().GetAnimator()->RemoveAnimation(mnScrollAnimationId);
156 :
157 0 : maRequestedVisibleTopLeft = aNewVisibleTopLeft.get();
158 : VisibleAreaScroller aAnimation(
159 : mrSlideSorter,
160 : aCurrentTopLeft,
161 0 : maRequestedVisibleTopLeft);
162 0 : if (meRequestedAnimationMode==Animator::AM_Animated
163 0 : && mrSlideSorter.GetProperties()->IsSmoothSelectionScrolling())
164 : {
165 0 : mnScrollAnimationId = mrSlideSorter.GetController().GetAnimator()->AddAnimation(
166 : aAnimation,
167 : 0,
168 0 : 300);
169 : }
170 : else
171 : {
172 : // Execute the animation at its final value.
173 0 : aAnimation(1.0);
174 : }
175 0 : meRequestedAnimationMode = Animator::AM_Immediate;
176 : }
177 :
178 :
179 :
180 :
181 0 : ::boost::optional<Point> VisibleAreaManager::GetRequestedTopLeft (void) const
182 : {
183 0 : SharedSdWindow pWindow (mrSlideSorter.GetContentWindow());
184 0 : if ( ! pWindow)
185 0 : return ::boost::optional<Point>();
186 :
187 : // Get the currently visible area and the model area.
188 0 : const Rectangle aVisibleArea (pWindow->PixelToLogic(
189 : Rectangle(
190 : Point(0,0),
191 0 : pWindow->GetOutputSizePixel())));
192 0 : const Rectangle aModelArea (mrSlideSorter.GetView().GetModelArea());
193 :
194 0 : sal_Int32 nVisibleTop (aVisibleArea.Top());
195 0 : const sal_Int32 nVisibleWidth (aVisibleArea.GetWidth());
196 0 : sal_Int32 nVisibleLeft (aVisibleArea.Left());
197 0 : const sal_Int32 nVisibleHeight (aVisibleArea.GetHeight());
198 :
199 : // Find the longest run of boxes whose union fits into the visible area.
200 0 : for (::std::vector<Rectangle>::const_iterator
201 0 : iBox(maVisibleRequests.begin()),
202 0 : iEnd(maVisibleRequests.end());
203 : iBox!=iEnd;
204 : ++iBox)
205 : {
206 0 : if (nVisibleTop+nVisibleHeight <= iBox->Bottom())
207 0 : nVisibleTop = iBox->Bottom()-nVisibleHeight;
208 0 : if (nVisibleTop > iBox->Top())
209 0 : nVisibleTop = iBox->Top();
210 :
211 0 : if (nVisibleLeft+nVisibleWidth <= iBox->Right())
212 0 : nVisibleLeft = iBox->Right()-nVisibleWidth;
213 0 : if (nVisibleLeft > iBox->Left())
214 0 : nVisibleLeft = iBox->Left();
215 :
216 : // Make sure the visible area does not move outside the model area.
217 0 : if (nVisibleTop + nVisibleHeight > aModelArea.Bottom())
218 0 : nVisibleTop = aModelArea.Bottom() - nVisibleHeight;
219 0 : if (nVisibleTop < aModelArea.Top())
220 0 : nVisibleTop = aModelArea.Top();
221 :
222 0 : if (nVisibleLeft + nVisibleWidth > aModelArea.Right())
223 0 : nVisibleLeft = aModelArea.Right() - nVisibleWidth;
224 0 : if (nVisibleLeft < aModelArea.Left())
225 0 : nVisibleLeft = aModelArea.Left();
226 : }
227 :
228 0 : const Point aRequestedTopLeft (nVisibleLeft, nVisibleTop);
229 0 : if (aRequestedTopLeft == aVisibleArea.TopLeft())
230 0 : return ::boost::optional<Point>();
231 : else
232 0 : return ::boost::optional<Point>(aRequestedTopLeft);
233 : }
234 :
235 :
236 :
237 :
238 : //===== VisibleAreaManager::TemporaryDisabler =================================
239 :
240 0 : VisibleAreaManager::TemporaryDisabler::TemporaryDisabler (SlideSorter& rSlideSorter)
241 0 : : mrVisibleAreaManager(rSlideSorter.GetController().GetVisibleAreaManager())
242 : {
243 0 : ++mrVisibleAreaManager.mnDisableCount;
244 0 : }
245 :
246 :
247 :
248 :
249 0 : VisibleAreaManager::TemporaryDisabler::~TemporaryDisabler (void)
250 : {
251 0 : --mrVisibleAreaManager.mnDisableCount;
252 0 : }
253 :
254 :
255 :
256 : //===== VerticalVisibleAreaScroller ===========================================
257 :
258 : namespace {
259 :
260 : const static sal_Int32 gnMaxScrollDistance = 300;
261 :
262 0 : VisibleAreaScroller::VisibleAreaScroller (
263 : SlideSorter& rSlideSorter,
264 : const Point aStart,
265 : const Point aEnd)
266 : : mrSlideSorter(rSlideSorter),
267 : maStart(aStart),
268 : maEnd(aEnd),
269 : maAccelerationFunction(
270 : controller::AnimationParametricFunction(
271 0 : controller::AnimationBezierFunction (0.1,0.6)))
272 : {
273 : // When the distance to scroll is larger than a threshold then first
274 : // jump to within this distance of the final value and start the
275 : // animation from there.
276 0 : if (std::abs(aStart.X()-aEnd.X()) > gnMaxScrollDistance)
277 : {
278 0 : if (aStart.X() < aEnd.X())
279 0 : maStart.X() = aEnd.X()-gnMaxScrollDistance;
280 : else
281 0 : maStart.X() = aEnd.X()+gnMaxScrollDistance;
282 : }
283 0 : if (std::abs(aStart.Y()-aEnd.Y()) > gnMaxScrollDistance)
284 : {
285 0 : if (aStart.Y() < aEnd.Y())
286 0 : maStart.Y() = aEnd.Y()-gnMaxScrollDistance;
287 : else
288 0 : maStart.Y() = aEnd.Y()+gnMaxScrollDistance;
289 : }
290 0 : }
291 :
292 :
293 :
294 :
295 0 : void VisibleAreaScroller::operator() (const double nTime)
296 : {
297 0 : const double nLocalTime (maAccelerationFunction(nTime));
298 0 : mrSlideSorter.GetController().GetScrollBarManager().SetTopLeft(
299 : Point(
300 0 : sal_Int32(0.5 + maStart.X() * (1.0 - nLocalTime) + maEnd.X() * nLocalTime),
301 0 : sal_Int32 (0.5 + maStart.Y() * (1.0 - nLocalTime) + maEnd.Y() * nLocalTime)));
302 0 : }
303 :
304 : } // end of anonymous namespace
305 :
306 : } } } // end of namespace ::sd::slidesorter::controller
307 :
308 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|