xref: /AOO41X/main/oox/source/ppt/timenode.cxx (revision ca5ec2004b000a7d9aaa8381be8ac2853e3b1dc7)
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 #include "oox/ppt/timenode.hxx"
25 
26 #include <boost/bind.hpp>
27 
28 #include <com/sun/star/beans/XPropertySet.hpp>
29 #include <com/sun/star/beans/NamedValue.hpp>
30 #include <com/sun/star/container/XEnumerationAccess.hpp>
31 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
32 #include <com/sun/star/frame/XModel.hpp>
33 #include <com/sun/star/animations/XAnimateColor.hpp>
34 #include <com/sun/star/animations/XAnimateMotion.hpp>
35 #include <com/sun/star/animations/XAnimateTransform.hpp>
36 #include <com/sun/star/animations/XCommand.hpp>
37 #include <com/sun/star/animations/XIterateContainer.hpp>
38 #include <com/sun/star/animations/XAnimationNodeSupplier.hpp>
39 #include <com/sun/star/animations/XTimeContainer.hpp>
40 #include <com/sun/star/animations/AnimationNodeType.hpp>
41 #include <com/sun/star/animations/Event.hpp>
42 #include <com/sun/star/animations/EventTrigger.hpp>
43 #include <com/sun/star/presentation/EffectNodeType.hpp>
44 
45 #include "oox/helper/helper.hxx"
46 #include "oox/core/xmlfilterbase.hxx"
47 
48 using ::rtl::OUString;
49 using namespace ::oox::core;
50 using namespace ::com::sun::star::beans;
51 using namespace ::com::sun::star::container;
52 using namespace ::com::sun::star::uno;
53 using namespace ::com::sun::star::lang;
54 using namespace ::com::sun::star::animations;
55 using namespace ::com::sun::star::frame;
56 using namespace ::com::sun::star::presentation;
57 
58 namespace oox { namespace ppt {
59 
getServiceName(sal_Int16 nNodeType)60         OUString TimeNode::getServiceName( sal_Int16 nNodeType )
61         {
62             OUString sServiceName;
63             switch( nNodeType )
64             {
65             case AnimationNodeType::PAR:
66 //              sServiceName = CREATE_OUSTRING("com.sun.star.animations.IterateContainer");
67                 sServiceName = CREATE_OUSTRING("com.sun.star.animations.ParallelTimeContainer");
68                 break;
69             case AnimationNodeType::SEQ:
70                 sServiceName = CREATE_OUSTRING("com.sun.star.animations.SequenceTimeContainer");
71                 break;
72             case AnimationNodeType::ANIMATE:
73                 sServiceName = CREATE_OUSTRING("com.sun.star.animations.Animate");
74                 break;
75             case AnimationNodeType::ANIMATECOLOR:
76                 sServiceName = CREATE_OUSTRING("com.sun.star.animations.AnimateColor");
77                 break;
78             case AnimationNodeType::TRANSITIONFILTER:
79                 sServiceName = CREATE_OUSTRING("com.sun.star.animations.TransitionFilter");
80                 break;
81             case AnimationNodeType::ANIMATEMOTION:
82                 sServiceName = CREATE_OUSTRING("com.sun.star.animations.AnimateMotion");
83                 break;
84             case AnimationNodeType::ANIMATETRANSFORM:
85                 sServiceName = CREATE_OUSTRING("com.sun.star.animations.AnimateTransform");
86                 break;
87             case AnimationNodeType::COMMAND:
88                 sServiceName = CREATE_OUSTRING("com.sun.star.animations.Command");
89                 break;
90             case AnimationNodeType::SET:
91                 sServiceName = CREATE_OUSTRING("com.sun.star.animations.AnimateSet");
92                 break;
93             case AnimationNodeType::AUDIO:
94                 sServiceName = CREATE_OUSTRING("com.sun.star.animations.Audio");
95                 break;
96             default:
97                 OSL_TRACE( "OOX: uhandled type %x", nNodeType );
98                 break;
99             }
100             return sServiceName;
101         }
102 
103 
104 
TimeNode(sal_Int16 nNodeType)105     TimeNode::TimeNode( sal_Int16 nNodeType )
106         : mnNodeType( nNodeType )
107         , mbHasEndSyncValue( false )
108     {
109     }
110 
111 
~TimeNode()112     TimeNode::~TimeNode()
113     {
114     }
115 
116 // BEGIN CUT&PASTE from sd/source/filter/ppt/pptinanimations.hxx
117 // --------------------------------------------------------------------
fixMainSequenceTiming(const::com::sun::star::uno::Reference<::com::sun::star::animations::XAnimationNode> & xNode)118     static void fixMainSequenceTiming( const ::com::sun::star::uno::Reference< ::com::sun::star::animations::XAnimationNode >& xNode )
119     {
120         try
121         {
122             bool bFirst = true;
123             Reference< XEnumerationAccess > xEA( xNode, UNO_QUERY_THROW );
124             Reference< XEnumeration > xE( xEA->createEnumeration(), UNO_QUERY_THROW );
125             while( xE->hasMoreElements() )
126             {
127                 // click node
128                 Reference< XAnimationNode > xClickNode( xE->nextElement(), UNO_QUERY );
129 
130                 Event aEvent;
131                 aEvent.Trigger = EventTrigger::ON_NEXT;
132                 aEvent.Repeat = 0;
133                 xClickNode->setBegin( makeAny( aEvent ) );
134 
135                 if( bFirst )
136                 {
137                     bFirst = false;
138                     Reference< XEnumerationAccess > xEA2( xClickNode, UNO_QUERY_THROW );
139                     Reference< XEnumeration > xE2( xEA2->createEnumeration(), UNO_QUERY_THROW );
140                     if( xE2->hasMoreElements() )
141                     {
142                         // with node
143                         xE2->nextElement() >>= xEA2;
144                         if( xEA2.is() )
145                             xE2.query( xEA2->createEnumeration() );
146                         else
147                             xE2.clear();
148 
149                         if( xE2.is() && xE2->hasMoreElements() )
150                         {
151                             Reference< XAnimationNode > xEffectNode( xE2->nextElement(), UNO_QUERY_THROW );
152                             const Sequence< NamedValue > aUserData( xEffectNode->getUserData() );
153                             const NamedValue* p = aUserData.getConstArray();
154                             sal_Int32 nLength = aUserData.getLength();
155                             while( nLength-- )
156                             {
157                                 if( p->Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "node-type" ) ) )
158                                 {
159                                     sal_Int16 nNodeType = 0;
160                                     p->Value >>= nNodeType;
161                                     if( nNodeType != ::com::sun::star::presentation::EffectNodeType::ON_CLICK )
162                                     {
163                                         // first effect does not start on click, so correct
164                                         // first click nodes begin to 0s
165                                         xClickNode->setBegin( makeAny( (double)0.0 ) );
166                                         break;
167                                     }
168                                 }
169                                 p++;
170                             }
171                         }
172                     }
173                 }
174             }
175         }
176         catch( Exception& e )
177         {
178             (void)e;
179             OSL_TRACE("fixMainSequenceTiming(), exception caught!" );
180         }
181     }
182 
183 // --------------------------------------------------------------------
184 
fixInteractiveSequenceTiming(const::com::sun::star::uno::Reference<::com::sun::star::animations::XAnimationNode> & xNode)185     static void fixInteractiveSequenceTiming( const ::com::sun::star::uno::Reference< ::com::sun::star::animations::XAnimationNode >& xNode )
186     {
187         try
188         {
189             Any aBegin( xNode->getBegin() );
190             Any aEmpty;
191             xNode->setBegin( aEmpty );
192 
193             Reference< XEnumerationAccess > xEA( xNode, UNO_QUERY_THROW );
194             Reference< XEnumeration > xE( xEA->createEnumeration(), UNO_QUERY_THROW );
195             while( xE->hasMoreElements() )
196             {
197                 // click node
198                 Reference< XAnimationNode > xClickNode( xE->nextElement(), UNO_QUERY );
199                 xClickNode->setBegin( aBegin );
200             }
201         }
202         catch( Exception& e )
203         {
204             (void)e;
205             OSL_TRACE("fixInteractiveSequenceTiming(), exception caught!" );
206         }
207     }
208 
209 // END CUT&PASTE
210 
addNode(const XmlFilterBase & rFilter,const Reference<XAnimationNode> & rxNode,const SlidePersistPtr & pSlide)211     void TimeNode::addNode( const XmlFilterBase& rFilter, const Reference< XAnimationNode >& rxNode, const SlidePersistPtr & pSlide )
212     {
213         try {
214             OUString sServiceName = getServiceName( mnNodeType );
215             Reference< XAnimationNode > xNode = createAndInsert( rFilter, sServiceName, rxNode );
216             setNode( rFilter, xNode, pSlide );
217         }
218         catch( const Exception& e )
219         {
220             OSL_TRACE( "OOX: exception raised in TimeNode::addNode() - %s",
221                                  OUStringToOString( e.Message, RTL_TEXTENCODING_ASCII_US ).getStr() );
222         }
223     }
224 
setNode(const XmlFilterBase & rFilter,const Reference<XAnimationNode> & xNode,const SlidePersistPtr & pSlide)225     void TimeNode::setNode( const XmlFilterBase& rFilter, const Reference< XAnimationNode >& xNode, const SlidePersistPtr & pSlide )
226     {
227         OSL_ENSURE( xNode.is(), "null node passed" );
228 
229         try {
230             if( msId.getLength() )
231             {
232                 pSlide->getAnimNodesMap()[ msId ] = xNode;
233             }
234 
235             if( mpTarget )
236             {
237                 sal_Int16 nSubType;
238                 maNodeProperties[ NP_TARGET ] = mpTarget->convert( pSlide, nSubType );
239                 if( mpTarget->mnType == XML_spTgt )
240                 {
241                     maNodeProperties[ NP_SUBITEM ] <<= nSubType;
242                 }
243             }
244 
245             if( !maStCondList.empty() )
246             {
247                 Any aAny = AnimationCondition::convertList( pSlide, maStCondList );
248                 if( aAny.hasValue() )
249                 {
250                     xNode->setBegin( aAny );
251                 }
252 
253             }
254             if( !maEndCondList.empty() )
255             {
256                 Any aAny = AnimationCondition::convertList( pSlide, maEndCondList );
257                 if( aAny.hasValue() )
258                 {
259                     xNode->setEnd( aAny );
260                 }
261             }
262 #if 0  // FIXME even the binary filter has this disabled.
263             if( !maNextCondList.empty() )
264             {
265                 Any aAny = AnimationCondition::convertList( pSlide, maNextCondList );
266                 if( aAny.hasValue() )
267                 {
268                     xNode->setNext( aAny );
269                 }
270             }
271             if( !maPrevCondList.empty() )
272             {
273                 Any aAny = AnimationCondition::convertList( pSlide, maPrevCondList );
274                 if( aAny.hasValue() )
275                 {
276                     xNode->setPrev( aAny );
277                 }
278             }
279 #endif
280             if( mbHasEndSyncValue )
281             {
282                 Any aValue = maEndSyncValue.convert( pSlide );
283                 xNode->setEndSync(aValue);
284             }
285 
286             if( !maUserData.empty() )
287             {
288                 Sequence< NamedValue > aUserDataSeq( static_cast< sal_Int32 >( maUserData.size() ) );
289                 NamedValue* pValues = aUserDataSeq.getArray();
290                 for( UserDataMap::const_iterator aIt = maUserData.begin(), aEnd = maUserData.end(); aIt != aEnd; ++aIt, ++pValues )
291                 {
292                     pValues->Name = aIt->first;
293                     pValues->Value = aIt->second;
294                 }
295                 maNodeProperties[ NP_USERDATA ] <<= aUserDataSeq;
296             }
297 
298             Reference< XAnimate > xAnimate( xNode, UNO_QUERY );
299             Reference< XAnimateColor > xAnimateColor( xNode, UNO_QUERY );
300             Reference< XAnimateMotion > xAnimateMotion( xNode, UNO_QUERY );
301             Reference< XAnimateTransform > xAnimateTransform( xNode, UNO_QUERY );
302             Reference< XCommand > xCommand( xNode, UNO_QUERY );
303             Reference< XIterateContainer > xIterateContainer( xNode, UNO_QUERY );
304             sal_Int16 nInt16 = 0;
305             sal_Bool bBool = sal_False;
306             double fDouble = 0;
307             OUString sString;
308             Sequence< NamedValue > aSeq;
309 
310             for( int i = 0; i < _NP_SIZE; i++)
311             {
312                 Any & aValue( maNodeProperties[ i ] );
313                 if( aValue.hasValue() )
314                 {
315                     switch( i )
316                     {
317                     case NP_TO:
318                         if( xAnimate.is() )
319                             xAnimate->setTo( aValue );
320                         break;
321                     case NP_FROM:
322                         if( xAnimate.is() )
323                             xAnimate->setFrom( aValue );
324                         break;
325                     case NP_BY:
326                         if( xAnimate.is() )
327                             xAnimate->setBy( aValue );
328                         break;
329                     case NP_TARGET:
330                         if( xAnimate.is() )
331                             xAnimate->setTarget( aValue );
332                         break;
333                     case NP_SUBITEM:
334                         if( xAnimate.is() )
335                         {
336                             if( aValue >>= nInt16 )
337                                 xAnimate->setSubItem( nInt16 );
338                             else
339                             {
340                                 OSL_TRACE( "any >>= failed %d", __LINE__ );
341                             }
342                         }
343                         break;
344                     case NP_ATTRIBUTENAME:
345                         if( xAnimate.is() )
346                         {
347                             if( aValue >>= sString )
348                                 xAnimate->setAttributeName( sString );
349                             else
350                             {
351                                 OSL_TRACE( "any >>= failed %d", __LINE__ );
352                             }
353                         }
354                         break;
355                     case NP_CALCMODE:
356                         if( xAnimate.is() )
357                         {
358                             if( aValue >>= nInt16 )
359                                 xAnimate->setCalcMode( nInt16 );
360                             else
361                             {
362                                 OSL_TRACE( "any >>= failed %d", __LINE__ );
363                             }
364                         }
365                         break;
366                     case NP_KEYTIMES:
367                         if( xAnimate.is() )
368                         {
369                             Sequence<double> aKeyTimes;
370                             if( aValue >>= aKeyTimes )
371                                 xAnimate->setKeyTimes(aKeyTimes);
372                             else
373                             {
374                                 OSL_TRACE( "any >>= failed %d", __LINE__ );
375                             }
376                         }
377                         break;
378                     case NP_VALUES:
379                         if( xAnimate.is() )
380                         {
381                             Sequence<Any> aValues;
382                             if( aValue >>= aValues )
383                                 xAnimate->setValues(aValues);
384                             else
385                             {
386                                 OSL_TRACE( "any >>= failed %d", __LINE__ );
387                             }
388                         }
389                         break;
390                     case NP_FORMULA:
391                         if( xAnimate.is() )
392                         {
393                             if( aValue >>= sString )
394                                 xAnimate->setFormula(sString);
395                             else
396                             {
397                                 OSL_TRACE( "any >>= failed %d", __LINE__ );
398                             }
399                         }
400                         break;
401                     case NP_COLORINTERPOLATION:
402                         if( xAnimateColor.is() )
403                         {
404                             if( aValue >>= nInt16 )
405                                 xAnimateColor->setColorInterpolation( nInt16 );
406                             else
407                             {
408                                 OSL_TRACE( "any >>= failed %d", __LINE__ );
409                             }
410                         }
411                         break;
412                     case NP_DIRECTION:
413                         if( xAnimateColor.is() )
414                         {
415                             if( aValue >>= bBool )
416                                 xAnimateColor->setDirection( bBool );
417                             else
418                             {
419                                 OSL_TRACE( "any >>= failed %d", __LINE__ );
420                             }
421                         }
422                         break;
423                     case NP_PATH:
424                         if( xAnimateMotion.is() )
425                             xAnimateMotion->setPath( aValue );
426                         break;
427                     case NP_TRANSFORMTYPE:
428                         if( xAnimateTransform.is() )
429                         {
430                             if( aValue >>= nInt16 )
431                                 xAnimateTransform->setTransformType( nInt16 );
432                             else
433                             {
434                                 OSL_TRACE( "any >>= failed %d", __LINE__ );
435                             }
436                         }
437                         break;
438                     case NP_USERDATA:
439                         if( aValue >>= aSeq )
440                             xNode->setUserData( aSeq );
441                         else
442                         {
443                             OSL_TRACE( "any >>= failed %d", __LINE__ );
444                         }
445                         break;
446                     case NP_ACCELERATION:
447                         if( aValue >>= fDouble )
448                             xNode->setAcceleration( fDouble );
449                         else
450                         {
451                             OSL_TRACE( "any >>= failed %d", __LINE__ );
452                         }
453                         break;
454                     case NP_DECELERATE:
455                         if( aValue >>= fDouble )
456                             xNode->setDecelerate( fDouble );
457                         else
458                         {
459                             OSL_TRACE( "any >>= failed %d", __LINE__ );
460                         }
461                         break;
462                     case NP_AUTOREVERSE:
463                         if( aValue >>= bBool )
464                             xNode->setAutoReverse( bBool );
465                         else
466                         {
467                             OSL_TRACE( "any >>= failed %d", __LINE__ );
468                         }
469                         break;
470                     case NP_DURATION:
471                         xNode->setDuration( aValue );
472                         break;
473                     case NP_FILL:
474                         if( aValue >>= nInt16 )
475                             xNode->setFill( nInt16 );
476                         else
477                         {
478                             OSL_TRACE( "any >>= failed %d", __LINE__ );
479                         }
480                         break;
481                     case NP_REPEATCOUNT:
482                         xNode->setRepeatCount( aValue );
483                         break;
484                     case NP_REPEATDURATION:
485                         xNode->setRepeatDuration( aValue );
486                         break;
487                     case NP_RESTART:
488                         if( aValue >>= nInt16 )
489                             xNode->setRestart( nInt16 );
490                         else
491                         {
492                             OSL_TRACE( "any >>= failed %d", __LINE__ );
493                         }
494                         break;
495                     case NP_COMMAND:
496                         if( xCommand.is() )
497                         {
498                             if( aValue >>= nInt16 )
499                                 xCommand->setCommand( nInt16 );
500                             else
501                             {
502                                 OSL_TRACE( "any >>= failed %d", __LINE__ );
503                             }
504                         }
505                         break;
506                     case NP_PARAMETER:
507                         if( xCommand.is() )
508                             xCommand->setParameter( aValue );
509                         break;
510                     case NP_ITERATETYPE:
511                         if( xIterateContainer.is() )
512                         {
513                             if( aValue >>= nInt16 )
514                                 xIterateContainer->setIterateType( nInt16 );
515                             else
516                             {
517                                 OSL_TRACE( "any >>= failed %d", __LINE__ );
518                             }
519                         }
520                         break;
521                     case NP_ITERATEINTERVAL:
522                         if( xIterateContainer.is() )
523                         {
524                             if( aValue >>= fDouble )
525                                 xIterateContainer->setIterateInterval( fDouble );
526                             else
527                             {
528                                 OSL_TRACE( "any >>= failed %d", __LINE__ );
529                             }
530                         }
531                         break;
532                     default:
533                         OSL_TRACE( "ERR-OOX: unknown prop index %d", i );
534                         break;
535                     }
536                 }
537             }
538 
539             if( mnNodeType == AnimationNodeType::TRANSITIONFILTER )
540             {
541 
542                 Reference< XTransitionFilter > xFilter( xNode, UNO_QUERY );
543                 maTransitionFilter.setTransitionFilterProperties( xFilter );
544             }
545 
546             std::for_each( maChildren.begin(), maChildren.end(),
547                            boost::bind(&TimeNode::addNode, _1, boost::cref(rFilter), boost::ref(xNode),
548                                        boost::ref(pSlide) ) );
549 
550             switch( mnNodeType )
551             {
552             case AnimationNodeType::SEQ:
553             {
554                 sal_Int16 nEnum = 0;
555                 if( maUserData[ CREATE_OUSTRING( "node-type" ) ] >>= nEnum )
556                 {
557                     if( nEnum == EffectNodeType::MAIN_SEQUENCE )
558                     {
559                         fixMainSequenceTiming( xNode );
560                     }
561                     else if( nEnum ==  EffectNodeType::INTERACTIVE_SEQUENCE )
562                     {
563                         fixInteractiveSequenceTiming( xNode );
564                     }
565                 }
566                 break;
567             }
568             case AnimationNodeType::PAR:
569                 // some other cut&paste... from AnimationImporter::importAnimationContainer()
570                 break;
571             }
572         }
573         catch( const Exception& e )
574         {
575             OSL_TRACE( "OOX: exception raised in TimeNode::setNode() - %s",
576                                  OUStringToOString( e.Message, RTL_TEXTENCODING_ASCII_US ).getStr() );
577         }
578     }
579 
580 
createAndInsert(const XmlFilterBase & rFilter,const OUString & rServiceName,const Reference<XAnimationNode> & rxNode)581     Reference< XAnimationNode > TimeNode::createAndInsert(
582             const XmlFilterBase& rFilter,
583             const OUString& rServiceName,
584             const Reference< XAnimationNode >& rxNode )
585     {
586         try {
587             Reference< XAnimationNode > xNode ( rFilter.getServiceFactory()->createInstance( rServiceName ), UNO_QUERY_THROW );
588             Reference< XTimeContainer > xParentContainer( rxNode, UNO_QUERY_THROW );
589 
590             xParentContainer->appendChild( xNode );
591             return xNode;
592         }
593         catch( const Exception& e )
594         {
595             OSL_TRACE( "OOX: exception raised in TimeNode::createAndInsert() trying to create a service %s = %s",
596                                  OUStringToOString( rServiceName, RTL_TEXTENCODING_ASCII_US ).getStr(),
597                                  OUStringToOString( e.Message, RTL_TEXTENCODING_ASCII_US ).getStr() );
598         }
599 
600         return Reference< XAnimationNode >();
601     }
602 
603 
setId(sal_Int32 nId)604     void    TimeNode::setId( sal_Int32 nId )
605     {
606         msId = OUString::valueOf(nId);
607     }
608 
setTo(const Any & aTo)609     void TimeNode::setTo( const Any & aTo )
610     {
611         maNodeProperties[ NP_TO ] = aTo;
612     }
613 
614 
setFrom(const Any & aFrom)615     void TimeNode::setFrom( const Any & aFrom )
616     {
617         maNodeProperties[ NP_FROM ] = aFrom;
618     }
619 
setBy(const Any & aBy)620     void TimeNode::setBy( const Any & aBy )
621     {
622         maNodeProperties[ NP_BY ] = aBy;
623     }
624 
625 
626 } }
627