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