blob: 1aa5e5f977903046043d3f051b25700d9b6b621d [file] [log] [blame]
/**************************************************************
*
* 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
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*************************************************************/
#include "oox/ppt/timenodelistcontext.hxx"
#include "comphelper/anytostring.hxx"
#include "cppuhelper/exc_hlp.hxx"
#include <osl/diagnose.h>
#include <rtl/math.hxx>
#include <com/sun/star/animations/XTimeContainer.hpp>
#include <com/sun/star/animations/XAnimationNode.hpp>
#include <com/sun/star/animations/XAnimateColor.hpp>
#include <com/sun/star/animations/XAnimateSet.hpp>
#include <com/sun/star/animations/XAnimateTransform.hpp>
#include <com/sun/star/animations/AnimationTransformType.hpp>
#include <com/sun/star/animations/AnimationCalcMode.hpp>
#include <com/sun/star/animations/AnimationColorSpace.hpp>
#include <com/sun/star/animations/AnimationNodeType.hpp>
#include <com/sun/star/animations/XCommand.hpp>
#include <com/sun/star/lang/XMultiServiceFactory.hpp>
#include <com/sun/star/presentation/EffectCommands.hpp>
#include <com/sun/star/beans/NamedValue.hpp>
#include "oox/helper/attributelist.hxx"
#include "oox/core/xmlfilterbase.hxx"
#include "oox/drawingml/drawingmltypes.hxx"
#include "oox/drawingml/colorchoicecontext.hxx"
#include "oox/ppt/slidetransition.hxx"
#include "animvariantcontext.hxx"
#include "commonbehaviorcontext.hxx"
#include "conditioncontext.hxx"
#include "commontimenodecontext.hxx"
#include "timeanimvaluecontext.hxx"
#include "animationtypes.hxx"
using namespace ::oox::core;
using namespace ::oox::drawingml;
using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::lang;
using namespace ::com::sun::star::animations;
using namespace ::com::sun::star::presentation;
using namespace ::com::sun::star::xml::sax;
using namespace ::com::sun::star::awt;
using ::com::sun::star::beans::NamedValue;
using ::rtl::OUString;
namespace oox { namespace ppt {
struct AnimColor
{
AnimColor(sal_Int16 cs, sal_Int32 o, sal_Int32 t, sal_Int32 th )
: colorSpace( cs ), one( o ), two( t ), three( th )
{
}
Any get()
{
sal_Int32 nColor;
Sequence< double > aHSL( 3 );
Any aColor;
switch( colorSpace )
{
case AnimationColorSpace::HSL:
aHSL[ 0 ] = double(one) / 100000;
aHSL[ 1 ] = double(two) / 100000;
aHSL[ 2 ] = double(three) / 100000;
aColor = Any(aHSL);
break;
case AnimationColorSpace::RGB:
nColor = ( ( ( one * 128 ) / 1000 ) & 0xff ) << 16
| ( ( ( two * 128 ) / 1000 ) & 0xff ) << 8
| ( ( ( three * 128 ) / 1000 ) & 0xff );
aColor = Any(nColor);
break;
default:
nColor = 0;
aColor = Any( nColor );
break;
}
return aColor;
}
sal_Int16 colorSpace;
sal_Int32 one;
sal_Int32 two;
sal_Int32 three;
};
/** CT_TLMediaNodeAudio
CT_TLMediaNodeVideo */
class MediaNodeContext
: public TimeNodeContext
{
public:
MediaNodeContext( ContextHandler& rParent, sal_Int32 aElement,
const Reference< XFastAttributeList >& xAttribs,
const TimeNodePtr & pNode )
: TimeNodeContext( rParent, aElement, xAttribs, pNode )
, mbIsNarration( false )
, mbFullScrn( false )
{
AttributeList attribs( xAttribs );
switch( aElement )
{
case PPT_TOKEN( audio ):
mbIsNarration = attribs.getBool( XML_isNarration, false );
break;
case PPT_TOKEN( video ):
mbFullScrn = attribs.getBool( XML_fullScrn, false );
break;
default:
break;
}
}
virtual void SAL_CALL endFastElement( sal_Int32 aElement )
throw ( SAXException, RuntimeException)
{
if( aElement == PPT_TOKEN( audio ) )
{
// TODO deal with mbIsNarration
}
else if( aElement == PPT_TOKEN( video ) )
{
// TODO deal with mbFullScrn
}
}
virtual Reference< XFastContextHandler > SAL_CALL createFastChildContext( ::sal_Int32 aElementToken,
const Reference< XFastAttributeList >& xAttribs )
throw ( SAXException, RuntimeException )
{
Reference< XFastContextHandler > xRet;
switch ( aElementToken )
{
case PPT_TOKEN( cBhvr ):
xRet.set( new CommonBehaviorContext ( *this, xAttribs, mpNode ) );
break;
default:
break;
}
if( !xRet.is() )
xRet.set( this );
return xRet;
}
private:
bool mbIsNarration;
bool mbFullScrn;
};
/** CT_TLSetBehavior
*/
class SetTimeNodeContext
: public TimeNodeContext
{
public:
SetTimeNodeContext( ContextHandler& rParent, sal_Int32 aElement,
const Reference< XFastAttributeList >& xAttribs,
const TimeNodePtr & pNode )
: TimeNodeContext( rParent, aElement, xAttribs, pNode )
{
}
~SetTimeNodeContext() throw ()
{
if( maTo.hasValue() )
{
// TODO
// HACK !!! discard and refactor
OUString aString;
if( maTo >>= aString )
{
OSL_TRACE( "Magic conversion %s", OUSTRING_TO_CSTR( aString ) );
maTo = makeAny( aString.equalsAscii( "visible" ) ? sal_True : sal_False );
if( !maTo.has<sal_Bool>() )
OSL_TRACE( "conversion failed" );
}
mpNode->setTo( maTo );
}
}
virtual void SAL_CALL endFastElement( sal_Int32 /*aElement*/ )
throw ( SAXException, RuntimeException)
{
}
virtual Reference< XFastContextHandler > SAL_CALL createFastChildContext( ::sal_Int32 aElementToken,
const Reference< XFastAttributeList >& xAttribs )
throw ( SAXException, RuntimeException )
{
Reference< XFastContextHandler > xRet;
switch ( aElementToken )
{
case PPT_TOKEN( cBhvr ):
xRet.set( new CommonBehaviorContext ( *this, xAttribs, mpNode ) );
break;
case PPT_TOKEN( to ):
// CT_TLAnimVariant
xRet.set( new AnimVariantContext( *this, aElementToken, maTo ) );
break;
default:
break;
}
if( !xRet.is() )
xRet.set( this );
return xRet;
}
private:
Any maTo;
};
/** CT_TLCommandBehavior
*/
class CmdTimeNodeContext
: public TimeNodeContext
{
public:
CmdTimeNodeContext( ContextHandler& rParent, sal_Int32 aElement,
const Reference< XFastAttributeList >& xAttribs,
const TimeNodePtr & pNode )
: TimeNodeContext( rParent, aElement, xAttribs, pNode )
, maType(0)
{
switch ( aElement )
{
case PPT_TOKEN( cmd ):
msCommand = xAttribs->getOptionalValue( XML_cmd );
maType = xAttribs->getOptionalValueToken( XML_type, 0 );
break;
default:
break;
}
}
~CmdTimeNodeContext() throw ()
{
}
virtual void SAL_CALL endFastElement( sal_Int32 aElement )
throw ( SAXException, RuntimeException)
{
if( aElement == PPT_TOKEN( cmd ) )
{
try {
// see sd/source/filter/ppt/pptinanimations.cxx
// in AnimationImporter::importCommandContainer()
// REFACTOR?
// a good chunk of this code has been copied verbatim *sigh*
sal_Int16 nCommand = EffectCommands::CUSTOM;
NamedValue aParamValue;
switch( maType )
{
case XML_verb:
aParamValue.Name = OUString(RTL_CONSTASCII_USTRINGPARAM("Verb"));
// TODO make sure msCommand has what we want
aParamValue.Value <<= msCommand.toInt32();
nCommand = EffectCommands::VERB;
break;
case XML_evt:
case XML_call:
if( msCommand.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "onstopaudio" ) ) )
{
nCommand = EffectCommands::STOPAUDIO;
}
else if( msCommand.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("play") ) )
{
nCommand = EffectCommands::PLAY;
}
else if( msCommand.compareToAscii( RTL_CONSTASCII_STRINGPARAM("playFrom") ) == 0 )
{
const OUString aMediaTime( msCommand.copy( 9, msCommand.getLength() - 10 ) );
rtl_math_ConversionStatus eStatus;
double fMediaTime = ::rtl::math::stringToDouble( aMediaTime, (sal_Unicode)('.'), (sal_Unicode)(','), &eStatus, NULL );
if( eStatus == rtl_math_ConversionStatus_Ok )
{
aParamValue.Name = CREATE_OUSTRING("MediaTime");
aParamValue.Value <<= fMediaTime;
}
nCommand = EffectCommands::PLAY;
}
else if( msCommand.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("togglePause") ) )
{
nCommand = EffectCommands::TOGGLEPAUSE;
}
else if( msCommand.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("stop") ) )
{
nCommand = EffectCommands::STOP;
}
break;
}
mpNode->getNodeProperties()[ NP_COMMAND ] = makeAny((sal_Int16)nCommand);
if( nCommand == EffectCommands::CUSTOM )
{
OSL_TRACE("OOX: CmdTimeNodeContext::endFastElement(), unknown command!");
aParamValue.Name = CREATE_OUSTRING("UserDefined");
aParamValue.Value <<= msCommand;
}
if( aParamValue.Value.hasValue() )
{
Sequence< NamedValue > aParamSeq( &aParamValue, 1 );
mpNode->getNodeProperties()[ NP_PARAMETER ] = makeAny( aParamSeq );
}
}
catch( RuntimeException& )
{
OSL_TRACE( "OOX: Exception in CmdTimeNodeContext::endFastElement()" );
}
}
}
virtual Reference< XFastContextHandler > SAL_CALL createFastChildContext( ::sal_Int32 aElementToken,
const Reference< XFastAttributeList >& xAttribs )
throw ( SAXException, RuntimeException )
{
Reference< XFastContextHandler > xRet;
switch ( aElementToken )
{
case PPT_TOKEN( cBhvr ):
xRet.set( new CommonBehaviorContext ( *this, xAttribs, mpNode ) );
break;
default:
break;
}
if( !xRet.is() )
xRet.set( this );
return xRet;
}
private:
OUString msCommand;
sal_Int32 maType;
};
/** CT_TLTimeNodeSequence
*/
class SequenceTimeNodeContext
: public TimeNodeContext
{
public:
SequenceTimeNodeContext( ContextHandler& rParent, sal_Int32 aElement,
const Reference< XFastAttributeList >& xAttribs,
const TimeNodePtr & pNode )
: TimeNodeContext( rParent, aElement, xAttribs, pNode )
, mnNextAc(0)
, mnPrevAc(0)
{
AttributeList attribs(xAttribs);
mbConcurrent = attribs.getBool( XML_concurrent, false );
// ST_TLNextActionType { none, seek }
mnNextAc = xAttribs->getOptionalValueToken( XML_nextAc, 0 );
// ST_TLPreviousActionType { none, skipTimed }
mnPrevAc = xAttribs->getOptionalValueToken( XML_prevAc, 0 );
}
~SequenceTimeNodeContext() throw()
{
}
virtual Reference< XFastContextHandler > SAL_CALL createFastChildContext( ::sal_Int32 aElementToken,
const Reference< XFastAttributeList >& xAttribs )
throw ( SAXException, RuntimeException )
{
Reference< XFastContextHandler > xRet;
switch ( aElementToken )
{
case PPT_TOKEN( cTn ):
xRet.set( new CommonTimeNodeContext( *this, aElementToken, xAttribs, mpNode ) );
break;
case PPT_TOKEN( nextCondLst ):
xRet.set( new CondListContext( *this, aElementToken, xAttribs, mpNode,
mpNode->getNextCondition() ) );
break;
case PPT_TOKEN( prevCondLst ):
xRet.set( new CondListContext( *this, aElementToken, xAttribs, mpNode,
mpNode->getPrevCondition() ) );
break;
default:
break;
}
if( !xRet.is() )
xRet.set( this );
return xRet;
}
private:
bool mbConcurrent;
sal_Int32 mnNextAc, mnPrevAc;
};
/** CT_TLTimeNodeParallel
* CT_TLTimeNodeExclusive
*/
class ParallelExclTimeNodeContext
: public TimeNodeContext
{
public:
ParallelExclTimeNodeContext( ContextHandler& rParent, sal_Int32 aElement,
const Reference< XFastAttributeList >& xAttribs,
const TimeNodePtr & pNode )
: TimeNodeContext( rParent, aElement, xAttribs, pNode )
{
}
virtual Reference< XFastContextHandler > SAL_CALL createFastChildContext( ::sal_Int32 aElementToken,
const Reference< XFastAttributeList >& xAttribs )
throw ( SAXException, RuntimeException )
{
Reference< XFastContextHandler > xRet;
switch ( aElementToken )
{
case PPT_TOKEN( cTn ):
xRet.set( new CommonTimeNodeContext( *this, aElementToken, xAttribs, mpNode ) );
break;
default:
break;
}
if( !xRet.is() )
xRet.set( this );
return xRet;
}
protected:
};
/** CT_TLAnimateColorBehavior */
class AnimColorContext
: public TimeNodeContext
{
public:
AnimColorContext( ContextHandler& rParent, sal_Int32 aElement,
const Reference< XFastAttributeList >& xAttribs,
const TimeNodePtr & pNode ) throw()
: TimeNodeContext( rParent, aElement, xAttribs, pNode )
// ST_TLAnimateColorSpace ( XML_rgb, XML_hsl }
, mnColorSpace( xAttribs->getOptionalValueToken( XML_clrSpc, 0 ) )
// ST_TLAnimateColorDirection { XML_cw, XML_ccw }
, mnDir( xAttribs->getOptionalValueToken( XML_dir, 0 ) )
, mbHasByColor( false )
, m_byColor( AnimationColorSpace::RGB, 0, 0, 0)
{
}
~AnimColorContext() throw()
{
}
virtual void SAL_CALL endFastElement( sal_Int32 aElement ) throw ( SAXException, RuntimeException)
{
//xParentNode
if( aElement == mnElement )
{
NodePropertyMap & pProps(mpNode->getNodeProperties());
pProps[ NP_DIRECTION ] = makeAny( mnDir == XML_cw );
pProps[ NP_COLORINTERPOLATION ] = makeAny( mnColorSpace == XML_hsl ? AnimationColorSpace::HSL : AnimationColorSpace::RGB );
const GraphicHelper& rGraphicHelper = getFilter().getGraphicHelper();
if( maToClr.isUsed() )
mpNode->setTo( Any( maToClr.getColor( rGraphicHelper ) ) );
if( maFromClr.isUsed() )
mpNode->setFrom( Any( maFromClr.getColor( rGraphicHelper ) ) );
if( mbHasByColor )
mpNode->setBy( m_byColor.get() );
}
}
virtual Reference< XFastContextHandler > SAL_CALL createFastChildContext( ::sal_Int32 aElementToken, const Reference< XFastAttributeList >& xAttribs ) throw ( SAXException, RuntimeException )
{
Reference< XFastContextHandler > xRet;
switch ( aElementToken )
{
case PPT_TOKEN( hsl ):
// CT_TLByHslColorTransform
{
if( mbHasByColor )
{
m_byColor.colorSpace = AnimationColorSpace::HSL;
m_byColor.one = xAttribs->getOptionalValue( XML_h ).toInt32( );
m_byColor.two = xAttribs->getOptionalValue( XML_s ).toInt32( );
m_byColor.three = xAttribs->getOptionalValue( XML_l ).toInt32( );
}
xRet.set(this);
break;
}
case PPT_TOKEN( rgb ):
{
if( mbHasByColor )
{
// CT_TLByRgbColorTransform
m_byColor.colorSpace = AnimationColorSpace::RGB;
m_byColor.one = xAttribs->getOptionalValue( XML_r ).toInt32();
m_byColor.two = xAttribs->getOptionalValue( XML_g ).toInt32();
m_byColor.three = xAttribs->getOptionalValue( XML_b ).toInt32();
}
xRet.set(this);
break;
}
case PPT_TOKEN( by ):
// CT_TLByAnimateColorTransform
mbHasByColor = true;
xRet.set(this);
break;
case PPT_TOKEN( cBhvr ):
xRet.set( new CommonBehaviorContext ( *this, xAttribs, mpNode ) );
break;
case PPT_TOKEN( to ):
// CT_Color
xRet.set( new ColorContext( *this, maToClr ) );
break;
case PPT_TOKEN( from ):
// CT_Color
xRet.set( new ColorContext( *this, maFromClr ) );
break;
default:
break;
}
if( !xRet.is() )
xRet.set( this );
return xRet;
}
private:
sal_Int32 mnColorSpace;
sal_Int32 mnDir;
bool mbHasByColor;
AnimColor m_byColor;
oox::drawingml::Color maToClr;
oox::drawingml::Color maFromClr;
};
/** CT_TLAnimateBehavior */
class AnimContext
: public TimeNodeContext
{
public:
AnimContext( ContextHandler& rParent, sal_Int32 aElement,
const Reference< XFastAttributeList >& xAttribs,
const TimeNodePtr & pNode ) throw()
: TimeNodeContext( rParent, aElement, xAttribs, pNode )
{
NodePropertyMap & aProps( pNode->getNodeProperties() );
sal_Int32 nCalcMode = xAttribs->getOptionalValueToken( XML_calcmode, 0 );
if(nCalcMode)
{
sal_Int16 nEnum = 0;
switch(nCalcMode)
{
case XML_discrete:
nEnum = AnimationCalcMode::DISCRETE;
break;
case XML_lin:
nEnum = AnimationCalcMode::LINEAR;
break;
case XML_fmla:
default:
// TODO what value is good ?
nEnum = AnimationCalcMode::DISCRETE;
break;
}
aProps[ NP_CALCMODE ] = makeAny(nEnum);
}
OUString aStr;
aStr = xAttribs->getOptionalValue( XML_from );
if( aStr.getLength() )
{
pNode->setFrom( makeAny( aStr ) );
}
aStr = xAttribs->getOptionalValue( XML_by );
if( aStr.getLength() )
{
pNode->setBy( makeAny( aStr ) );
}
aStr = xAttribs->getOptionalValue( XML_to );
if( aStr.getLength() )
{
pNode->setTo( makeAny( aStr ) );
}
mnValueType = xAttribs->getOptionalValueToken( XML_valueType, 0 );
}
~AnimContext() throw ()
{
::std::list< TimeAnimationValue >::iterator iter, end;
int nKeyTimes = maTavList.size();
if( nKeyTimes > 0)
{
int i;
Sequence< double > aKeyTimes( nKeyTimes );
Sequence< Any > aValues( nKeyTimes );
NodePropertyMap & aProps( mpNode->getNodeProperties() );
end = maTavList.end();
for(iter = maTavList.begin(), i=0; iter != end; iter++,i++)
{
// TODO what to do if it is Timing_INFINITE ?
Any aTime = GetTimeAnimateValueTime( iter->msTime );
aTime >>= aKeyTimes[i];
aValues[i] = iter->maValue;
OUString aTest;
iter->maValue >>= aTest;
if( aTest.getLength() != 0 )
{
aValues[i] = iter->maValue;
}
else
{
aProps[ NP_FORMULA ] <<= iter->msFormula;
}
}
aProps[ NP_VALUES ] <<= aValues;
aProps[ NP_KEYTIMES ] <<= aKeyTimes;
}
}
virtual Reference< XFastContextHandler > SAL_CALL createFastChildContext( ::sal_Int32 aElementToken, const Reference< XFastAttributeList >& xAttribs ) throw ( SAXException, RuntimeException )
{
Reference< XFastContextHandler > xRet;
switch ( aElementToken )
{
case PPT_TOKEN( cBhvr ):
xRet.set( new CommonBehaviorContext ( *this, xAttribs, mpNode ) );
break;
case PPT_TOKEN( tavLst ):
xRet.set( new TimeAnimValueListContext ( *this, xAttribs, maTavList ) );
break;
default:
break;
}
if( !xRet.is() )
xRet.set( this );
return xRet;
}
private:
sal_Int32 mnValueType;
TimeAnimationValueList maTavList;
};
/** CT_TLAnimateScaleBehavior */
class AnimScaleContext
: public TimeNodeContext
{
public:
AnimScaleContext( ContextHandler& rParent, sal_Int32 aElement,
const Reference< XFastAttributeList >& xAttribs,
const TimeNodePtr & pNode ) throw()
: TimeNodeContext( rParent, aElement, xAttribs, pNode )
, mbZoomContents( false )
{
AttributeList attribs( xAttribs );
// TODO what to do with mbZoomContents
mbZoomContents = attribs.getBool( XML_zoomContents, false );
pNode->getNodeProperties()[ NP_TRANSFORMTYPE ]
= makeAny((sal_Int16)AnimationTransformType::SCALE);
}
~AnimScaleContext( ) throw( )
{
}
virtual void SAL_CALL endFastElement( sal_Int32 aElement ) throw ( SAXException, RuntimeException)
{
if( aElement == mnElement )
{
if( maTo.hasValue() )
{
mpNode->setTo( maTo );
}
if( maBy.hasValue() )
{
mpNode->setBy( maBy );
}
if( maFrom.hasValue() )
{
mpNode->setFrom( maFrom );
}
}
}
virtual Reference< XFastContextHandler > SAL_CALL createFastChildContext( ::sal_Int32 aElementToken,
const Reference< XFastAttributeList >& xAttribs )
throw ( SAXException, RuntimeException )
{
Reference< XFastContextHandler > xRet;
switch ( aElementToken )
{
case PPT_TOKEN( cBhvr ):
xRet.set( new CommonBehaviorContext ( *this, xAttribs, mpNode ) );
break;
case PPT_TOKEN( to ):
{
// CT_TLPoint
Point p = GetPointPercent( xAttribs );
maTo <<= p.X;
maTo <<= p.Y;
break;
}
case PPT_TOKEN( from ):
{
// CT_TLPoint
Point p = GetPointPercent( xAttribs );
maFrom <<= p.X;
maFrom <<= p.Y;
break;
}
case PPT_TOKEN( by ):
{
// CT_TLPoint
Point p = GetPointPercent( xAttribs );
maBy <<= p.X;
maBy <<= p.Y;
break;
}
default:
break;
}
if( !xRet.is() )
xRet.set( this );
return xRet;
}
private:
Any maBy;
Any maFrom;
Any maTo;
bool mbZoomContents;
};
/** CT_TLAnimateRotationBehavior */
class AnimRotContext
: public TimeNodeContext
{
public:
AnimRotContext( ContextHandler& rParent, sal_Int32 aElement,
const Reference< XFastAttributeList >& xAttribs,
const TimeNodePtr & pNode ) throw()
: TimeNodeContext( rParent, aElement, xAttribs, pNode )
{
AttributeList attribs( xAttribs );
pNode->getNodeProperties()[ NP_TRANSFORMTYPE ]
= makeAny((sal_Int16)AnimationTransformType::ROTATE);
// TODO make sure the units are OK
if(attribs.hasAttribute( XML_by ) )
{
sal_Int32 nBy = attribs.getInteger( XML_by, 0 );
pNode->setBy( makeAny( (double)nBy ) );
}
if(attribs.hasAttribute( XML_from ) )
{
sal_Int32 nFrom = attribs.getInteger( XML_from, 0 );
pNode->setFrom( makeAny( nFrom ) );
}
if(attribs.hasAttribute( XML_to ) )
{
sal_Int32 nTo = attribs.getInteger( XML_to, 0 );
pNode->setTo( makeAny( nTo ) );
}
}
~AnimRotContext( ) throw( )
{
}
virtual Reference< XFastContextHandler > SAL_CALL createFastChildContext( ::sal_Int32 aElementToken, const Reference< XFastAttributeList >& xAttribs ) throw ( SAXException, RuntimeException )
{
Reference< XFastContextHandler > xRet;
switch ( aElementToken )
{
case PPT_TOKEN( cBhvr ):
xRet.set( new CommonBehaviorContext ( *this, xAttribs, mpNode ) );
break;
default:
break;
}
if( !xRet.is() )
xRet.set( this );
return xRet;
}
};
/** CT_TLAnimateMotionBehavior */
class AnimMotionContext
: public TimeNodeContext
{
public:
AnimMotionContext( ContextHandler& rParent, sal_Int32 aElement,
const Reference< XFastAttributeList >& xAttribs,
const TimeNodePtr & pNode ) throw()
: TimeNodeContext( rParent, aElement, xAttribs, pNode )
{
pNode->getNodeProperties()[ NP_TRANSFORMTYPE ]
= makeAny((sal_Int16)AnimationTransformType::TRANSLATE);
AttributeList attribs( xAttribs );
// ST_TLAnimateMotionBehaviorOrigin { parent, layour }
sal_Int32 nOrigin = xAttribs->getOptionalValueToken( XML_origin, 0 );
if( nOrigin != 0 )
{
switch(nOrigin)
{
case XML_layout:
case XML_parent:
break;
}
// TODO
}
OUString aStr = xAttribs->getOptionalValue( XML_path );
aStr = aStr.replace( 'E', ' ' );
aStr = aStr.trim();
pNode->getNodeProperties()[ NP_PATH ] = makeAny(aStr);
// ST_TLAnimateMotionPathEditMode{ fixed, relative }
mnPathEditMode = xAttribs->getOptionalValueToken( XML_pathEditMode, 0 );
msPtsTypes = xAttribs->getOptionalValue( XML_ptsTypes );
mnAngle = attribs.getInteger( XML_rAng, 0 );
// TODO make sure the units are right. Likely not.
}
~AnimMotionContext( ) throw()
{
}
virtual Reference< XFastContextHandler > SAL_CALL createFastChildContext( ::sal_Int32 aElementToken,
const Reference< XFastAttributeList >& xAttribs )
throw ( SAXException, RuntimeException )
{
Reference< XFastContextHandler > xRet;
switch ( aElementToken )
{
case PPT_TOKEN( cBhvr ):
xRet.set( new CommonBehaviorContext ( *this, xAttribs, mpNode ) );
break;
case PPT_TOKEN( to ):
{
// CT_TLPoint
Point p = GetPointPercent( xAttribs );
Any rAny;
rAny <<= p.X;
rAny <<= p.Y;
mpNode->setTo( rAny );
break;
}
case PPT_TOKEN( from ):
{
// CT_TLPoint
Point p = GetPointPercent( xAttribs );
Any rAny;
rAny <<= p.X;
rAny <<= p.Y;
mpNode->setFrom( rAny );
break;
}
case PPT_TOKEN( by ):
{
// CT_TLPoint
Point p = GetPointPercent( xAttribs );
Any rAny;
rAny <<= p.X;
rAny <<= p.Y;
mpNode->setBy( rAny );
break;
}
case PPT_TOKEN( rCtr ):
{
// CT_TLPoint
Point p = GetPointPercent( xAttribs );
// TODO push
break;
}
default:
break;
}
if( !xRet.is() )
xRet.set( this );
return xRet;
}
private:
OUString msPtsTypes;
sal_Int32 mnPathEditMode;
sal_Int32 mnAngle;
};
/** CT_TLAnimateEffectBehavior */
class AnimEffectContext
: public TimeNodeContext
{
public:
AnimEffectContext( ContextHandler& rParent, sal_Int32 aElement,
const Reference< XFastAttributeList >& xAttribs,
const TimeNodePtr & pNode ) throw()
: TimeNodeContext( rParent, aElement, xAttribs, pNode )
{
sal_Int32 nDir = xAttribs->getOptionalValueToken( XML_transition, 0 );
OUString sFilter = xAttribs->getOptionalValue( XML_filter );
// TODO
// OUString sPrList = xAttribs->getOptionalValue( XML_prLst );
if( sFilter.getLength() )
{
SlideTransition aFilter( sFilter );
aFilter.setMode( nDir == XML_out ? false : true );
pNode->setTransitionFilter( aFilter );
}
}
~AnimEffectContext( ) throw()
{
}
virtual Reference< XFastContextHandler > SAL_CALL createFastChildContext( ::sal_Int32 aElementToken, const Reference< XFastAttributeList >& xAttribs ) throw ( SAXException, RuntimeException )
{
Reference< XFastContextHandler > xRet;
switch ( aElementToken )
{
case PPT_TOKEN( cBhvr ):
xRet.set( new CommonBehaviorContext ( *this, xAttribs, mpNode ) );
break;
case PPT_TOKEN( progress ):
xRet.set( new AnimVariantContext( *this, aElementToken, maProgress ) );
// TODO handle it.
break;
default:
break;
}
if( !xRet.is() )
xRet.set( this );
return xRet;
}
private:
Any maProgress;
OUString msFilter;
OUString msPrList;
};
TimeNodeContext * TimeNodeContext::makeContext(
ContextHandler& rParent, sal_Int32 aElement,
const Reference< XFastAttributeList >& xAttribs,
const TimeNodePtr & pNode )
{
TimeNodeContext *pCtx = NULL;
switch( aElement )
{
case PPT_TOKEN( animClr ):
pCtx = new AnimColorContext( rParent, aElement, xAttribs, pNode );
break;
case PPT_TOKEN( par ):
pCtx = new ParallelExclTimeNodeContext( rParent, aElement, xAttribs, pNode );
break;
case PPT_TOKEN( seq ):
pCtx = new SequenceTimeNodeContext( rParent, aElement, xAttribs, pNode );
break;
case PPT_TOKEN( excl ):
pCtx = new ParallelExclTimeNodeContext( rParent, aElement, xAttribs, pNode );
break;
case PPT_TOKEN( anim ):
pCtx = new AnimContext ( rParent, aElement, xAttribs, pNode );
break;
case PPT_TOKEN( animEffect ):
pCtx = new AnimEffectContext( rParent, aElement, xAttribs, pNode );
break;
case PPT_TOKEN( animMotion ):
pCtx = new AnimMotionContext( rParent, aElement, xAttribs, pNode );
break;
case PPT_TOKEN( animRot ):
pCtx = new AnimRotContext( rParent, aElement, xAttribs, pNode );
break;
case PPT_TOKEN( animScale ):
pCtx = new AnimScaleContext( rParent, aElement, xAttribs, pNode );
break;
case PPT_TOKEN( cmd ):
pCtx = new CmdTimeNodeContext( rParent, aElement, xAttribs, pNode );
break;
case PPT_TOKEN( set ):
pCtx = new SetTimeNodeContext( rParent, aElement, xAttribs, pNode );
break;
case PPT_TOKEN( audio ):
case PPT_TOKEN( video ):
pCtx = new MediaNodeContext( rParent, aElement, xAttribs, pNode );
break;
default:
break;
}
return pCtx;
}
TimeNodeContext::TimeNodeContext( ContextHandler& rParent, sal_Int32 aElement,
const Reference< XFastAttributeList >& /*xAttribs*/,
const TimeNodePtr & pNode ) throw()
: ContextHandler( rParent )
, mnElement( aElement )
, mpNode( pNode )
{
}
TimeNodeContext::~TimeNodeContext( ) throw()
{
}
TimeNodeListContext::TimeNodeListContext( ContextHandler& rParent, TimeNodePtrList & aList )
throw()
: ContextHandler( rParent )
, maList( aList )
{
}
TimeNodeListContext::~TimeNodeListContext( ) throw()
{
}
Reference< XFastContextHandler > SAL_CALL TimeNodeListContext::createFastChildContext( ::sal_Int32 aElementToken, const Reference< XFastAttributeList >& xAttribs ) throw (SAXException, RuntimeException)
{
Reference< XFastContextHandler > xRet;
sal_Int16 nNodeType;
switch( aElementToken )
{
case PPT_TOKEN( par ):
nNodeType = AnimationNodeType::PAR;
break;
case PPT_TOKEN( seq ):
nNodeType = AnimationNodeType::SEQ;
break;
case PPT_TOKEN( excl ):
// TODO pick the right type. We choose parallel for now as
// there does not seem to be an "Exclusive"
nNodeType = AnimationNodeType::PAR;
break;
case PPT_TOKEN( anim ):
nNodeType = AnimationNodeType::ANIMATE;
break;
case PPT_TOKEN( animClr ):
nNodeType = AnimationNodeType::ANIMATECOLOR;
break;
case PPT_TOKEN( animEffect ):
nNodeType = AnimationNodeType::TRANSITIONFILTER;
break;
case PPT_TOKEN( animMotion ):
nNodeType = AnimationNodeType::ANIMATEMOTION;
break;
case PPT_TOKEN( animRot ):
case PPT_TOKEN( animScale ):
nNodeType = AnimationNodeType::ANIMATETRANSFORM;
break;
case PPT_TOKEN( cmd ):
nNodeType = AnimationNodeType::COMMAND;
break;
case PPT_TOKEN( set ):
nNodeType = AnimationNodeType::SET;
break;
case PPT_TOKEN( audio ):
nNodeType = AnimationNodeType::AUDIO;
break;
case PPT_TOKEN( video ):
nNodeType = AnimationNodeType::AUDIO;
OSL_TRACE( "OOX: video requested, gave Audio instead" );
break;
default:
nNodeType = AnimationNodeType::CUSTOM;
OSL_TRACE( "OOX: uhandled token %x", aElementToken );
break;
}
TimeNodePtr pNode(new TimeNode(nNodeType));
maList.push_back( pNode );
ContextHandler * pContext = TimeNodeContext::makeContext( *this, aElementToken, xAttribs, pNode );
xRet.set( pContext ? pContext : this );
return xRet;
}
} }