LibreOffice Module slideshow (master) 1
basecontainernode.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 <basecontainernode.hxx>
22#include <com/sun/star/animations/AnimationRestart.hpp>
23#include <com/sun/star/animations/AnimationFill.hpp>
24#include <eventqueue.hxx>
25#include "nodetools.hxx"
26#include <delayevent.hxx>
27#include <o3tl/safeint.hxx>
28#include <sal/log.hxx>
29
30#include <functional>
31#include <algorithm>
32
33using namespace com::sun::star;
34
35namespace slideshow::internal {
36namespace {
37bool isRepeatIndefinite(const uno::Reference<animations::XAnimationNode>& xNode)
38{
39 return xNode->getRepeatCount().hasValue() && isIndefiniteTiming(xNode->getRepeatCount());
40}
41
42bool isRestart(const uno::Reference<animations::XAnimationNode>& xNode)
43{
44 sal_Int16 nRestart = xNode->getRestart();
45 return nRestart == animations::AnimationRestart::WHEN_NOT_ACTIVE ||
46 nRestart == animations::AnimationRestart::ALWAYS;
47}
48}
49
52 const BaseContainerNodeSharedPtr& rParent,
53 const NodeContext& rContext )
54 : BaseNode( xNode, rParent, rContext ),
55 maChildren(),
56 mnFinishedChildren(0),
57 mnLeftIterations(0),
58 mbRepeatIndefinite(isRepeatIndefinite(xNode)),
59 mbRestart(isRestart(xNode)),
60 mbDurationIndefinite( isIndefiniteTiming( xNode->getEnd() ) &&
61 isIndefiniteTiming( xNode->getDuration() ) )
62{
63}
64
66{
67 forEachChildNode( std::mem_fn(&Disposable::dispose), -1 );
68 maChildren.clear();
70}
71
73{
74 if( !(getXAnimationNode()->getRepeatCount() >>= mnLeftIterations) )
75 mnLeftIterations = 1.0;
76 return init_children();
77}
78
80{
82
83 // initialize all children
84 return (o3tl::make_unsigned(std::count_if(
85 maChildren.begin(), maChildren.end(),
86 std::mem_fn(&AnimationNode::init) )) ==
87 maChildren.size());
88}
89
91{
92 mnLeftIterations = 0; // in order to make skip effect work correctly
93 if (eDestState == FROZEN) {
94 // deactivate all children that are not FROZEN or ENDED:
96 ~(FROZEN | ENDED) );
97 }
98 else {
99 // end all children that are not ENDED:
100 forEachChildNode( std::mem_fn(&AnimationNode::end), ~ENDED );
101 }
102}
103
105{
106 // does any of our children returns "true" on
107 // AnimationNode::hasPendingAnimation()?
108 // If yes, we, too, return true
109 return std::any_of(
110 maChildren.begin(), maChildren.end(),
112}
113
115{
116 if (! checkValidNode())
117 return;
118
119 // register derived classes as end listeners at all children.
120 // this is necessary to control the children animation
121 // sequence, and to determine our own end event
122 if (pNode->registerDeactivatingListener( getSelf() )) {
123 maChildren.push_back( pNode );
124 }
125}
126
128{
129 // find given notifier in child vector
130 VectorOfNodes::const_iterator const iEnd( maChildren.end() );
131 VectorOfNodes::const_iterator const iFind(
132 std::find( maChildren.begin(), iEnd, pNode ) );
133 return (iFind != iEnd);
134}
135
137 AnimationNodeSharedPtr const& pChildNode )
138{
139 OSL_ASSERT( pChildNode->getState() == FROZEN ||
140 pChildNode->getState() == ENDED );
141 // early exit on invalid nodes
142 OSL_ASSERT( getState() != INVALID );
143 if( getState() == INVALID )
144 return false;
145
146 if (! isChildNode(pChildNode)) {
147 OSL_FAIL( "unknown notifier!" );
148 return false;
149 }
150
151 std::size_t const nSize = maChildren.size();
152 OSL_ASSERT( mnFinishedChildren < nSize );
154 bool bFinished = (mnFinishedChildren >= nSize);
155
156 // Handle repetition here.
157 if (bFinished) {
159 {
160 mnLeftIterations -= 1.0;
161 }
162 if(mnLeftIterations >= 1.0 || mbRestart)
163 {
164 // SMIL spec said that "Accumulate" controls whether or not the animation
165 // is cumulative, but XTimeContainer do not have this attribute, so always
166 // remove the effect before next repeat.
168
169 if (mnLeftIterations >= 1.0)
170 bFinished = false;
171
172 EventSharedPtr aRepetitionEvent =
173 makeDelay( [this] () { this->repeat(); },
174 0.0,
175 "BaseContainerNode::repeat");
176 getContext().mrEventQueue.addEvent( aRepetitionEvent );
177 }
178 else if (isDurationIndefinite())
179 {
180 if (getFillMode() == animations::AnimationFill::REMOVE)
182 deactivate();
183 }
184 }
185
186 return bFinished;
187}
188
190{
191 // Prevent repeat event scheduled before deactivation.
192 if (getState() == FROZEN || getState() == ENDED)
193 return;
194
195 forEachChildNode( std::mem_fn(&AnimationNode::end), ~ENDED );
196 bool bState = init_children();
197 if( bState )
198 activate_st();
199}
200
201#if defined(DBG_UTIL)
203{
204 for(const auto & i : maChildren)
205 {
206 BaseNodeSharedPtr pNode =
207 std::dynamic_pointer_cast<BaseNode>(i);
208 SAL_INFO("slideshow.verbose",
209 "Node connection: n" <<
210 debugGetNodeName(this) <<
211 " -> n" <<
212 debugGetNodeName(pNode.get()));
213 pNode->showState();
214 }
215
217}
218#endif
219
220} // namespace slideshow::internal
221
222/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
std::vector< Reference< XAnimationNode > > maChildren
virtual void end()=0
End the animation on this node.
virtual bool hasPendingAnimation() const =0
Query node whether it has an animation pending.
NodeState
The current state of this AnimationNode.
@ FROZEN
Node is frozen (no longer active, but changes remain in place)
@ INVALID
Invalid state, node is disposed or otherwise invalid.
@ ENDED
Node has completed an active lifecycle, and any effect is removed from the document.
virtual void deactivate()=0
Immediately stop this node.
virtual bool init()=0
Init this node.
virtual void removeEffect()=0
Called by the container to remove the animation effect to make the painted shape correct if it restar...
bool notifyDeactivatedChild(AnimationNodeSharedPtr const &pChildNode)
virtual void activate_st() override=0
bool isChildNode(AnimationNodeSharedPtr const &pNode) const
void appendChildNode(AnimationNodeSharedPtr const &pNode)
Add given child node to this container.
void forEachChildNode(FuncT func, int nodeStateMask) const
virtual void deactivate_st(NodeState eDestState) override
virtual void showState() const override
virtual bool hasPendingAnimation() const override
Query node whether it has an animation pending.
BaseContainerNode(css::uno::Reference< css::animations::XAnimationNode > const &xNode, BaseContainerNodeSharedPtr const &pParent, NodeContext const &rContext)
virtual void dispose() override
Dispose all object references.
This interface extends AnimationNode with some file-private accessor methods.
Definition: basenode.hxx:83
virtual void showState() const
Definition: basenode.cxx:688
virtual css::uno::Reference< css::animations::XAnimationNode > getXAnimationNode() const override
Query the corresponding XAnimationNode.
Definition: basenode.cxx:408
SlideShowContext const & getContext() const
Definition: basenode.hxx:135
sal_Int16 getFillMode()
Get the node's fill mode.
Definition: basenode.cxx:363
::std::shared_ptr< BaseNode > const & getSelf() const
Definition: basenode.hxx:136
virtual void dispose() override
Dispose all object references.
Definition: basenode.cxx:339
virtual NodeState getState() const override
Query node state.
Definition: basenode.cxx:655
virtual void deactivate() override
Immediately stop this node.
Definition: basenode.cxx:564
virtual void dispose()=0
Dispose all object references.
bool addEvent(const EventSharedPtr &event)
Add the given event to the queue.
Definition: eventqueue.cxx:79
#define makeDelay(f, t, d)
Definition: delayevent.hxx:128
#define SAL_INFO(area, stream)
int i
constexpr std::enable_if_t< std::is_signed_v< T >, std::make_unsigned_t< T > > make_unsigned(T value)
::std::shared_ptr< BaseContainerNode > BaseContainerNodeSharedPtr
bool isIndefiniteTiming(const uno::Any &rAny)
Definition: nodetools.cxx:72
::std::shared_ptr< AnimationNode > AnimationNodeSharedPtr
::std::shared_ptr< Event > EventSharedPtr
Definition: event.hxx:76
::std::shared_ptr< BaseNode > BaseNodeSharedPtr
Definition: basenode.hxx:74
OUString debugGetNodeName(const BaseNode *pNode)
Definition: nodetools.cxx:33
Context for every node.
Definition: basenode.hxx:45