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 "view/SlsInsertAnimator.hxx"
21 #include "controller/SlideSorterController.hxx"
22 #include "controller/SlsAnimationFunction.hxx"
23 #include "view/SlideSorterView.hxx"
24 #include "view/SlsLayouter.hxx"
25 #include "model/SlideSorterModel.hxx"
26 #include "model/SlsPageEnumerationProvider.hxx"
29 #include <boost/bind.hpp>
30 #include <boost/enable_shared_from_this.hpp>
32 namespace sd
{ namespace slidesorter
{ namespace view
{
41 virtual void AddRun (const ::boost::shared_ptr
<PageObjectRun
>& rRun
) = 0;
42 virtual void RemoveRun (const ::boost::shared_ptr
<PageObjectRun
>& rRun
) = 0;
43 virtual model::SlideSorterModel
& GetModel (void) const = 0;
44 virtual view::SlideSorterView
& GetView (void) const = 0;
45 virtual ::boost::shared_ptr
<controller::Animator
> GetAnimator (void) = 0;
46 virtual VclPtr
<sd::Window
> GetContentWindow (void) = 0;
52 /** Controller of the position offsets of all page objects in one row or one
55 class PageObjectRun
: public ::boost::enable_shared_from_this
<PageObjectRun
>
59 AnimatorAccess
& rAnimatorAccess
,
60 const sal_Int32 nRunIndex
,
61 const sal_Int32 nStartIndex
,
62 const sal_Int32 nEndIndex
);
65 void operator () (const double nTime
);
68 const InsertPosition
& rInsertPosition
,
69 const view::Layouter
& GetLayouter
);
70 void ResetOffsets (const controller::Animator::AnimationMode eMode
);
72 /// Index of the row or column that this run represents.
74 /// The index at which to make place for the insertion indicator (-1 for
76 sal_Int32 mnLocalInsertIndex
;
77 /// Index of the first page in the run.
78 sal_Int32 mnStartIndex
;
79 /// Index of the last page in the run.
81 /// Offset of each item in the run at the start of the current animation.
82 ::std::vector
<Point
> maStartOffset
;
83 /// Target offset of each item in the run at the end of the current animation.
84 ::std::vector
<Point
> maEndOffset
;
85 /// Time at which the current animation started.
90 public: bool operator() (
91 const ::boost::shared_ptr
<PageObjectRun
>& rpRunA
,
92 const ::boost::shared_ptr
<PageObjectRun
>& rpRunB
) const
94 return rpRunA
->mnRunIndex
< rpRunB
->mnRunIndex
;
98 controller::Animator::AnimationId mnAnimationId
;
99 AnimatorAccess
& mrAnimatorAccess
;
100 ::boost::function
<double(double)> maAccelerationFunction
;
102 void RestartAnimation();
104 typedef ::boost::shared_ptr
<PageObjectRun
> SharedPageObjectRun
;
106 Point
Blend (const Point
& rPointA
, const Point
& rPointB
, const double nT
)
109 sal_Int32(rPointA
.X() * (1-nT
) + rPointB
.X() * nT
),
110 sal_Int32(rPointA
.Y() * (1-nT
) + rPointB
.Y() * nT
));
113 } // end of anonymous namespace
115 class InsertAnimator::Implementation
: public AnimatorAccess
118 Implementation (SlideSorter
& rSlideSorter
);
119 virtual ~Implementation();
121 void SetInsertPosition (
122 const InsertPosition
& rInsertPosition
,
123 const controller::Animator::AnimationMode eAnimationMode
);
125 virtual void AddRun (const ::boost::shared_ptr
<PageObjectRun
>& rRun
) SAL_OVERRIDE
;
126 virtual void RemoveRun (const ::boost::shared_ptr
<PageObjectRun
>& rRun
) SAL_OVERRIDE
;
128 virtual model::SlideSorterModel
& GetModel() const SAL_OVERRIDE
{ return mrModel
; }
129 virtual view::SlideSorterView
& GetView() const SAL_OVERRIDE
{ return mrView
; }
130 virtual ::boost::shared_ptr
<controller::Animator
> GetAnimator() SAL_OVERRIDE
{ return mpAnimator
; }
131 virtual VclPtr
<sd::Window
> GetContentWindow() SAL_OVERRIDE
{ return mrSlideSorter
.GetContentWindow(); }
134 model::SlideSorterModel
& mrModel
;
135 view::SlideSorterView
& mrView
;
136 SlideSorter
& mrSlideSorter
;
137 ::boost::shared_ptr
<controller::Animator
> mpAnimator
;
138 typedef ::std::set
<SharedPageObjectRun
, PageObjectRun::Comparator
> RunContainer
;
140 InsertPosition maInsertPosition
;
142 SharedPageObjectRun
GetRun (
143 view::Layouter
& rLayouter
,
144 const InsertPosition
& rInsertPosition
,
145 const bool bCreate
= true);
146 RunContainer::const_iterator
FindRun (const sal_Int32 nRunIndex
) const;
149 //===== InsertAnimator ========================================================
151 InsertAnimator::InsertAnimator (SlideSorter
& rSlideSorter
)
152 : mpImplementation(new Implementation(rSlideSorter
))
156 void InsertAnimator::SetInsertPosition (const InsertPosition
& rInsertPosition
)
158 mpImplementation
->SetInsertPosition(rInsertPosition
, controller::Animator::AM_Animated
);
161 void InsertAnimator::Reset (const controller::Animator::AnimationMode eMode
)
163 mpImplementation
->SetInsertPosition(InsertPosition(), eMode
);
166 //===== InsertAnimator::Implementation ========================================
168 InsertAnimator::Implementation::Implementation (SlideSorter
& rSlideSorter
)
169 : mrModel(rSlideSorter
.GetModel()),
170 mrView(rSlideSorter
.GetView()),
171 mrSlideSorter(rSlideSorter
),
172 mpAnimator(rSlideSorter
.GetController().GetAnimator()),
178 InsertAnimator::Implementation::~Implementation()
180 SetInsertPosition(InsertPosition(), controller::Animator::AM_Immediate
);
183 void InsertAnimator::Implementation::SetInsertPosition (
184 const InsertPosition
& rInsertPosition
,
185 const controller::Animator::AnimationMode eMode
)
187 if (maInsertPosition
== rInsertPosition
)
190 SharedPageObjectRun
pOldRun (GetRun(mrView
.GetLayouter(), maInsertPosition
));
191 SharedPageObjectRun
pCurrentRun (GetRun(mrView
.GetLayouter(), rInsertPosition
));
192 maInsertPosition
= rInsertPosition
;
194 // When the new insert position is in a different run then move the page
195 // objects in the old run to their default positions.
196 if (pOldRun
!= pCurrentRun
)
199 pOldRun
->ResetOffsets(eMode
);
204 pCurrentRun
->UpdateOffsets(rInsertPosition
, mrView
.GetLayouter());
208 SharedPageObjectRun
InsertAnimator::Implementation::GetRun (
209 view::Layouter
& rLayouter
,
210 const InsertPosition
& rInsertPosition
,
213 const sal_Int32
nRow (rInsertPosition
.GetRow());
215 return SharedPageObjectRun();
217 RunContainer::const_iterator
iRun (maRuns
.end());
218 if (rLayouter
.GetColumnCount() == 1)
220 // There is only one run that contains all slides.
221 if (maRuns
.empty() && bCreate
)
222 maRuns
.insert(SharedPageObjectRun(new PageObjectRun(
226 mrModel
.GetPageCount()-1)));
227 iRun
= maRuns
.begin();
231 iRun
= FindRun(nRow
);
232 if (iRun
== maRuns
.end() && bCreate
)
235 const sal_Int32
nStartIndex (rLayouter
.GetIndex(nRow
, 0));
236 const sal_Int32
nEndIndex (rLayouter
.GetIndex(nRow
, rLayouter
.GetColumnCount()-1));
237 if (nStartIndex
<= nEndIndex
)
239 iRun
= maRuns
.insert(SharedPageObjectRun(new PageObjectRun(
244 OSL_ASSERT(iRun
!= maRuns
.end());
249 if (iRun
!= maRuns
.end())
252 return SharedPageObjectRun();
255 InsertAnimator::Implementation::RunContainer::const_iterator
256 InsertAnimator::Implementation::FindRun (const sal_Int32 nRunIndex
) const
262 ::std::equal_to
<sal_Int32
>(),
263 ::boost::bind(&PageObjectRun::mnRunIndex
, _1
),
267 void InsertAnimator::Implementation::AddRun (const ::boost::shared_ptr
<PageObjectRun
>& rRun
)
279 void InsertAnimator::Implementation::RemoveRun (const ::boost::shared_ptr
<PageObjectRun
>& rRun
)
283 // Do not remove runs that show the space for the insertion indicator.
284 if (rRun
->mnLocalInsertIndex
== -1)
286 InsertAnimator::Implementation::RunContainer::const_iterator
iRun (FindRun(rRun
->mnRunIndex
));
287 if (iRun
!= maRuns
.end())
289 OSL_ASSERT(*iRun
== rRun
);
300 //===== PageObjectRun =========================================================
302 PageObjectRun::PageObjectRun (
303 AnimatorAccess
& rAnimatorAccess
,
304 const sal_Int32 nRunIndex
,
305 const sal_Int32 nStartIndex
,
306 const sal_Int32 nEndIndex
)
307 : mnRunIndex(nRunIndex
),
308 mnLocalInsertIndex(-1),
309 mnStartIndex(nStartIndex
),
310 mnEndIndex(nEndIndex
),
314 mnAnimationId(controller::Animator::NotAnAnimationId
),
315 mrAnimatorAccess(rAnimatorAccess
),
316 maAccelerationFunction(
317 controller::AnimationParametricFunction(
318 controller::AnimationBezierFunction (0.1,0.7)))
320 maStartOffset
.resize(nEndIndex
- nStartIndex
+ 1);
321 maEndOffset
.resize(nEndIndex
- nStartIndex
+ 1);
324 PageObjectRun::~PageObjectRun()
328 void PageObjectRun::UpdateOffsets(
329 const InsertPosition
& rInsertPosition
,
330 const view::Layouter
& rLayouter
)
332 const bool bIsVertical (rLayouter
.GetColumnCount()==1);
333 const sal_Int32
nLocalInsertIndex(bIsVertical
334 ? rInsertPosition
.GetRow()
335 : rInsertPosition
.GetColumn());
336 if (nLocalInsertIndex
!= mnLocalInsertIndex
)
338 mnLocalInsertIndex
= nLocalInsertIndex
;
340 model::SlideSorterModel
& rModel (mrAnimatorAccess
.GetModel());
341 const sal_Int32
nRunLength (mnEndIndex
- mnStartIndex
+ 1);
342 for (sal_Int32 nIndex
=0; nIndex
<nRunLength
; ++nIndex
)
344 model::SharedPageDescriptor
pDescriptor(rModel
.GetPageDescriptor(nIndex
+mnStartIndex
));
346 maStartOffset
[nIndex
] = pDescriptor
->GetVisualState().GetLocationOffset();
347 maEndOffset
[nIndex
] = nIndex
< mnLocalInsertIndex
348 ? rInsertPosition
.GetLeadingOffset()
349 : rInsertPosition
.GetTrailingOffset();
351 maEndOffset
[nIndex
].X() = 0;
353 maEndOffset
[nIndex
].Y() = 0;
359 void PageObjectRun::ResetOffsets (const controller::Animator::AnimationMode eMode
)
361 mnLocalInsertIndex
= -1;
362 const sal_Int32
nRunLength (mnEndIndex
- mnStartIndex
+ 1);
363 model::SlideSorterModel
& rModel (mrAnimatorAccess
.GetModel());
364 view::SlideSorterView
& rView (mrAnimatorAccess
.GetView());
365 for (sal_Int32 nIndex
=0; nIndex
<nRunLength
; ++nIndex
)
367 model::SharedPageDescriptor
pDescriptor(rModel
.GetPageDescriptor(nIndex
+mnStartIndex
));
370 if (eMode
== controller::Animator::AM_Animated
)
371 maStartOffset
[nIndex
] = pDescriptor
->GetVisualState().GetLocationOffset();
374 const Rectangle
aOldBoundingBox (pDescriptor
->GetBoundingBox());
375 pDescriptor
->GetVisualState().SetLocationOffset(Point(0,0));
376 rView
.RequestRepaint(aOldBoundingBox
);
377 rView
.RequestRepaint(pDescriptor
);
380 maEndOffset
[nIndex
] = Point(0,0);
382 if (eMode
== controller::Animator::AM_Animated
)
385 mrAnimatorAccess
.RemoveRun(shared_from_this());
388 void PageObjectRun::RestartAnimation()
390 // Stop the current animation.
391 if (mnAnimationId
!= controller::Animator::NotAnAnimationId
)
393 mrAnimatorAccess
.GetAnimator()->RemoveAnimation(mnAnimationId
);
396 // Restart the animation.
397 mrAnimatorAccess
.AddRun(shared_from_this());
398 mnAnimationId
= mrAnimatorAccess
.GetAnimator()->AddAnimation(
403 &AnimatorAccess::RemoveRun
,
404 ::boost::ref(mrAnimatorAccess
),
405 shared_from_this()));
408 void PageObjectRun::operator () (const double nGlobalTime
)
411 mnStartTime
= nGlobalTime
;
413 double nLocalTime (nGlobalTime
- mnStartTime
);
414 if (nLocalTime
> 1.0)
416 nLocalTime
= maAccelerationFunction(nLocalTime
);
418 model::SlideSorterModel
& rModel (mrAnimatorAccess
.GetModel());
419 view::SlideSorterView
& rView (mrAnimatorAccess
.GetView());
420 for (sal_Int32 nIndex
=mnStartIndex
; nIndex
<=mnEndIndex
; ++nIndex
)
422 model::SharedPageDescriptor
pDescriptor (rModel
.GetPageDescriptor(nIndex
));
425 const Rectangle
aOldBoundingBox (pDescriptor
->GetBoundingBox());
426 pDescriptor
->GetVisualState().SetLocationOffset(
428 maStartOffset
[nIndex
-mnStartIndex
],
429 maEndOffset
[nIndex
-mnStartIndex
],
432 // Request a repaint of the old and new bounding box (which largely overlap.)
433 rView
.RequestRepaint(aOldBoundingBox
);
434 rView
.RequestRepaint(pDescriptor
);
437 // Call Flush to make
438 // a) animations a bit more smooth and
439 // b) on Mac without the Flush a Reset of the page locations is not properly
440 // visualized when the mouse leaves the window during drag-and-drop.
441 mrAnimatorAccess
.GetContentWindow()->Flush();
444 } } } // end of namespace ::sd::slidesorter::view
446 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */