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