1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_sd.hxx"
26 #include <com/sun/star/animations/XAnimationNode.hpp>
27 #include <com/sun/star/animations/Event.hpp>
28 #ifndef _COM_SUN_STAR_ANIMATIONS_XAnimateColor_HPP_
29 #include <com/sun/star/animations/XAnimateColor.hpp>
30 #endif
31 #ifndef _COM_SUN_STAR_ANIMATIONS_XAnimateSet_HPP_
32 #include <com/sun/star/animations/XAnimateSet.hpp>
33 #endif
34 #include <com/sun/star/animations/XCommand.hpp>
35 #ifndef _COM_SUN_STAR_ANIMATIONS_XAnimateMotion_HPP_
36 #include <com/sun/star/animations/XAnimateMotion.hpp>
37 #endif
38 #ifndef _COM_SUN_STAR_ANIMATIONS_XAnimateTransform_HPP_
39 #include <com/sun/star/animations/XAnimateTransform.hpp>
40 #endif
41 #ifndef _COM_SUN_STAR_ANIMATIONS_XTransitionFilter_HPP_
42 #include <com/sun/star/animations/XTransitionFilter.hpp>
43 #endif
44 #include <com/sun/star/animations/XIterateContainer.hpp>
45 #include <com/sun/star/animations/XAudio.hpp>
46 #include <com/sun/star/animations/AnimationNodeType.hpp>
47 #include <com/sun/star/animations/ValuePair.hpp>
48 #include <com/sun/star/presentation/EffectNodeType.hpp>
49 #include <com/sun/star/util/XCloneable.hpp>
50 #include <com/sun/star/presentation/ParagraphTarget.hpp>
51 #include <com/sun/star/container/XEnumerationAccess.hpp>
52 #include <com/sun/star/beans/NamedValue.hpp>
53 
54 #include <map>
55 
56 #include "comphelper/anytostring.hxx"
57 #include "cppuhelper/exc_hlp.hxx"
58 #include "rtl/ref.hxx"
59 #include <animations/animationnodehelper.hxx>
60 
61 // header for class SdrObjListIter
62 #include <svx/svditer.hxx>
63 
64 #include "sdpage.hxx"
65 
66 using namespace ::com::sun::star::uno;
67 using namespace ::com::sun::star::animations;
68 using namespace ::com::sun::star::presentation;
69 using namespace ::com::sun::star::container;
70 
71 using ::rtl::OUString;
72 using ::rtl::OString;
73 using ::com::sun::star::drawing::XShape;
74 using ::com::sun::star::beans::NamedValue;
75 
76 namespace sd
77 {
78     class CustomAnimationClonerImpl
79     {
80 	public:
81         CustomAnimationClonerImpl();
82 		Reference< XAnimationNode > Clone( const Reference< XAnimationNode >& xSourceNode, const SdPage* pSource = 0, const SdPage* pTarget = 0 );
83 
84     private:
85 		void transformNode( const Reference< XAnimationNode >& xNode );
86 		Any transformValue( const Any& rValue );
87 
88         Reference< XShape > getClonedShape( const Reference< XShape >& xSource ) const;
89         Reference< XAnimationNode > getClonedNode( const Reference< XAnimationNode >& xSource ) const;
90 
91         mutable ::std::map< Reference< XShape >, Reference< XShape > > maShapeMap;
92 		std::vector< Reference< XAnimationNode > > maSourceNodeVector;
93 		std::vector< Reference< XAnimationNode > > maCloneNodeVector;
94     };
95 
CustomAnimationClonerImpl()96 	CustomAnimationClonerImpl::CustomAnimationClonerImpl()
97 	{
98 	}
99 
Clone(const Reference<XAnimationNode> & xSourceNode,const SdPage * pSource,const SdPage * pTarget)100 	Reference< XAnimationNode > Clone( const Reference< XAnimationNode >& xSourceNode, const SdPage* pSource, const SdPage* pTarget )
101 	{
102 		CustomAnimationClonerImpl aCloner;
103 		return aCloner.Clone( xSourceNode, pSource, pTarget );
104 	}
105 
Clone(const Reference<XAnimationNode> & xSourceNode,const SdPage * pSourcePage,const SdPage * pTargetPage)106 	Reference< XAnimationNode > CustomAnimationClonerImpl::Clone( const Reference< XAnimationNode >& xSourceNode, const SdPage* pSourcePage, const SdPage* pTargetPage )
107 	{
108 		try
109 		{
110 			// clone animation hierarchie
111 			Reference< ::com::sun::star::util::XCloneable > xClonable( xSourceNode, UNO_QUERY_THROW );
112 			Reference< XAnimationNode > xCloneNode( xClonable->createClone(), UNO_QUERY_THROW );
113 
114 			// create a dictionary to map source to cloned shapes
115 			if( pSourcePage && pTargetPage )
116 			{
117 				SdrObjListIter aSourceIter( *pSourcePage, IM_DEEPWITHGROUPS );
118 				SdrObjListIter aTargetIter( *pTargetPage, IM_DEEPWITHGROUPS );
119 
120 				while( aSourceIter.IsMore() && aTargetIter.IsMore() )
121 				{
122 					SdrObject* pSource = aSourceIter.Next();
123 					SdrObject* pTarget = aTargetIter.Next();
124 
125 					if( pSource && pTarget)
126 					{
127 						Reference< XShape > xSource( pSource->getUnoShape(), UNO_QUERY );
128 						Reference< XShape > xTarget( pTarget->getUnoShape(), UNO_QUERY );
129 						if( xSource.is() && xTarget.is() )
130 						{
131 							maShapeMap[xSource] = xTarget;
132 						}
133 					}
134 				}
135 			}
136 
137 			// create a dictionary to map source to cloned nodes
138 			::anim::create_deep_vector( xSourceNode, maSourceNodeVector );
139 			::anim::create_deep_vector( xCloneNode, maCloneNodeVector );
140 
141 			transformNode( xCloneNode );
142 
143 			return xCloneNode;
144 		}
145 		catch( Exception& e )
146 		{
147 			(void)e;
148 			DBG_ERROR(
149 				(OString("sd::CustomAnimationClonerImpl::Clone(), "
150 						"exception caught: ") +
151 				rtl::OUStringToOString(
152 					comphelper::anyToString( cppu::getCaughtException() ),
153 					RTL_TEXTENCODING_UTF8 )).getStr() );
154 
155 			Reference< XAnimationNode > xEmpty;
156 			return xEmpty;
157 		}
158 	}
159 
transformNode(const Reference<XAnimationNode> & xNode)160 	void CustomAnimationClonerImpl::transformNode( const Reference< XAnimationNode >& xNode )
161 	{
162 		try
163 		{
164 			xNode->setBegin( transformValue( xNode->getBegin() ) );
165 			xNode->setEnd( transformValue( xNode->getEnd() ) );
166 
167 			sal_Int16 nNodeType( xNode->getType() );
168 			switch( nNodeType )
169 			{
170 			case AnimationNodeType::ITERATE:
171 			{
172 				Reference< XIterateContainer > xIter( xNode, UNO_QUERY_THROW );
173 				xIter->setTarget( transformValue( xIter->getTarget() ) );
174 			}
175 			// its intended that here is no break!
176 			case AnimationNodeType::PAR:
177 			case AnimationNodeType::SEQ:
178 			{
179 				Reference< XEnumerationAccess > xEnumerationAccess( xNode, UNO_QUERY_THROW );
180 				Reference< XEnumeration > xEnumeration( xEnumerationAccess->createEnumeration(), UNO_QUERY_THROW );
181 				while( xEnumeration->hasMoreElements() )
182 				{
183 					Reference< XAnimationNode > xChildNode( xEnumeration->nextElement(), UNO_QUERY_THROW );
184 					transformNode( xChildNode );
185 				}
186 			}
187 			break;
188 
189 			case AnimationNodeType::ANIMATE:
190 			case AnimationNodeType::SET:
191 			case AnimationNodeType::ANIMATEMOTION:
192 			case AnimationNodeType::ANIMATECOLOR:
193 			case AnimationNodeType::ANIMATETRANSFORM:
194 			case AnimationNodeType::TRANSITIONFILTER:
195 			{
196 				Reference< XAnimate > xAnimate( xNode, UNO_QUERY_THROW );
197 				xAnimate->setTarget( transformValue( xAnimate->getTarget() ) );
198 			}
199 			break;
200 
201 			case AnimationNodeType::COMMAND:
202 			{
203 				Reference< XCommand > xCommand( xNode, UNO_QUERY_THROW );
204 				xCommand->setTarget( transformValue( xCommand->getTarget() ) );
205 			}
206 			break;
207 
208 			case AnimationNodeType::AUDIO:
209 			{
210 				Reference< XAudio > xAudio( xNode, UNO_QUERY_THROW );
211 				xAudio->setSource( transformValue( xAudio->getSource() ) );
212 			}
213 			break;
214 			}
215 
216 			Sequence< NamedValue > aUserData( xNode->getUserData() );
217 			if( aUserData.hasElements() )
218 			{
219 				NamedValue* pValue = aUserData.getArray();
220 				const sal_Int32 nLength = aUserData.getLength();
221 				sal_Int32 nElement;
222 				for( nElement = 0; nElement < nLength; nElement++, pValue++ )
223 				{
224 					pValue->Value = transformValue( pValue->Value );
225 				}
226 
227 				xNode->setUserData( aUserData );
228 			}
229 		}
230 		catch( Exception& e )
231 		{
232 			(void)e;
233 			DBG_ERROR(
234 				(OString("sd::CustomAnimationClonerImpl::transformNode(), "
235 						"exception caught: ") +
236 				rtl::OUStringToOString(
237 					comphelper::anyToString( cppu::getCaughtException() ),
238 					RTL_TEXTENCODING_UTF8 )).getStr() );
239 		}
240 	}
241 
transformValue(const Any & rValue)242 	Any CustomAnimationClonerImpl::transformValue( const Any& rValue )
243 	{
244 		if( rValue.hasValue() ) try
245 		{
246 			if( rValue.getValueType() == ::getCppuType((const ValuePair*)0) )
247 			{
248 				ValuePair aValuePair;
249 				rValue >>= aValuePair;
250 
251 				aValuePair.First = transformValue( aValuePair.First );
252 				aValuePair.Second = transformValue( aValuePair.Second );
253 
254 				return makeAny( aValuePair );
255 			}
256 			else if( rValue.getValueType() == ::getCppuType((Sequence<Any>*)0) )
257 			{
258 				Sequence<Any> aSequence;
259 				rValue >>= aSequence;
260 
261 				const sal_Int32 nLength = aSequence.getLength();
262 				sal_Int32 nElement;
263 				Any* pAny = aSequence.getArray();
264 
265 				for( nElement = 0; nElement < nLength; nElement++, pAny++ )
266 					*pAny = transformValue( *pAny );
267 
268 				return makeAny( aSequence );
269 			}
270 			else if( rValue.getValueTypeClass() == TypeClass_INTERFACE )
271 			{
272 				Reference< XShape > xShape;
273 				rValue >>= xShape;
274 				if( xShape.is() )
275 				{
276 					return makeAny( getClonedShape( xShape ) );
277 				}
278 				else
279 				{
280 					Reference< XAnimationNode > xNode;
281 					rValue >>= xNode;
282 					if( xNode.is() )
283 						return makeAny( getClonedNode( xNode ) );
284 				}
285 			}
286 			else if( rValue.getValueType() == ::getCppuType((const ParagraphTarget*)0) )
287 			{
288 				ParagraphTarget aParaTarget;
289 				rValue >>= aParaTarget;
290 
291 				aParaTarget.Shape = getClonedShape( aParaTarget.Shape );
292 
293 				return makeAny( aParaTarget );
294 			}
295 			else if( rValue.getValueType() == ::getCppuType((const Event*)0) )
296 			{
297 				Event aEvent;
298 				rValue >>= aEvent;
299 
300 				aEvent.Source = transformValue( aEvent.Source );
301 
302 				return makeAny( aEvent );
303 			}
304 		}
305 		catch( Exception& e )
306 		{
307 			(void)e;
308 			DBG_ERROR(
309 				(OString("sd::CustomAnimationClonerImpl::transformValue(), "
310 						"exception caught: ") +
311 				rtl::OUStringToOString(
312 					comphelper::anyToString( cppu::getCaughtException() ),
313 					RTL_TEXTENCODING_UTF8 )).getStr() );
314 		}
315 
316 		return rValue;
317 	}
318 
getClonedShape(const Reference<XShape> & xSource) const319     Reference< XShape > CustomAnimationClonerImpl::getClonedShape( const Reference< XShape >& xSource ) const
320     {
321         if( xSource.is() )
322 		{
323 			if( maShapeMap.find(xSource) != maShapeMap.end() )
324 			{
325 				return maShapeMap[xSource];
326 			}
327 
328 			DBG_ASSERT( maShapeMap.empty(), "sd::CustomAnimationClonerImpl::getClonedShape() failed!" );
329 		}
330         return xSource;
331     }
332 
getClonedNode(const Reference<XAnimationNode> & xSource) const333 	Reference< XAnimationNode > CustomAnimationClonerImpl::getClonedNode( const Reference< XAnimationNode >& xSource ) const
334 	{
335 		sal_Int32 nNode, nNodeCount = maSourceNodeVector.size();
336 
337 		for( nNode = 0; nNode < nNodeCount; nNode++ )
338 		{
339 			if( maSourceNodeVector[nNode] == xSource )
340 				return maCloneNodeVector[nNode];
341 		}
342 
343 		DBG_ERROR( "sd::CustomAnimationClonerImpl::getClonedNode() failed!" );
344 		return xSource;
345 	}
346 }
347