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