xref: /trunk/main/sd/source/core/CustomAnimationCloner.cxx (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
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