Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*************************************************************************
3 : : *
4 : : * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 : : *
6 : : * Copyright 2000, 2010 Oracle and/or its affiliates.
7 : : *
8 : : * OpenOffice.org - a multi-platform office productivity suite
9 : : *
10 : : * This file is part of OpenOffice.org.
11 : : *
12 : : * OpenOffice.org is free software: you can redistribute it and/or modify
13 : : * it under the terms of the GNU Lesser General Public License version 3
14 : : * only, as published by the Free Software Foundation.
15 : : *
16 : : * OpenOffice.org is distributed in the hope that it will be useful,
17 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 : : * GNU Lesser General Public License version 3 for more details
20 : : * (a copy is included in the LICENSE file that accompanied this code).
21 : : *
22 : : * You should have received a copy of the GNU Lesser General Public License
23 : : * version 3 along with OpenOffice.org. If not, see
24 : : * <http://www.openoffice.org/license.html>
25 : : * for a copy of the LGPLv3 License.
26 : : *
27 : : ************************************************************************/
28 : :
29 : :
30 : : #include "view/SlsInsertAnimator.hxx"
31 : : #include "controller/SlideSorterController.hxx"
32 : : #include "controller/SlsAnimationFunction.hxx"
33 : : #include "view/SlideSorterView.hxx"
34 : : #include "view/SlsLayouter.hxx"
35 : : #include "model/SlideSorterModel.hxx"
36 : : #include "model/SlsPageEnumerationProvider.hxx"
37 : :
38 : : #include <set>
39 : : #include <boost/bind.hpp>
40 : : #include <boost/enable_shared_from_this.hpp>
41 : :
42 : : namespace sd { namespace slidesorter { namespace view {
43 : :
44 : : namespace {
45 : :
46 : : class PageObjectRun;
47 : :
48 : 0 : class AnimatorAccess
49 : : {
50 : : public:
51 : : virtual void AddRun (const ::boost::shared_ptr<PageObjectRun> pRun) = 0;
52 : : virtual void RemoveRun (const ::boost::shared_ptr<PageObjectRun> pRun) = 0;
53 : : virtual model::SlideSorterModel& GetModel (void) const = 0;
54 : : virtual view::SlideSorterView& GetView (void) const = 0;
55 : : virtual ::boost::shared_ptr<controller::Animator> GetAnimator (void) = 0;
56 : : virtual SharedSdWindow GetContentWindow (void) = 0;
57 : :
58 : : protected:
59 : 0 : ~AnimatorAccess() {}
60 : : };
61 : :
62 : :
63 : : /** Controller of the position offsets of all page objects in one row or one
64 : : column.
65 : : */
66 : : class PageObjectRun : public ::boost::enable_shared_from_this<PageObjectRun>
67 : : {
68 : : public:
69 : : PageObjectRun (
70 : : AnimatorAccess& rAnimatorAccess,
71 : : const sal_Int32 nRunIndex,
72 : : const sal_Int32 nStartIndex,
73 : : const sal_Int32 nEndIndex);
74 : : ~PageObjectRun (void);
75 : :
76 : : void operator () (const double nTime);
77 : :
78 : : void UpdateOffsets(
79 : : const InsertPosition& rInsertPosition,
80 : : const view::Layouter& GetLayouter);
81 : : void ResetOffsets (const controller::Animator::AnimationMode eMode);
82 : :
83 : : /// Index of the row or column that this run represents.
84 : : sal_Int32 mnRunIndex;
85 : : /// The index at which to make place for the insertion indicator (-1 for
86 : : /// no indicator).
87 : : sal_Int32 mnLocalInsertIndex;
88 : : /// Index of the first page in the run.
89 : : sal_Int32 mnStartIndex;
90 : : /// Index of the last page in the run.
91 : : sal_Int32 mnEndIndex;
92 : : /// Offset of each item in the run at the start of the current animation.
93 : : ::std::vector<Point> maStartOffset;
94 : : /// Target offset of each item in the run at the end of the current animation.
95 : : ::std::vector<Point> maEndOffset;
96 : : /// Time at which the current animation started.
97 : : double mnStartTime;
98 : :
99 : : class Comparator
100 : : {
101 : 0 : public: bool operator() (
102 : : const ::boost::shared_ptr<PageObjectRun>& rpRunA,
103 : : const ::boost::shared_ptr<PageObjectRun>& rpRunB) const
104 : : {
105 : 0 : return rpRunA->mnRunIndex < rpRunB->mnRunIndex;
106 : : }
107 : : };
108 : : private:
109 : : controller::Animator::AnimationId mnAnimationId;
110 : : AnimatorAccess& mrAnimatorAccess;
111 : : ::boost::function<double(double)> maAccelerationFunction;
112 : :
113 : : void RestartAnimation (void);
114 : : };
115 : : typedef ::boost::shared_ptr<PageObjectRun> SharedPageObjectRun;
116 : :
117 : :
118 : 0 : Point Blend (const Point& rPointA, const Point& rPointB, const double nT)
119 : : {
120 : : return Point(
121 : 0 : sal_Int32(rPointA.X() * (1-nT) + rPointB.X() * nT),
122 : 0 : sal_Int32(rPointA.Y() * (1-nT) + rPointB.Y() * nT));
123 : : }
124 : :
125 : : } // end of anonymous namespace
126 : :
127 : :
128 : :
129 : : class InsertAnimator::Implementation : public AnimatorAccess
130 : : {
131 : : public:
132 : : Implementation (SlideSorter& rSlideSorter);
133 : : virtual ~Implementation (void);
134 : :
135 : : void SetInsertPosition (
136 : : const InsertPosition& rInsertPosition,
137 : : const controller::Animator::AnimationMode eAnimationMode);
138 : :
139 : : virtual void AddRun (const ::boost::shared_ptr<PageObjectRun> pRun);
140 : : virtual void RemoveRun (const ::boost::shared_ptr<PageObjectRun> pRun);
141 : :
142 : 0 : virtual model::SlideSorterModel& GetModel (void) const { return mrModel; }
143 : 0 : virtual view::SlideSorterView& GetView (void) const { return mrView; }
144 : 0 : virtual ::boost::shared_ptr<controller::Animator> GetAnimator (void) { return mpAnimator; }
145 : 0 : virtual SharedSdWindow GetContentWindow (void) { return mrSlideSorter.GetContentWindow(); }
146 : :
147 : : private:
148 : : model::SlideSorterModel& mrModel;
149 : : view::SlideSorterView& mrView;
150 : : SlideSorter& mrSlideSorter;
151 : : ::boost::shared_ptr<controller::Animator> mpAnimator;
152 : : typedef ::std::set<SharedPageObjectRun, PageObjectRun::Comparator> RunContainer;
153 : : RunContainer maRuns;
154 : : InsertPosition maInsertPosition;
155 : :
156 : : void StopAnimation (void);
157 : : SharedPageObjectRun GetRun (
158 : : view::Layouter& rLayouter,
159 : : const InsertPosition& rInsertPosition,
160 : : const bool bCreate = true);
161 : : RunContainer::const_iterator FindRun (const sal_Int32 nRunIndex) const;
162 : : };
163 : :
164 : :
165 : :
166 : :
167 : :
168 : : //===== InsertAnimator ========================================================
169 : :
170 : 0 : InsertAnimator::InsertAnimator (SlideSorter& rSlideSorter)
171 [ # # ][ # # ]: 0 : : mpImplementation(new Implementation(rSlideSorter))
[ # # ]
172 : : {
173 : 0 : }
174 : :
175 : :
176 : :
177 : :
178 : 0 : void InsertAnimator::SetInsertPosition (const InsertPosition& rInsertPosition)
179 : : {
180 : 0 : mpImplementation->SetInsertPosition(rInsertPosition, controller::Animator::AM_Animated);
181 : 0 : }
182 : :
183 : :
184 : :
185 : :
186 : 0 : void InsertAnimator::Reset (const controller::Animator::AnimationMode eMode)
187 : : {
188 [ # # ]: 0 : mpImplementation->SetInsertPosition(InsertPosition(), eMode);
189 : 0 : }
190 : :
191 : :
192 : :
193 : :
194 : : //===== InsertAnimator::Implementation ========================================
195 : :
196 : 0 : InsertAnimator::Implementation::Implementation (SlideSorter& rSlideSorter)
197 [ # # ]: 0 : : mrModel(rSlideSorter.GetModel()),
198 [ # # ]: 0 : mrView(rSlideSorter.GetView()),
199 : : mrSlideSorter(rSlideSorter),
200 [ # # ]: 0 : mpAnimator(rSlideSorter.GetController().GetAnimator()),
201 : : maRuns(),
202 [ # # ][ # # ]: 0 : maInsertPosition()
[ # # ]
203 : : {
204 : 0 : }
205 : :
206 : :
207 : :
208 : :
209 [ # # ]: 0 : InsertAnimator::Implementation::~Implementation (void)
210 : : {
211 [ # # ][ # # ]: 0 : SetInsertPosition(InsertPosition(), controller::Animator::AM_Immediate);
212 [ # # ]: 0 : }
213 : :
214 : :
215 : :
216 : :
217 : 0 : void InsertAnimator::Implementation::SetInsertPosition (
218 : : const InsertPosition& rInsertPosition,
219 : : const controller::Animator::AnimationMode eMode)
220 : : {
221 [ # # ][ # # ]: 0 : if (maInsertPosition == rInsertPosition)
222 : 0 : return;
223 : :
224 [ # # ][ # # ]: 0 : SharedPageObjectRun pOldRun (GetRun(mrView.GetLayouter(), maInsertPosition));
225 [ # # ][ # # ]: 0 : SharedPageObjectRun pCurrentRun (GetRun(mrView.GetLayouter(), rInsertPosition));
226 [ # # ]: 0 : maInsertPosition = rInsertPosition;
227 : :
228 : : // When the new insert position is in a different run then move the page
229 : : // objects in the old run to their default positions.
230 [ # # ][ # # ]: 0 : if (pOldRun != pCurrentRun)
231 : : {
232 [ # # ]: 0 : if (pOldRun)
233 [ # # ]: 0 : pOldRun->ResetOffsets(eMode);
234 : : }
235 : :
236 [ # # ]: 0 : if (pCurrentRun)
237 : : {
238 [ # # ][ # # ]: 0 : pCurrentRun->UpdateOffsets(rInsertPosition, mrView.GetLayouter());
239 [ # # ][ # # ]: 0 : }
240 : : }
241 : :
242 : :
243 : :
244 : :
245 : 0 : SharedPageObjectRun InsertAnimator::Implementation::GetRun (
246 : : view::Layouter& rLayouter,
247 : : const InsertPosition& rInsertPosition,
248 : : const bool bCreate)
249 : : {
250 : 0 : const sal_Int32 nRow (rInsertPosition.GetRow());
251 [ # # ]: 0 : if (nRow < 0)
252 [ # # ]: 0 : return SharedPageObjectRun();
253 : :
254 : 0 : RunContainer::const_iterator iRun (maRuns.end());
255 [ # # ][ # # ]: 0 : if (rLayouter.GetColumnCount() == 1)
256 : : {
257 : : // There is only one run that contains all slides.
258 [ # # ][ # # ]: 0 : if (maRuns.empty() && bCreate)
[ # # ]
259 : : maRuns.insert(SharedPageObjectRun(new PageObjectRun(
260 : : *this,
261 : : 0,
262 : : 0,
263 [ # # ][ # # ]: 0 : mrModel.GetPageCount()-1)));
[ # # ][ # # ]
[ # # ][ # # ]
264 : 0 : iRun = maRuns.begin();
265 : : }
266 : : else
267 : : {
268 [ # # ]: 0 : iRun = FindRun(nRow);
269 [ # # ][ # # ]: 0 : if (iRun == maRuns.end() && bCreate)
[ # # ][ # # ]
270 : : {
271 : : // Create a new run.
272 [ # # ]: 0 : const sal_Int32 nStartIndex (rLayouter.GetIndex(nRow, 0));
273 [ # # ][ # # ]: 0 : const sal_Int32 nEndIndex (rLayouter.GetIndex(nRow, rLayouter.GetColumnCount()-1));
274 [ # # ]: 0 : if (nStartIndex <= nEndIndex)
275 : : {
276 : : iRun = maRuns.insert(SharedPageObjectRun(new PageObjectRun(
277 : : *this,
278 : : nRow,
279 : : nStartIndex,
280 [ # # ][ # # ]: 0 : nEndIndex))).first;
[ # # ][ # # ]
[ # # ]
281 : : OSL_ASSERT(iRun != maRuns.end());
282 : : }
283 : : }
284 : : }
285 : :
286 [ # # ]: 0 : if (iRun != maRuns.end())
287 [ # # ]: 0 : return *iRun;
288 : : else
289 [ # # ]: 0 : return SharedPageObjectRun();
290 : : }
291 : :
292 : :
293 : :
294 : :
295 : : InsertAnimator::Implementation::RunContainer::const_iterator
296 : 0 : InsertAnimator::Implementation::FindRun (const sal_Int32 nRunIndex) const
297 : : {
298 : : return std::find_if(
299 : : maRuns.begin(),
300 : : maRuns.end(),
301 : : ::boost::bind(
302 : : ::std::equal_to<sal_Int32>(),
303 : : ::boost::bind(&PageObjectRun::mnRunIndex, _1),
304 [ # # ][ # # ]: 0 : nRunIndex));
305 : : }
306 : :
307 : :
308 : :
309 : :
310 : 0 : void InsertAnimator::Implementation::AddRun (const ::boost::shared_ptr<PageObjectRun> pRun)
311 : : {
312 [ # # ]: 0 : if (pRun)
313 : : {
314 : 0 : maRuns.insert(pRun);
315 : : }
316 : : else
317 : : {
318 : : OSL_ASSERT(pRun);
319 : : }
320 : 0 : }
321 : :
322 : :
323 : :
324 : :
325 : :
326 : 0 : void InsertAnimator::Implementation::RemoveRun (const ::boost::shared_ptr<PageObjectRun> pRun)
327 : : {
328 [ # # ]: 0 : if (pRun)
329 : : {
330 : : // Do not remove runs that show the space for the insertion indicator.
331 [ # # ]: 0 : if (pRun->mnLocalInsertIndex == -1)
332 : : {
333 [ # # ]: 0 : InsertAnimator::Implementation::RunContainer::const_iterator iRun (FindRun(pRun->mnRunIndex));
334 [ # # ]: 0 : if (iRun != maRuns.end())
335 : : {
336 : : OSL_ASSERT(*iRun == pRun);
337 [ # # ]: 0 : maRuns.erase(iRun);
338 : : }
339 : : }
340 : : }
341 : : else
342 : : {
343 : : OSL_ASSERT(pRun);
344 : : }
345 : 0 : }
346 : :
347 : :
348 : :
349 : :
350 : :
351 : : //===== PageObjectRun =========================================================
352 : :
353 : 0 : PageObjectRun::PageObjectRun (
354 : : AnimatorAccess& rAnimatorAccess,
355 : : const sal_Int32 nRunIndex,
356 : : const sal_Int32 nStartIndex,
357 : : const sal_Int32 nEndIndex)
358 : : : mnRunIndex(nRunIndex),
359 : : mnLocalInsertIndex(-1),
360 : : mnStartIndex(nStartIndex),
361 : : mnEndIndex(nEndIndex),
362 : : maStartOffset(),
363 : : maEndOffset(),
364 : : mnStartTime(-1),
365 : : mnAnimationId(controller::Animator::NotAnAnimationId),
366 : : mrAnimatorAccess(rAnimatorAccess),
367 : : maAccelerationFunction(
368 : : controller::AnimationParametricFunction(
369 [ # # ][ # # ]: 0 : controller::AnimationBezierFunction (0.1,0.7)))
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
370 : : {
371 [ # # ]: 0 : maStartOffset.resize(nEndIndex - nStartIndex + 1);
372 [ # # ]: 0 : maEndOffset.resize(nEndIndex - nStartIndex + 1);
373 : 0 : }
374 : :
375 : :
376 : :
377 : :
378 [ # # ]: 0 : PageObjectRun::~PageObjectRun (void)
379 : : {
380 : 0 : }
381 : :
382 : 0 : void PageObjectRun::UpdateOffsets(
383 : : const InsertPosition& rInsertPosition,
384 : : const view::Layouter& rLayouter)
385 : : {
386 : 0 : const bool bIsVertical (rLayouter.GetColumnCount()==1);
387 : : const sal_Int32 nLocalInsertIndex(bIsVertical
388 : : ? rInsertPosition.GetRow()
389 [ # # ]: 0 : : rInsertPosition.GetColumn());
390 [ # # ]: 0 : if (nLocalInsertIndex != mnLocalInsertIndex)
391 : : {
392 : 0 : mnLocalInsertIndex = nLocalInsertIndex;
393 : :
394 : 0 : model::SlideSorterModel& rModel (mrAnimatorAccess.GetModel());
395 : 0 : const sal_Int32 nRunLength (mnEndIndex - mnStartIndex + 1);
396 [ # # ]: 0 : for (sal_Int32 nIndex=0; nIndex<nRunLength; ++nIndex)
397 : : {
398 [ # # ]: 0 : model::SharedPageDescriptor pDescriptor(rModel.GetPageDescriptor(nIndex+mnStartIndex));
399 [ # # ]: 0 : if (pDescriptor)
400 [ # # ][ # # ]: 0 : maStartOffset[nIndex] = pDescriptor->GetVisualState().GetLocationOffset();
401 : 0 : maEndOffset[nIndex] = nIndex < mnLocalInsertIndex
402 : : ? rInsertPosition.GetLeadingOffset()
403 [ # # ]: 0 : : rInsertPosition.GetTrailingOffset();
404 [ # # ]: 0 : if (bIsVertical)
405 : 0 : maEndOffset[nIndex].X() = 0;
406 : : else
407 : 0 : maEndOffset[nIndex].Y() = 0;
408 [ # # ]: 0 : }
409 : 0 : RestartAnimation();
410 : : }
411 : 0 : }
412 : :
413 : :
414 : :
415 : :
416 : 0 : void PageObjectRun::ResetOffsets (const controller::Animator::AnimationMode eMode)
417 : : {
418 : 0 : mnLocalInsertIndex = -1;
419 : 0 : const sal_Int32 nRunLength (mnEndIndex - mnStartIndex + 1);
420 : 0 : model::SlideSorterModel& rModel (mrAnimatorAccess.GetModel());
421 : 0 : view::SlideSorterView& rView (mrAnimatorAccess.GetView());
422 [ # # ]: 0 : for (sal_Int32 nIndex=0; nIndex<nRunLength; ++nIndex)
423 : : {
424 [ # # ]: 0 : model::SharedPageDescriptor pDescriptor(rModel.GetPageDescriptor(nIndex+mnStartIndex));
425 [ # # ]: 0 : if (pDescriptor)
426 : : {
427 [ # # ]: 0 : if (eMode == controller::Animator::AM_Animated)
428 [ # # ][ # # ]: 0 : maStartOffset[nIndex] = pDescriptor->GetVisualState().GetLocationOffset();
429 : : else
430 : : {
431 [ # # ]: 0 : const Rectangle aOldBoundingBox (pDescriptor->GetBoundingBox());
432 [ # # ][ # # ]: 0 : pDescriptor->GetVisualState().SetLocationOffset(Point(0,0));
433 [ # # ]: 0 : rView.RequestRepaint(aOldBoundingBox);
434 [ # # ]: 0 : rView.RequestRepaint(pDescriptor);
435 : : }
436 : : }
437 : 0 : maEndOffset[nIndex] = Point(0,0);
438 [ # # ]: 0 : }
439 [ # # ]: 0 : if (eMode == controller::Animator::AM_Animated)
440 : 0 : RestartAnimation();
441 : : else
442 [ # # ]: 0 : mrAnimatorAccess.RemoveRun(shared_from_this());
443 : 0 : }
444 : :
445 : :
446 : :
447 : :
448 : 0 : void PageObjectRun::RestartAnimation (void)
449 : : {
450 : : // Stop the current animation.
451 [ # # ]: 0 : if (mnAnimationId != controller::Animator::NotAnAnimationId)
452 : : {
453 [ # # ]: 0 : mrAnimatorAccess.GetAnimator()->RemoveAnimation(mnAnimationId);
454 : : }
455 : :
456 : : // Restart the animation.
457 [ # # ]: 0 : mrAnimatorAccess.AddRun(shared_from_this());
458 : 0 : mnAnimationId = mrAnimatorAccess.GetAnimator()->AddAnimation(
459 : : ::boost::ref(*this),
460 : : 0,
461 : : 300,
462 : : ::boost::bind(
463 : : &AnimatorAccess::RemoveRun,
464 : : ::boost::ref(mrAnimatorAccess),
465 [ # # ][ # # ]: 0 : shared_from_this()));
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
466 : 0 : }
467 : :
468 : :
469 : :
470 : :
471 : 0 : void PageObjectRun::operator () (const double nGlobalTime)
472 : : {
473 [ # # ]: 0 : if (mnStartTime < 0)
474 : 0 : mnStartTime = nGlobalTime;
475 : :
476 : 0 : double nLocalTime (nGlobalTime - mnStartTime);
477 [ # # ]: 0 : if (nLocalTime > 1.0)
478 : 0 : nLocalTime = 1.0;
479 : 0 : nLocalTime = maAccelerationFunction(nLocalTime);
480 : :
481 : 0 : model::SlideSorterModel& rModel (mrAnimatorAccess.GetModel());
482 : 0 : view::SlideSorterView& rView (mrAnimatorAccess.GetView());
483 [ # # ]: 0 : for (sal_Int32 nIndex=mnStartIndex; nIndex<=mnEndIndex; ++nIndex)
484 : : {
485 [ # # ]: 0 : model::SharedPageDescriptor pDescriptor (rModel.GetPageDescriptor(nIndex));
486 [ # # ]: 0 : if ( ! pDescriptor)
487 : 0 : continue;
488 [ # # ]: 0 : const Rectangle aOldBoundingBox (pDescriptor->GetBoundingBox());
489 [ # # ]: 0 : pDescriptor->GetVisualState().SetLocationOffset(
490 : : Blend(
491 : 0 : maStartOffset[nIndex-mnStartIndex],
492 : 0 : maEndOffset[nIndex-mnStartIndex],
493 [ # # ]: 0 : nLocalTime));
494 : :
495 : : // Request a repaint of the old and new bounding box (which largely overlap.)
496 [ # # ]: 0 : rView.RequestRepaint(aOldBoundingBox);
497 [ # # ][ # # ]: 0 : rView.RequestRepaint(pDescriptor);
498 [ # # ]: 0 : }
499 : :
500 : : // Call Flush to make
501 : : // a) animations a bit more smooth and
502 : : // b) on Mac without the Flush a Reset of the page locations is not properly
503 : : // visualized when the mouse leaves the window during drag-and-drop.
504 [ # # ]: 0 : mrAnimatorAccess.GetContentWindow()->Flush();
505 : 0 : }
506 : :
507 : :
508 : :
509 : :
510 [ + - ][ + - ]: 75 : } } } // end of namespace ::sd::slidesorter::view
511 : :
512 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|