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