LibreOffice Module slideshow (master) 1
effectrewinder.cxx
Go to the documentation of this file.
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
21#include "effectrewinder.hxx"
22#include <eventqueue.hxx>
23#include <usereventqueue.hxx>
24#include <basecontainernode.hxx>
25#include <delayevent.hxx>
26
27#include <com/sun/star/animations/Event.hpp>
28#include <com/sun/star/animations/EventTrigger.hpp>
29#include <com/sun/star/container/XEnumerationAccess.hpp>
30#include <com/sun/star/beans/XPropertySet.hpp>
31#include <utility>
32
33using ::com::sun::star::uno::Reference;
34using namespace ::com::sun::star;
35
36namespace slideshow::internal {
37
38
39namespace {
40
41class RewinderEventHandler : public EventHandler
42{
43public:
44 typedef ::std::function<bool ()> Action;
45 explicit RewinderEventHandler (Action aAction) : maAction(std::move(aAction)) {}
46
47private:
49 virtual bool handleEvent() override { return maAction(); }
50};
51
52
53class RewinderAnimationEventHandler : public AnimationEventHandler
54{
55public:
56 typedef ::std::function<bool (const AnimationNodeSharedPtr& rpNode)> Action;
57 explicit RewinderAnimationEventHandler (Action aAction) : maAction(std::move(aAction)) {}
58
59private:
60 const Action maAction;
61 virtual bool handleAnimationEvent (const AnimationNodeSharedPtr& rpNode) override
62 { return maAction(rpNode); }
63};
64
65
66} // end of anonymous namespace
67
68
69//----- EffectRewinder --------------------------------------------------------------
70
72 EventMultiplexer& rEventMultiplexer,
73 EventQueue& rEventQueue,
74 UserEventQueue& rUserEventQueue)
75 : mrEventMultiplexer(rEventMultiplexer),
76 mrEventQueue(rEventQueue),
77 mrUserEventQueue(rUserEventQueue),
78 mpSlideStartHandler(),
79 mpSlideEndHandler(),
80 mpAnimationStartHandler(),
81 mnMainSequenceEffectCount(0),
82 mpAsynchronousRewindEvent(),
83 mxCurrentAnimationRootNode(),
84 mxCurrentSlide(),
85 mbNonUserTriggeredMainSequenceEffectSeen(false),
86 mbHasAdvancedTimeSetting(false)
87{
88 initialize();
89}
90
91
93{
94 // Add some event handlers so that we are informed when
95 // a) an animation is started (we then check whether that belongs to a
96 // main sequence effect and if so, increase the respective counter),
97 // b,c) a slide was started or ended (in which case the effect counter
98 // is reset.
99
101 std::make_shared<RewinderAnimationEventHandler>(
102 [this]( const AnimationNodeSharedPtr& pNode)
103 { return this->notifyAnimationStart( pNode ); } );
105
107 std::make_shared<RewinderEventHandler>(
108 [this]() { return this->resetEffectCount(); } );
110
112 std::make_shared<RewinderEventHandler>(
113 [this]() { return this->resetEffectCount(); } );
115}
116
117
119{
120 dispose();
121}
122
123
125{
127 {
128 mpAsynchronousRewindEvent->dispose();
130 }
131
133 {
136 }
137
139 {
141 mpSlideStartHandler.reset();
142 }
143
145 {
147 mpSlideEndHandler.reset();
148 }
149}
150
151
154{
155 mxCurrentAnimationRootNode = xRootNode;
156}
157
160{
161 mxCurrentSlide = xSlide;
162
163 // Check if the current slide has advance time setting or not
164 uno::Reference< beans::XPropertySet > xPropSet( mxCurrentSlide, uno::UNO_QUERY );
165 sal_Int32 nChange(0);
166
167 if( xPropSet.is())
168 getPropertyValue( nChange, xPropSet, "Change");
169
170 mbHasAdvancedTimeSetting = nChange;
171}
172
174 const ::std::shared_ptr<ScreenUpdater::UpdateLock>& rpPaintLock,
175 const ::std::function<void ()>& rSlideRewindFunctor,
176 const ::std::function<void ()>& rPreviousSlideFunctor)
177{
178 mpPaintLock = rpPaintLock;
179
180 // Do not allow nested rewinds.
182 {
183 OSL_ASSERT( ! mpAsynchronousRewindEvent);
184 return false;
185 }
186
187 // Abort (and skip over the rest of) any currently active animation.
189
192
193 const int nSkipCount (mnMainSequenceEffectCount - 1);
194 if (nSkipCount < 0)
195 {
196 if ( ! rPreviousSlideFunctor)
197 {
198 OSL_ASSERT(rPreviousSlideFunctor);
199 return false;
200 }
201
202 // No main sequence effects to rewind on the current slide.
203 // Go back to the previous slide.
205 ::std::bind(
207 this,
208 rPreviousSlideFunctor),
209 "EffectRewinder::asynchronousRewindToPreviousSlide");
210 }
211 else
212 {
213 // The actual rewinding is done asynchronously so that we can safely
214 // call other methods.
216 ::std::bind(
218 this,
219 nSkipCount,
220 true,
221 rSlideRewindFunctor),
222 "EffectRewinder::asynchronousRewind");
223 }
224
227
228 return bool(mpAsynchronousRewindEvent);
229}
230
231
233{
234 // Do not allow nested rewinds.
236 {
237 OSL_ASSERT(!mpAsynchronousRewindEvent);
238 return;
239 }
240
241 const int nTotalMainSequenceEffectCount (countMainSequenceEffects());
243 ::std::bind(
245 this,
246 nTotalMainSequenceEffectCount,
247 false,
248 ::std::function<void ()>()),
249 "EffectRewinder::asynchronousRewind");
251}
252
253
255{
256 // Determine the number of main sequence effects.
257 sal_Int32 nMainSequenceNodeCount (0);
258
259 ::std::queue<uno::Reference<animations::XAnimationNode> > aNodeQueue;
260 aNodeQueue.push(mxCurrentAnimationRootNode);
261 while ( ! aNodeQueue.empty())
262 {
263 const uno::Reference<animations::XAnimationNode> xNode (aNodeQueue.front());
264 aNodeQueue.pop();
265
266 // Does the current node belong to the main sequence?
267 if (xNode.is())
268 {
269 animations::Event aEvent;
270 if (xNode->getBegin() >>= aEvent)
271 if (aEvent.Trigger == animations::EventTrigger::ON_NEXT)
272 ++nMainSequenceNodeCount;
273 }
274
275 // If the current node is a container then prepare its children for investigation.
276 uno::Reference<container::XEnumerationAccess> xEnumerationAccess (xNode, uno::UNO_QUERY);
277 if (xEnumerationAccess.is())
278 {
280 xEnumerationAccess->createEnumeration());
281 if (xEnumeration.is())
282 while (xEnumeration->hasMoreElements())
283 {
284 aNodeQueue.push(
286 xEnumeration->nextElement(), uno::UNO_QUERY));
287 }
288 }
289 }
290
291 return nMainSequenceNodeCount;
292}
293
294
296{
297 // This basically just starts the next effect and then skips over its
298 // animation.
303}
304
305
307{
309 return false;
310}
311
312
314{
315 // This notification is only relevant for us when the rpNode belongs to
316 // the main sequence.
317 BaseNodeSharedPtr pBaseNode (::std::dynamic_pointer_cast<BaseNode>(rpNode));
318 if ( ! pBaseNode)
319 return false;
320
321 BaseContainerNodeSharedPtr pParent (pBaseNode->getParentNode());
322 if ( ! (pParent && pParent->isMainSequenceRootNode()))
323 return false;
324
325 // This notification is only relevant for us when the effect is user
326 // triggered.
327 bool bIsUserTriggered (false);
328
329 Reference<animations::XAnimationNode> xNode (rpNode->getXAnimationNode());
330 if (xNode.is())
331 {
332 animations::Event aEvent;
333 if (xNode->getBegin() >>= aEvent)
334 bIsUserTriggered = (aEvent.Trigger == animations::EventTrigger::ON_NEXT);
335 }
336
337 if (bIsUserTriggered)
339 else
341
342 return false;
343}
344
345
347 sal_Int32 nEffectCount,
348 const bool bRedisplayCurrentSlide,
349 const std::function<void ()>& rSlideRewindFunctor)
350{
351 OSL_ASSERT(mpAsynchronousRewindEvent);
352
353 if (bRedisplayCurrentSlide)
354 {
355 mpPaintLock->Activate();
356 // Re-display the current slide.
357 if (rSlideRewindFunctor)
358 rSlideRewindFunctor();
360 ::std::bind(
362 this,
363 nEffectCount,
364 false,
365 rSlideRewindFunctor),
366 "EffectRewinder::asynchronousRewind");
368 }
369 else
370 {
371 // Process initial events and skip any animations that are started
372 // when the slide is shown.
374
377
379 {
382 }
383
384 while (--nEffectCount >= 0)
386
388 mpPaintLock.reset();
389 }
390}
391
392
394 const ::std::function<void ()>& rSlideRewindFunctor)
395{
396 OSL_ASSERT(mpAsynchronousRewindEvent);
397
399 rSlideRewindFunctor();
400}
401
402
403} // end of namespace ::slideshow::internal
404
405/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
AnyEventRef aEvent
void asynchronousRewindToPreviousSlide(const ::std::function< void()> &rPreviousSlideFunctor)
Go to the previous slide and replay all of its main sequence effects (or effect groups).
EventHandlerSharedPtr mpSlideEndHandler
sal_Int32 countMainSequenceEffects()
Count the number of effects (or effect groups) in the main effect sequence.
void skipSingleMainSequenceEffects()
Skip the next main sequence effect.
css::uno::Reference< css::animations::XAnimationNode > mxCurrentAnimationRootNode
void asynchronousRewind(sal_Int32 nEffectCount, const bool bRedisplayCurrentSlide, const ::std::function< void()> &rSlideRewindFunctor)
Rewind the last effect of the main effect sequence by replaying all previous effects.
void setRootAnimationNode(const css::uno::Reference< css::animations::XAnimationNode > &xRootNode)
Store the root node of the animation tree.
sal_Int32 mnMainSequenceEffectCount
The number off main sequence effects so far.
css::uno::Reference< css::drawing::XDrawPage > mxCurrentSlide
bool notifyAnimationStart(const AnimationNodeSharedPtr &rpNode)
Called by listeners when an animation (not necessarily of a main sequence effect) starts.
void dispose()
Call Dispose() before the owner of an EffectRewinder object dies so that the EffectRewinder can relea...
void skipAllMainSequenceEffects()
Call this method after gotoPreviousEffect() triggered a slide change to the previous slide.
EffectRewinder(EventMultiplexer &rEventMultiplexer, EventQueue &rEventQueue, UserEventQueue &rUserEventQueue)
AnimationEventHandlerSharedPtr mpAnimationStartHandler
void setCurrentSlide(const css::uno::Reference< css::drawing::XDrawPage > &xSlide)
Store the XDrawPage to reach specific slide properties.
EventHandlerSharedPtr mpSlideStartHandler
EventSharedPtr mpAsynchronousRewindEvent
This is the currently scheduled event that executes the asynchronous part of the effect rewinding.
bool rewind(const ::std::shared_ptr< ScreenUpdater::UpdateLock > &rpPaintLock, const ::std::function< void()> &rSlideRewindFunctor, const ::std::function< void()> &rPreviousSlideFunctor)
Rewind one effect of the main effect sequence.
::std::shared_ptr< ScreenUpdater::UpdateLock > mpPaintLock
This class multiplexes user-activated and slide-show global events.
void addAnimationStartHandler(const AnimationEventHandlerSharedPtr &rHandler)
Register an event handler that will be called when an XAnimationNode starts its active duration.
void removeSlideEndHandler(const EventHandlerSharedPtr &rHandler)
void addSlideEndHandler(const EventHandlerSharedPtr &rHandler)
Register an event handler that will be called when the slide is about to vanish.
void addSlideStartHandler(const EventHandlerSharedPtr &rHandler)
Register an event handler that will be called when the slide is just shown.
bool notifyNextEffect()
Notify that the user requested the next effect.
void removeSlideStartHandler(const EventHandlerSharedPtr &rHandler)
void removeAnimationStartHandler(const AnimationEventHandlerSharedPtr &rHandler)
This class handles events in a presentation.
Definition: eventqueue.hxx:41
void forceEmpty()
Forces an empty queue, firing all events immediately without minding any times.
Definition: eventqueue.cxx:142
bool addEvent(const EventSharedPtr &event)
Add the given event to the queue.
Definition: eventqueue.cxx:79
This class schedules user-activated events.
void callSkipEffectEventHandler()
Typically skipping the current effect is triggered by mouse clicks or key presses that trigger the ne...
#define makeEvent(f, d)
Definition: delayevent.hxx:131
const Action maAction
::std::shared_ptr< BaseContainerNode > BaseContainerNodeSharedPtr
bool getPropertyValue(ValueType &rValue, css::uno::Reference< css::beans::XPropertySet > const &xPropSet, OUString const &propName)
Definition: tools.hxx:278
::std::shared_ptr< AnimationNode > AnimationNodeSharedPtr
::std::shared_ptr< BaseNode > BaseNodeSharedPtr
Definition: basenode.hxx:74
EventMultiplexer & mrEventMultiplexer
Definition: slideview.cxx:728
EventQueue & mrEventQueue
Definition: slideview.cxx:729