1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <oox/ppt/timenode.hxx>
22 #include <com/sun/star/beans/NamedValue.hpp>
23 #include <com/sun/star/container/XEnumerationAccess.hpp>
24 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
25 #include <com/sun/star/animations/XAnimateColor.hpp>
26 #include <com/sun/star/animations/XAnimateMotion.hpp>
27 #include <com/sun/star/animations/XAnimateTransform.hpp>
28 #include <com/sun/star/animations/XCommand.hpp>
29 #include <com/sun/star/animations/XAudio.hpp>
30 #include <com/sun/star/animations/XIterateContainer.hpp>
31 #include <com/sun/star/animations/XTimeContainer.hpp>
32 #include <com/sun/star/animations/XTransitionFilter.hpp>
33 #include <com/sun/star/animations/AnimationNodeType.hpp>
34 #include <com/sun/star/animations/Event.hpp>
35 #include <com/sun/star/animations/EventTrigger.hpp>
36 #include <com/sun/star/io/WrongFormatException.hpp>
37 #include <com/sun/star/presentation/EffectNodeType.hpp>
38 #include <com/sun/star/uno/XComponentContext.hpp>
40 #include <oox/core/xmlfilterbase.hxx>
41 #include <oox/ppt/pptfilterhelpers.hxx>
42 #include <oox/token/tokens.hxx>
43 #include <sal/log.hxx>
44 #include <comphelper/diagnose_ex.hxx>
46 using namespace ::oox::core
;
47 using namespace ::com::sun::star::beans
;
48 using namespace ::com::sun::star::container
;
49 using namespace ::com::sun::star::uno
;
50 using namespace ::com::sun::star::lang
;
51 using namespace ::com::sun::star::animations
;
52 using namespace ::com::sun::star::presentation
;
56 void lcl_setAncestorSubItem( const Reference
<XAnimationNode
>& xParent
, sal_Int16 nSubItem
)
59 Reference
<XAnimationNode
> xNode
= xParent
;
63 if ( xNode
->getType() == AnimationNodeType::ANIMATE
)
65 Reference
<XAnimate
> xAnimate( xNode
, UNO_QUERY
);
67 xAnimate
->setSubItem( nSubItem
);
70 else if ( xNode
->getType() == AnimationNodeType::ITERATE
)
72 Reference
<XIterateContainer
> xIterateContainer( xNode
, UNO_QUERY
);
73 if ( xIterateContainer
.is() )
74 xIterateContainer
->setSubItem( nSubItem
);
78 xNode
.set( xNode
->getParent(), UNO_QUERY
);
85 OUString
TimeNode::getServiceName( sal_Int16 nNodeType
)
87 OUString sServiceName
;
90 case AnimationNodeType::PAR
:
91 sServiceName
= "com.sun.star.animations.ParallelTimeContainer";
93 case AnimationNodeType::SEQ
:
94 sServiceName
= "com.sun.star.animations.SequenceTimeContainer";
96 case AnimationNodeType::ANIMATE
:
97 sServiceName
= "com.sun.star.animations.Animate";
99 case AnimationNodeType::ITERATE
:
100 sServiceName
= "com.sun.star.animations.IterateContainer";
102 case AnimationNodeType::ANIMATECOLOR
:
103 sServiceName
= "com.sun.star.animations.AnimateColor";
105 case AnimationNodeType::TRANSITIONFILTER
:
106 sServiceName
= "com.sun.star.animations.TransitionFilter";
108 case AnimationNodeType::ANIMATEMOTION
:
109 sServiceName
= "com.sun.star.animations.AnimateMotion";
111 case AnimationNodeType::ANIMATETRANSFORM
:
112 sServiceName
= "com.sun.star.animations.AnimateTransform";
114 case AnimationNodeType::COMMAND
:
115 sServiceName
= "com.sun.star.animations.Command";
117 case AnimationNodeType::SET
:
118 sServiceName
= "com.sun.star.animations.AnimateSet";
120 case AnimationNodeType::AUDIO
:
121 sServiceName
= "com.sun.star.animations.Audio";
124 SAL_INFO("oox.ppt","OOX: unhandled type " << nNodeType
);
130 TimeNode::TimeNode( sal_Int16 nNodeType
)
131 : mnNodeType( nNodeType
)
132 , mbHasEndSyncValue( false )
136 TimeNode::~TimeNode()
140 void fixMainSequenceTiming( const css::uno::Reference
< css::animations::XAnimationNode
>& xNode
)
145 Reference
< XEnumerationAccess
> xEA( xNode
, UNO_QUERY_THROW
);
146 Reference
< XEnumeration
> xE( xEA
->createEnumeration(), UNO_SET_THROW
);
147 while( xE
->hasMoreElements() )
150 Reference
< XAnimationNode
> xClickNode( xE
->nextElement(), UNO_QUERY
);
153 aEvent
.Trigger
= EventTrigger::ON_NEXT
;
155 xClickNode
->setBegin( Any( aEvent
) );
160 Reference
< XEnumerationAccess
> xEA2( xClickNode
, UNO_QUERY_THROW
);
161 Reference
< XEnumeration
> xE2( xEA2
->createEnumeration(), UNO_SET_THROW
);
162 if( xE2
->hasMoreElements() )
165 xE2
->nextElement() >>= xEA2
;
167 xE2
= xEA2
->createEnumeration();
171 if( xE2
.is() && xE2
->hasMoreElements() )
173 Reference
< XAnimationNode
> xEffectNode( xE2
->nextElement(), UNO_QUERY_THROW
);
174 const Sequence
< NamedValue
> aUserData( xEffectNode
->getUserData() );
175 for( const NamedValue
& rProp
: aUserData
)
177 if ( rProp
.Name
== "node-type" )
179 sal_Int16 nNodeType
= 0;
180 rProp
.Value
>>= nNodeType
;
181 if( nNodeType
!= css::presentation::EffectNodeType::ON_CLICK
)
183 // first effect does not start on click, so correct
184 // first click nodes begin to 0s
185 xClickNode
->setBegin( Any( 0.0 ) );
197 SAL_INFO("oox.ppt","fixMainSequenceTiming(), exception caught!" );
201 void fixInteractiveSequenceTiming( const css::uno::Reference
< css::animations::XAnimationNode
>& xNode
)
205 Any
aBegin( xNode
->getBegin() );
207 xNode
->setBegin( aEmpty
);
209 Reference
< XEnumerationAccess
> xEA( xNode
, UNO_QUERY_THROW
);
210 Reference
< XEnumeration
> xE( xEA
->createEnumeration(), UNO_SET_THROW
);
211 while( xE
->hasMoreElements() )
214 Reference
< XAnimationNode
> xClickNode( xE
->nextElement(), UNO_QUERY
);
215 xClickNode
->setBegin( aBegin
);
220 SAL_INFO("oox.ppt","fixInteractiveSequenceTiming(), exception caught!" );
224 void TimeNode::addNode( const XmlFilterBase
& rFilter
, const Reference
< XAnimationNode
>& rxNode
, const SlidePersistPtr
& pSlide
)
227 sal_Int16 nNodeType
= mnNodeType
;
229 if (mnNodeType
== AnimationNodeType::PAR
&& maNodeProperties
[NP_ITERATETYPE
].hasValue())
230 nNodeType
= AnimationNodeType::ITERATE
;
232 OUString sServiceName
= getServiceName(nNodeType
);
234 Reference
< XAnimationNode
> xNode
= createAndInsert( rFilter
, sServiceName
, rxNode
);
237 setNode(rFilter
, xNode
, pSlide
, rxNode
);
239 catch( const Exception
& )
241 TOOLS_INFO_EXCEPTION("oox.ppt","OOX: exception raised in TimeNode::addNode()" );
245 void TimeNode::setNode(const XmlFilterBase
& rFilter
, const Reference
< XAnimationNode
>& xNode
, const SlidePersistPtr
& pSlide
, const Reference
<XAnimationNode
>& xParent
)
247 SAL_WARN_IF( !xNode
.is(), "oox.ppt", "null node passed" );
250 if( !msId
.isEmpty() )
252 pSlide
->getAnimNodesMap()[ msId
] = xNode
;
257 sal_Int16
nSubItem(0);
258 maNodeProperties
[ NP_TARGET
] = mpTarget
->convert( pSlide
, nSubItem
);
259 if( mpTarget
->mnType
== XML_spTgt
)
261 if ( xNode
->getType() == AnimationNodeType::ANIMATE
||
262 xNode
->getType() == AnimationNodeType::ITERATE
)
264 maNodeProperties
[ NP_SUBITEM
] <<= nSubItem
;
267 lcl_setAncestorSubItem( xParent
, nSubItem
);
271 if( !maStCondList
.empty() )
273 Any aAny
= AnimationCondition::convertList( pSlide
, maStCondList
);
274 if( aAny
.hasValue() )
276 xNode
->setBegin( aAny
);
280 if( !maEndCondList
.empty() )
282 Any aAny
= AnimationCondition::convertList( pSlide
, maEndCondList
);
283 if( aAny
.hasValue() )
285 xNode
->setEnd( aAny
);
288 if( mbHasEndSyncValue
)
290 Any aValue
= maEndSyncValue
.convert( pSlide
);
291 xNode
->setEndSync(aValue
);
294 if( !maUserData
.empty() )
296 Sequence
< NamedValue
> aUserDataSeq( static_cast< sal_Int32
>( maUserData
.size() ) );
297 NamedValue
* pValues
= aUserDataSeq
.getArray();
298 for (auto const& elem
: maUserData
)
300 pValues
->Name
= elem
.first
;
301 pValues
->Value
= elem
.second
;
304 maNodeProperties
[ NP_USERDATA
] <<= aUserDataSeq
;
307 Reference
< XAnimate
> xAnimate( xNode
, UNO_QUERY
);
308 Reference
< XAnimateColor
> xAnimateColor( xNode
, UNO_QUERY
);
309 Reference
< XAnimateMotion
> xAnimateMotion( xNode
, UNO_QUERY
);
310 Reference
< XAnimateTransform
> xAnimateTransform( xNode
, UNO_QUERY
);
311 Reference
< XCommand
> xCommand( xNode
, UNO_QUERY
);
312 Reference
< XAudio
> xAudio( xNode
, UNO_QUERY
);
313 Reference
< XIterateContainer
> xIterateContainer( xNode
, UNO_QUERY
);
314 sal_Int16 nInt16
= 0;
318 Sequence
< NamedValue
> aSeq
;
320 for( int i
= 0; i
< NP_SIZE_
; i
++)
322 Any
& aValue( maNodeProperties
[ i
] );
323 if( aValue
.hasValue() )
329 xAnimate
->setTo( aValue
);
333 xAnimate
->setFrom( aValue
);
337 xAnimate
->setBy( aValue
);
339 case NP_HIDEDURINGSHOW
:
340 if (xAudio
.is() && (aValue
>>= bBool
))
342 xAudio
->setHideDuringShow(bBool
);
346 if (xAudio
.is() && (aValue
>>= bBool
))
348 xAudio
->setNarration(bBool
);
353 if (xParent
.is() && xParent
->getType() == AnimationNodeType::ITERATE
)
355 Reference
<XIterateContainer
> xParentContainer(xParent
, UNO_QUERY
);
356 if (xParentContainer
.is())
357 xParentContainer
->setTarget(aValue
);
362 xAnimate
->setTarget(aValue
);
364 xCommand
->setTarget(aValue
);
366 xAudio
->setSource(aValue
);
370 if( aValue
>>= nInt16
)
374 xAnimate
->setSubItem( nInt16
);
376 else if ( xIterateContainer
.is() )
378 xIterateContainer
->setSubItem( nInt16
);
383 SAL_INFO("oox.ppt","any >>= failed " << __LINE__
);
386 case NP_ATTRIBUTENAME
:
389 if( aValue
>>= sString
)
390 xAnimate
->setAttributeName( sString
);
393 SAL_INFO("oox.ppt","any >>= failed " << __LINE__
);
400 if( aValue
>>= nInt16
)
401 xAnimate
->setCalcMode( nInt16
);
404 SAL_INFO("oox.ppt","any >>= failed " << __LINE__
);
411 Sequence
<double> aKeyTimes
;
412 if( aValue
>>= aKeyTimes
)
413 xAnimate
->setKeyTimes(aKeyTimes
);
416 SAL_INFO("oox.ppt","any >>= failed " << __LINE__
);
423 Sequence
<Any
> aValues
;
424 if( aValue
>>= aValues
)
425 xAnimate
->setValues(aValues
);
428 SAL_INFO("oox.ppt","any >>= failed " << __LINE__
);
435 if( aValue
>>= sString
)
436 xAnimate
->setFormula(sString
);
439 SAL_INFO("oox.ppt","any >>= failed " << __LINE__
);
443 case NP_COLORINTERPOLATION
:
444 if( xAnimateColor
.is() )
446 if( aValue
>>= nInt16
)
447 xAnimateColor
->setColorInterpolation( nInt16
);
450 SAL_INFO("oox.ppt","any >>= failed " << __LINE__
);
455 if( xAnimateColor
.is() )
457 if( aValue
>>= bBool
)
458 xAnimateColor
->setDirection( bBool
);
461 SAL_INFO("oox.ppt","any >>= failed " << __LINE__
);
466 if( xAnimateMotion
.is() )
467 xAnimateMotion
->setPath( aValue
);
469 case NP_TRANSFORMTYPE
:
470 if( xAnimateTransform
.is() )
472 if( aValue
>>= nInt16
)
473 xAnimateTransform
->setTransformType( nInt16
);
476 SAL_INFO("oox.ppt","any >>= failed " << __LINE__
);
481 if( aValue
>>= aSeq
)
482 xNode
->setUserData( aSeq
);
485 SAL_INFO("oox.ppt","any >>= failed " << __LINE__
);
488 case NP_ACCELERATION
:
489 if( aValue
>>= fDouble
)
490 xNode
->setAcceleration( fDouble
);
493 SAL_INFO("oox.ppt","any >>= failed " << __LINE__
);
497 if( aValue
>>= fDouble
)
498 xNode
->setDecelerate( fDouble
);
501 SAL_INFO("oox.ppt","any >>= failed " << __LINE__
);
505 if( aValue
>>= bBool
)
506 xNode
->setAutoReverse( bBool
);
509 SAL_INFO("oox.ppt","any >>= failed " << __LINE__
);
513 xNode
->setDuration( aValue
);
516 if( aValue
>>= nInt16
)
517 xNode
->setFill( nInt16
);
520 SAL_INFO("oox.ppt","any >>= failed " << __LINE__
);
524 xNode
->setRepeatCount( aValue
);
526 case NP_REPEATDURATION
:
527 xNode
->setRepeatDuration( aValue
);
530 if( aValue
>>= nInt16
)
531 xNode
->setRestart( nInt16
);
534 SAL_INFO("oox.ppt","any >>= failed " << __LINE__
);
540 if( aValue
>>= nInt16
)
541 xCommand
->setCommand( nInt16
);
544 SAL_INFO("oox.ppt","any >>= failed " << __LINE__
);
550 xCommand
->setParameter( aValue
);
553 if( xIterateContainer
.is() )
555 if( aValue
>>= nInt16
)
556 xIterateContainer
->setIterateType( nInt16
);
559 SAL_INFO("oox.ppt","any >>= failed " << __LINE__
);
563 case NP_ITERATEINTERVAL
:
564 if( xIterateContainer
.is() )
566 if( aValue
>>= fDouble
)
567 xIterateContainer
->setIterateInterval( fDouble
);
570 SAL_INFO("oox.ppt","any >>= failed " << __LINE__
);
575 SAL_INFO("oox.ppt","ERR-OOX: unknown prop index " << i
);
581 if (xAnimate
.is() && xAnimate
->getValues().getLength() != xAnimate
->getKeyTimes().getLength())
582 throw css::io::WrongFormatException();
584 if( mnNodeType
== AnimationNodeType::TRANSITIONFILTER
)
587 Reference
< XTransitionFilter
> xFilter( xNode
, UNO_QUERY
);
588 maTransitionFilter
.setTransitionFilterProperties( xFilter
);
592 maChildren
.begin(), maChildren
.end(),
593 [&rFilter
, &xNode
, &pSlide
] (TimeNodePtr
const & child
) {
594 child
->addNode(rFilter
, xNode
, pSlide
);
599 case AnimationNodeType::SEQ
:
602 if( maUserData
[ u
"node-type"_ustr
] >>= nEnum
)
604 if( nEnum
== EffectNodeType::MAIN_SEQUENCE
)
606 fixMainSequenceTiming( xNode
);
608 else if( nEnum
== EffectNodeType::INTERACTIVE_SEQUENCE
)
610 fixInteractiveSequenceTiming( xNode
);
615 case AnimationNodeType::PAR
:
616 // some other cut&paste... from AnimationImporter::importAnimationContainer()
620 catch( const Exception
& )
622 TOOLS_INFO_EXCEPTION("oox.ppt","OOX: exception raised in TimeNode::setNode()");
626 Reference
< XAnimationNode
> TimeNode::createAndInsert(
627 const XmlFilterBase
& rFilter
,
628 const OUString
& rServiceName
,
629 const Reference
< XAnimationNode
>& rxNode
)
632 Reference
< XAnimationNode
> xNode( Reference
<css::lang::XMultiServiceFactory
>(rFilter
.getComponentContext()->getServiceManager(), UNO_QUERY_THROW
)->createInstance( rServiceName
), UNO_QUERY_THROW
);
633 Reference
< XTimeContainer
> xParentContainer( rxNode
, UNO_QUERY_THROW
);
635 xParentContainer
->appendChild( xNode
);
638 catch( const Exception
& )
640 TOOLS_INFO_EXCEPTION("oox.ppt", "OOX: exception raised in TimeNode::createAndInsert() trying to create a service " << rServiceName
);
643 return Reference
< XAnimationNode
>();
646 void TimeNode::setId( sal_Int32 nId
)
648 msId
= OUString::number(nId
);
651 void TimeNode::setTo( const Any
& aTo
)
653 maNodeProperties
[ NP_TO
] = aTo
;
656 void TimeNode::setFrom( const Any
& aFrom
)
658 maNodeProperties
[ NP_FROM
] = aFrom
;
661 void TimeNode::setBy( const Any
& aBy
)
663 maNodeProperties
[ NP_BY
] = aBy
;
668 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */