diff options
Diffstat (limited to '')
-rw-r--r-- | oox/source/ppt/timenode.cxx | 668 |
1 files changed, 668 insertions, 0 deletions
diff --git a/oox/source/ppt/timenode.cxx b/oox/source/ppt/timenode.cxx new file mode 100644 index 000000000..2701a3f60 --- /dev/null +++ b/oox/source/ppt/timenode.cxx @@ -0,0 +1,668 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <oox/ppt/timenode.hxx> + +#include <com/sun/star/beans/NamedValue.hpp> +#include <com/sun/star/container/XEnumerationAccess.hpp> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/animations/XAnimateColor.hpp> +#include <com/sun/star/animations/XAnimateMotion.hpp> +#include <com/sun/star/animations/XAnimateTransform.hpp> +#include <com/sun/star/animations/XCommand.hpp> +#include <com/sun/star/animations/XAudio.hpp> +#include <com/sun/star/animations/XIterateContainer.hpp> +#include <com/sun/star/animations/XTimeContainer.hpp> +#include <com/sun/star/animations/XTransitionFilter.hpp> +#include <com/sun/star/animations/AnimationNodeType.hpp> +#include <com/sun/star/animations/Event.hpp> +#include <com/sun/star/animations/EventTrigger.hpp> +#include <com/sun/star/io/WrongFormatException.hpp> +#include <com/sun/star/presentation/EffectNodeType.hpp> +#include <com/sun/star/uno/XComponentContext.hpp> + +#include <oox/core/xmlfilterbase.hxx> +#include <oox/ppt/pptfilterhelpers.hxx> +#include <oox/token/tokens.hxx> +#include <sal/log.hxx> +#include <tools/diagnose_ex.h> + +using namespace ::oox::core; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::animations; +using namespace ::com::sun::star::presentation; + +namespace { + +void lcl_setAncestorSubItem( const Reference<XAnimationNode>& xParent, sal_Int16 nSubItem ) +{ + + Reference<XAnimationNode> xNode = xParent; + + while ( xNode.is() ) + { + if ( xNode->getType() == AnimationNodeType::ANIMATE ) + { + Reference<XAnimate> xAnimate( xNode, UNO_QUERY ); + if ( xAnimate.is() ) + xAnimate->setSubItem( nSubItem ); + break; + } + else if ( xNode->getType() == AnimationNodeType::ITERATE ) + { + Reference<XIterateContainer> xIterateContainer( xNode, UNO_QUERY ); + if ( xIterateContainer.is() ) + xIterateContainer->setSubItem( nSubItem ); + break; + } + + xNode.set( xNode->getParent(), UNO_QUERY ); + } +} + +} + +namespace oox::ppt { + OUString TimeNode::getServiceName( sal_Int16 nNodeType ) + { + OUString sServiceName; + switch( nNodeType ) + { + case AnimationNodeType::PAR: + sServiceName = "com.sun.star.animations.ParallelTimeContainer"; + break; + case AnimationNodeType::SEQ: + sServiceName = "com.sun.star.animations.SequenceTimeContainer"; + break; + case AnimationNodeType::ANIMATE: + sServiceName = "com.sun.star.animations.Animate"; + break; + case AnimationNodeType::ITERATE: + sServiceName = "com.sun.star.animations.IterateContainer"; + break; + case AnimationNodeType::ANIMATECOLOR: + sServiceName = "com.sun.star.animations.AnimateColor"; + break; + case AnimationNodeType::TRANSITIONFILTER: + sServiceName = "com.sun.star.animations.TransitionFilter"; + break; + case AnimationNodeType::ANIMATEMOTION: + sServiceName = "com.sun.star.animations.AnimateMotion"; + break; + case AnimationNodeType::ANIMATETRANSFORM: + sServiceName = "com.sun.star.animations.AnimateTransform"; + break; + case AnimationNodeType::COMMAND: + sServiceName = "com.sun.star.animations.Command"; + break; + case AnimationNodeType::SET: + sServiceName = "com.sun.star.animations.AnimateSet"; + break; + case AnimationNodeType::AUDIO: + sServiceName = "com.sun.star.animations.Audio"; + break; + default: + SAL_INFO("oox.ppt","OOX: unhandled type " << nNodeType ); + break; + } + return sServiceName; + } + + TimeNode::TimeNode( sal_Int16 nNodeType ) + : mnNodeType( nNodeType ) + , mbHasEndSyncValue( false ) + { + } + + TimeNode::~TimeNode() + { + } + + void fixMainSequenceTiming( const css::uno::Reference< css::animations::XAnimationNode >& xNode ) + { + try + { + bool bFirst = true; + Reference< XEnumerationAccess > xEA( xNode, UNO_QUERY_THROW ); + Reference< XEnumeration > xE( xEA->createEnumeration(), UNO_SET_THROW ); + while( xE->hasMoreElements() ) + { + // click node + Reference< XAnimationNode > xClickNode( xE->nextElement(), UNO_QUERY ); + + Event aEvent; + aEvent.Trigger = EventTrigger::ON_NEXT; + aEvent.Repeat = 0; + xClickNode->setBegin( Any( aEvent ) ); + + if( bFirst ) + { + bFirst = false; + Reference< XEnumerationAccess > xEA2( xClickNode, UNO_QUERY_THROW ); + Reference< XEnumeration > xE2( xEA2->createEnumeration(), UNO_SET_THROW ); + if( xE2->hasMoreElements() ) + { + // with node + xE2->nextElement() >>= xEA2; + if( xEA2.is() ) + xE2 = xEA2->createEnumeration(); + else + xE2.clear(); + + if( xE2.is() && xE2->hasMoreElements() ) + { + Reference< XAnimationNode > xEffectNode( xE2->nextElement(), UNO_QUERY_THROW ); + const Sequence< NamedValue > aUserData( xEffectNode->getUserData() ); + for( const NamedValue& rProp : aUserData ) + { + if ( rProp.Name == "node-type" ) + { + sal_Int16 nNodeType = 0; + rProp.Value >>= nNodeType; + if( nNodeType != css::presentation::EffectNodeType::ON_CLICK ) + { + // first effect does not start on click, so correct + // first click nodes begin to 0s + xClickNode->setBegin( Any( 0.0 ) ); + break; + } + } + } + } + } + } + } + } + catch( Exception& ) + { + SAL_INFO("oox.ppt","fixMainSequenceTiming(), exception caught!" ); + } + } + + void fixInteractiveSequenceTiming( const css::uno::Reference< css::animations::XAnimationNode >& xNode ) + { + try + { + Any aBegin( xNode->getBegin() ); + Any aEmpty; + xNode->setBegin( aEmpty ); + + Reference< XEnumerationAccess > xEA( xNode, UNO_QUERY_THROW ); + Reference< XEnumeration > xE( xEA->createEnumeration(), UNO_SET_THROW ); + while( xE->hasMoreElements() ) + { + // click node + Reference< XAnimationNode > xClickNode( xE->nextElement(), UNO_QUERY ); + xClickNode->setBegin( aBegin ); + } + } + catch( Exception& ) + { + SAL_INFO("oox.ppt","fixInteractiveSequenceTiming(), exception caught!" ); + } + } + + void TimeNode::addNode( const XmlFilterBase& rFilter, const Reference< XAnimationNode >& rxNode, const SlidePersistPtr & pSlide ) + { + try { + sal_Int16 nNodeType = mnNodeType; + + if (mnNodeType == AnimationNodeType::PAR && maNodeProperties[NP_ITERATETYPE].hasValue()) + nNodeType = AnimationNodeType::ITERATE; + + OUString sServiceName = getServiceName(nNodeType); + + Reference< XAnimationNode > xNode = createAndInsert( rFilter, sServiceName, rxNode ); + if (!xNode) + return; + setNode(rFilter, xNode, pSlide, rxNode); + } + catch( const Exception& ) + { + TOOLS_INFO_EXCEPTION("oox.ppt","OOX: exception raised in TimeNode::addNode()" ); + } + } + + void TimeNode::setNode(const XmlFilterBase& rFilter, const Reference< XAnimationNode >& xNode, const SlidePersistPtr & pSlide, const Reference<XAnimationNode>& xParent) + { + SAL_WARN_IF( !xNode.is(), "oox.ppt", "null node passed" ); + + try { + if( !msId.isEmpty() ) + { + pSlide->getAnimNodesMap()[ msId ] = xNode; + } + + if( mpTarget ) + { + sal_Int16 nSubItem(0); + maNodeProperties[ NP_TARGET ] = mpTarget->convert( pSlide, nSubItem ); + if( mpTarget->mnType == XML_spTgt ) + { + if ( xNode->getType() == AnimationNodeType::ANIMATE || + xNode->getType() == AnimationNodeType::ITERATE ) + { + maNodeProperties[ NP_SUBITEM ] <<= nSubItem; + } + else + lcl_setAncestorSubItem( xParent, nSubItem ); + } + } + + if( !maStCondList.empty() ) + { + Any aAny = AnimationCondition::convertList( pSlide, maStCondList ); + if( aAny.hasValue() ) + { + xNode->setBegin( aAny ); + } + + } + if( !maEndCondList.empty() ) + { + Any aAny = AnimationCondition::convertList( pSlide, maEndCondList ); + if( aAny.hasValue() ) + { + xNode->setEnd( aAny ); + } + } + if( mbHasEndSyncValue ) + { + Any aValue = maEndSyncValue.convert( pSlide ); + xNode->setEndSync(aValue); + } + + if( !maUserData.empty() ) + { + Sequence< NamedValue > aUserDataSeq( static_cast< sal_Int32 >( maUserData.size() ) ); + NamedValue* pValues = aUserDataSeq.getArray(); + for (auto const& elem : maUserData) + { + pValues->Name = elem.first; + pValues->Value = elem.second; + ++pValues; + } + maNodeProperties[ NP_USERDATA ] <<= aUserDataSeq; + } + + Reference< XAnimate > xAnimate( xNode, UNO_QUERY ); + Reference< XAnimateColor > xAnimateColor( xNode, UNO_QUERY ); + Reference< XAnimateMotion > xAnimateMotion( xNode, UNO_QUERY ); + Reference< XAnimateTransform > xAnimateTransform( xNode, UNO_QUERY ); + Reference< XCommand > xCommand( xNode, UNO_QUERY ); + Reference< XAudio > xAudio( xNode, UNO_QUERY ); + Reference< XIterateContainer > xIterateContainer( xNode, UNO_QUERY ); + sal_Int16 nInt16 = 0; + bool bBool = false; + double fDouble = 0; + OUString sString; + Sequence< NamedValue > aSeq; + + for( int i = 0; i < NP_SIZE_; i++) + { + Any & aValue( maNodeProperties[ i ] ); + if( aValue.hasValue() ) + { + switch( i ) + { + case NP_TO: + if( xAnimate.is() ) + xAnimate->setTo( aValue ); + break; + case NP_FROM: + if( xAnimate.is() ) + xAnimate->setFrom( aValue ); + break; + case NP_BY: + if( xAnimate.is() ) + xAnimate->setBy( aValue ); + break; + case NP_HIDEDURINGSHOW: + if (xAudio.is() && (aValue >>= bBool)) + { + xAudio->setHideDuringShow(bBool); + } + break; + case NP_ISNARRATION: + if (xAudio.is() && (aValue >>= bBool)) + { + xAudio->setNarration(bBool); + } + break; + case NP_TARGET: + + if (xParent.is() && xParent->getType() == AnimationNodeType::ITERATE) + { + Reference<XIterateContainer> xParentContainer(xParent, UNO_QUERY); + if (xParentContainer.is()) + xParentContainer->setTarget(aValue); + } + else + { + if (xAnimate.is()) + xAnimate->setTarget(aValue); + if (xCommand.is()) + xCommand->setTarget(aValue); + if (xAudio.is()) + xAudio->setSource(aValue); + } + break; + case NP_SUBITEM: + if( aValue >>= nInt16 ) + { + if( xAnimate.is() ) + { + xAnimate->setSubItem( nInt16 ); + } + else if ( xIterateContainer.is() ) + { + xIterateContainer->setSubItem( nInt16 ); + } + } + else + { + SAL_INFO("oox.ppt","any >>= failed " << __LINE__ ); + } + break; + case NP_ATTRIBUTENAME: + if( xAnimate.is() ) + { + if( aValue >>= sString ) + xAnimate->setAttributeName( sString ); + else + { + SAL_INFO("oox.ppt","any >>= failed " << __LINE__ ); + } + } + break; + case NP_CALCMODE: + if( xAnimate.is() ) + { + if( aValue >>= nInt16 ) + xAnimate->setCalcMode( nInt16 ); + else + { + SAL_INFO("oox.ppt","any >>= failed " << __LINE__ ); + } + } + break; + case NP_KEYTIMES: + if( xAnimate.is() ) + { + Sequence<double> aKeyTimes; + if( aValue >>= aKeyTimes ) + xAnimate->setKeyTimes(aKeyTimes); + else + { + SAL_INFO("oox.ppt","any >>= failed " << __LINE__ ); + } + } + break; + case NP_VALUES: + if( xAnimate.is() ) + { + Sequence<Any> aValues; + if( aValue >>= aValues ) + xAnimate->setValues(aValues); + else + { + SAL_INFO("oox.ppt","any >>= failed " << __LINE__ ); + } + } + break; + case NP_FORMULA: + if( xAnimate.is() ) + { + if( aValue >>= sString ) + xAnimate->setFormula(sString); + else + { + SAL_INFO("oox.ppt","any >>= failed " << __LINE__ ); + } + } + break; + case NP_COLORINTERPOLATION: + if( xAnimateColor.is() ) + { + if( aValue >>= nInt16 ) + xAnimateColor->setColorInterpolation( nInt16 ); + else + { + SAL_INFO("oox.ppt","any >>= failed " << __LINE__ ); + } + } + break; + case NP_DIRECTION: + if( xAnimateColor.is() ) + { + if( aValue >>= bBool ) + xAnimateColor->setDirection( bBool ); + else + { + SAL_INFO("oox.ppt","any >>= failed " << __LINE__ ); + } + } + break; + case NP_PATH: + if( xAnimateMotion.is() ) + xAnimateMotion->setPath( aValue ); + break; + case NP_TRANSFORMTYPE: + if( xAnimateTransform.is() ) + { + if( aValue >>= nInt16 ) + xAnimateTransform->setTransformType( nInt16 ); + else + { + SAL_INFO("oox.ppt","any >>= failed " << __LINE__ ); + } + } + break; + case NP_USERDATA: + if( aValue >>= aSeq ) + xNode->setUserData( aSeq ); + else + { + SAL_INFO("oox.ppt","any >>= failed " << __LINE__ ); + } + break; + case NP_ACCELERATION: + if( aValue >>= fDouble ) + xNode->setAcceleration( fDouble ); + else + { + SAL_INFO("oox.ppt","any >>= failed " << __LINE__ ); + } + break; + case NP_DECELERATE: + if( aValue >>= fDouble ) + xNode->setDecelerate( fDouble ); + else + { + SAL_INFO("oox.ppt","any >>= failed " << __LINE__ ); + } + break; + case NP_AUTOREVERSE: + if( aValue >>= bBool ) + xNode->setAutoReverse( bBool ); + else + { + SAL_INFO("oox.ppt","any >>= failed " << __LINE__ ); + } + break; + case NP_DURATION: + xNode->setDuration( aValue ); + break; + case NP_FILL: + if( aValue >>= nInt16 ) + xNode->setFill( nInt16 ); + else + { + SAL_INFO("oox.ppt","any >>= failed " << __LINE__ ); + } + break; + case NP_REPEATCOUNT: + xNode->setRepeatCount( aValue ); + break; + case NP_REPEATDURATION: + xNode->setRepeatDuration( aValue ); + break; + case NP_RESTART: + if( aValue >>= nInt16 ) + xNode->setRestart( nInt16 ); + else + { + SAL_INFO("oox.ppt","any >>= failed " << __LINE__ ); + } + break; + case NP_COMMAND: + if( xCommand.is() ) + { + if( aValue >>= nInt16 ) + xCommand->setCommand( nInt16 ); + else + { + SAL_INFO("oox.ppt","any >>= failed " << __LINE__ ); + } + } + break; + case NP_PARAMETER: + if( xCommand.is() ) + xCommand->setParameter( aValue ); + break; + case NP_ITERATETYPE: + if( xIterateContainer.is() ) + { + if( aValue >>= nInt16 ) + xIterateContainer->setIterateType( nInt16 ); + else + { + SAL_INFO("oox.ppt","any >>= failed " << __LINE__ ); + } + } + break; + case NP_ITERATEINTERVAL: + if( xIterateContainer.is() ) + { + if( aValue >>= fDouble ) + xIterateContainer->setIterateInterval( fDouble ); + else + { + SAL_INFO("oox.ppt","any >>= failed " << __LINE__ ); + } + } + break; + default: + SAL_INFO("oox.ppt","ERR-OOX: unknown prop index " << i ); + break; + } + } + } + + if (xAnimate.is() && xAnimate->getValues().getLength() != xAnimate->getKeyTimes().getLength()) + throw css::io::WrongFormatException(); + + if( mnNodeType == AnimationNodeType::TRANSITIONFILTER ) + { + + Reference< XTransitionFilter > xFilter( xNode, UNO_QUERY ); + maTransitionFilter.setTransitionFilterProperties( xFilter ); + } + + std::for_each( + maChildren.begin(), maChildren.end(), + [&rFilter, &xNode, &pSlide] (TimeNodePtr const & child) { + child->addNode(rFilter, xNode, pSlide); + } ); + + switch( mnNodeType ) + { + case AnimationNodeType::SEQ: + { + sal_Int16 nEnum = 0; + if( maUserData[ "node-type" ] >>= nEnum ) + { + if( nEnum == EffectNodeType::MAIN_SEQUENCE ) + { + fixMainSequenceTiming( xNode ); + } + else if( nEnum == EffectNodeType::INTERACTIVE_SEQUENCE ) + { + fixInteractiveSequenceTiming( xNode ); + } + } + break; + } + case AnimationNodeType::PAR: + // some other cut&paste... from AnimationImporter::importAnimationContainer() + break; + } + } + catch( const Exception& ) + { + TOOLS_INFO_EXCEPTION("oox.ppt","OOX: exception raised in TimeNode::setNode()"); + } + } + + Reference< XAnimationNode > TimeNode::createAndInsert( + const XmlFilterBase& rFilter, + const OUString& rServiceName, + const Reference< XAnimationNode >& rxNode ) + { + try { + Reference< XAnimationNode > xNode( Reference<css::lang::XMultiServiceFactory>(rFilter.getComponentContext()->getServiceManager(), UNO_QUERY_THROW)->createInstance( rServiceName ), UNO_QUERY_THROW ); + Reference< XTimeContainer > xParentContainer( rxNode, UNO_QUERY_THROW ); + + xParentContainer->appendChild( xNode ); + return xNode; + } + catch( const Exception& ) + { + TOOLS_INFO_EXCEPTION("oox.ppt", "OOX: exception raised in TimeNode::createAndInsert() trying to create a service " << rServiceName); + } + + return Reference< XAnimationNode >(); + } + + void TimeNode::setId( sal_Int32 nId ) + { + msId = OUString::number(nId); + } + + void TimeNode::setTo( const Any & aTo ) + { + maNodeProperties[ NP_TO ] = aTo; + } + + void TimeNode::setFrom( const Any & aFrom ) + { + maNodeProperties[ NP_FROM ] = aFrom; + } + + void TimeNode::setBy( const Any & aBy ) + { + maNodeProperties[ NP_BY ] = aBy; + } + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |