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