/**************************************************************
 * 
 * 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.
 * 
 *************************************************************/



// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_sd.hxx"
#include <com/sun/star/presentation/EffectNodeType.hpp>
#include <com/sun/star/presentation/ShapeAnimationSubType.hpp>
#include <com/sun/star/presentation/TextAnimationType.hpp>
#include <com/sun/star/presentation/ParagraphTarget.hpp>
#include <svx/unoshape.hxx>
#include <svx/svdotext.hxx>
#include <svx/svdopath.hxx>
#include "drawdoc.hxx"
#include "sdpage.hxx"
#include <CustomAnimationPreset.hxx>
#include <TransitionPreset.hxx>
#include <EffectMigration.hxx>
#include <anminfo.hxx>

using namespace ::vos;
using namespace ::sd;
using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::animations;
using namespace ::com::sun::star::presentation;

using ::com::sun::star::drawing::XShape;
using ::rtl::OUString;

struct deprecated_FadeEffect_conversion_table_entry
{
	FadeEffect	meFadeEffect;
	const sal_Char* mpPresetId;
}
deprecated_FadeEffect_conversion_table[] =
{
// OOo 1.x transitions
	{ FadeEffect_FADE_FROM_LEFT,			"wipe-right" },
	{ FadeEffect_FADE_FROM_TOP,				"wipe-down" },
	{ FadeEffect_FADE_FROM_RIGHT,			"wipe-left" },
	{ FadeEffect_FADE_FROM_BOTTOM,			"wipe-up" },

	{ FadeEffect_CLOCKWISE,					"wheel-clockwise-1-spoke" },

	{ FadeEffect_UNCOVER_TO_LEFT,			"uncover-left" },
	{ FadeEffect_UNCOVER_TO_UPPERLEFT,		"uncover-left-up" },
	{ FadeEffect_UNCOVER_TO_TOP,			"uncover-up" },
	{ FadeEffect_UNCOVER_TO_UPPERRIGHT,		"uncover-right-up" },
	{ FadeEffect_UNCOVER_TO_RIGHT,			"uncover-right" },
	{ FadeEffect_UNCOVER_TO_LOWERRIGHT,		"uncover-right-down" },
	{ FadeEffect_UNCOVER_TO_BOTTOM,			"uncover-down" },
	{ FadeEffect_UNCOVER_TO_LOWERLEFT,		"uncover-left-down" },

	{ FadeEffect_VERTICAL_LINES,			"random-bars-vertical" },
	{ FadeEffect_HORIZONTAL_LINES,			"random-bars-horizontal" },

	{ FadeEffect_VERTICAL_CHECKERBOARD,		"checkerboard-down" },
	{ FadeEffect_HORIZONTAL_CHECKERBOARD,	"checkerboard-across" },

	{ FadeEffect_FADE_TO_CENTER,			"box-in" },
	{ FadeEffect_FADE_FROM_CENTER,			"box-out" },

	{ FadeEffect_VERTICAL_STRIPES,			"venetian-blinds-vertical" },
	{ FadeEffect_HORIZONTAL_STRIPES,		"venetian-blinds-horizontal" },

	{ FadeEffect_MOVE_FROM_LEFT,			"cover-right" },
	{ FadeEffect_MOVE_FROM_TOP,				"cover-down" },
	{ FadeEffect_MOVE_FROM_RIGHT,			"cover-left" },
	{ FadeEffect_MOVE_FROM_BOTTOM,			"cover-up" },
	{ FadeEffect_MOVE_FROM_UPPERLEFT,		"cover-right-down" },
	{ FadeEffect_MOVE_FROM_UPPERRIGHT,		"cover-left-down" },
	{ FadeEffect_MOVE_FROM_LOWERRIGHT,		"cover-left-up" },
	{ FadeEffect_MOVE_FROM_LOWERLEFT,		"cover-right-up" },

	{ FadeEffect_DISSOLVE,					"dissolve" },

	{ FadeEffect_RANDOM,					"random-transition" },

	{ FadeEffect_ROLL_FROM_LEFT,			"push-right" },
	{ FadeEffect_ROLL_FROM_TOP,				"push-down" },
	{ FadeEffect_ROLL_FROM_RIGHT,			"push-left" },
	{ FadeEffect_ROLL_FROM_BOTTOM,			"push-up" },

	{ FadeEffect_CLOSE_VERTICAL,			"split-horizontal-in" },
	{ FadeEffect_CLOSE_HORIZONTAL,			"split-vertical-in" },
	{ FadeEffect_OPEN_VERTICAL,				"split-horizontal-out" },
	{ FadeEffect_OPEN_HORIZONTAL,			"split-vertical-out" },

	{ FadeEffect_FADE_FROM_UPPERLEFT,		"diagonal-squares-right-down" },
	{ FadeEffect_FADE_FROM_UPPERRIGHT,		"diagonal-squares-left-down" },
	{ FadeEffect_FADE_FROM_LOWERLEFT,		"diagonal-squares-right-up" },
	{ FadeEffect_FADE_FROM_LOWERRIGHT,		"diagonal-squares-left-up" },

// OOo 1.x transitions not in OOo 2.x
	{ FadeEffect_CLOCKWISE,					"clock-wipe-twelve" },
	{ FadeEffect_COUNTERCLOCKWISE,			"reverse-clock-wipe-twelve" },
	{ FadeEffect_SPIRALIN_LEFT,				"spiral-wipe-top-left-clockwise" },
	{ FadeEffect_SPIRALIN_RIGHT,			"spiral-wipe-top-right-counter-clockwise" },
	{ FadeEffect_SPIRALOUT_LEFT,			"spiral-wipe-out-to-bottom-right-clockwise" },
	{ FadeEffect_SPIRALOUT_RIGHT,			"spiral-wipe-out-to-bottom-left-counter-clockwise" },
	{ FadeEffect_WAVYLINE_FROM_LEFT,		"snake-wipe-top-left-vertical" },
	{ FadeEffect_WAVYLINE_FROM_TOP,			"snake-wipe-top-left-horizontal" },
	{ FadeEffect_WAVYLINE_FROM_RIGHT,		"snake-wipe-bottom-right-vertical" },
	{ FadeEffect_WAVYLINE_FROM_BOTTOM,		"snake-wipe-bottom-right-horizontal" },
	{ FadeEffect_STRETCH_FROM_LEFT,			"wipe-right" },	// todo
	{ FadeEffect_STRETCH_FROM_TOP,			"wipe-down" },	// todo
	{ FadeEffect_STRETCH_FROM_RIGHT,		"wipe-left" },	// todo
	{ FadeEffect_STRETCH_FROM_BOTTOM,		"wipe-up" },	// todo

// OOo 1.x not available transitions

	{ FadeEffect_CLOCKWISE,					"wheel-clockwise-2-spokes" },
	{ FadeEffect_CLOCKWISE,					"wheel-clockwise-3-spokes" },
	{ FadeEffect_CLOCKWISE,					"wheel-clockwise-4-spokes" },
	{ FadeEffect_CLOCKWISE,					"wheel-clockwise-8-spokes" },

	{ FadeEffect_FADE_FROM_CENTER,			"shape-circle" },
	{ FadeEffect_FADE_FROM_CENTER,			"shape-diamond" },
	{ FadeEffect_FADE_FROM_CENTER,			"shape-plus" },

	{ FadeEffect_CLOCKWISE,					"wedge" },

	{ FadeEffect_DISSOLVE,					"fade-through-black" },

	{ FadeEffect_CLOCKWISE,					"zoom-rotate-in" },

	{ FadeEffect_HORIZONTAL_LINES,			"comb-horizontal" },
	{ FadeEffect_VERTICAL_LINES,			"comb-vertical" },

	{ FadeEffect_DISSOLVE,					"fade-smoothly" },

	{ FadeEffect_NONE, 0 }
};

/* todo
cut                             cut                                 (same as NONE?)
cut-through-black               cut         toBlack
wedge                           wedge
*/

void EffectMigration::SetFadeEffect( SdPage* pPage, ::com::sun::star::presentation::FadeEffect eNewEffect)
{
	deprecated_FadeEffect_conversion_table_entry* pEntry = deprecated_FadeEffect_conversion_table;
	while( (pEntry->meFadeEffect != FadeEffect_NONE) && (pEntry->meFadeEffect != eNewEffect) )
		pEntry++;

	if( pEntry->mpPresetId )
	{
		const OUString aPresetId( OUString::createFromAscii( pEntry->mpPresetId ) );

		const TransitionPresetList& rPresetList = TransitionPreset::getTransitionPresetList();

        TransitionPresetList::const_iterator aIt( rPresetList.begin());
        const TransitionPresetList::const_iterator aEndIt( rPresetList.end());
        for( ; aIt != aEndIt; ++aIt )
        {
            if( (*aIt)->getPresetId() == aPresetId)
            {
				pPage->setTransitionType( (*aIt)->getTransition() );
				pPage->setTransitionSubtype( (*aIt)->getSubtype() );
				pPage->setTransitionDirection( (*aIt)->getDirection() );
				pPage->setTransitionFadeColor( (*aIt)->getFadeColor() );
				break;
            }
        }
	}
	else
	{
		pPage->setTransitionType( 0 );
		pPage->setTransitionSubtype( 0 );
		pPage->setTransitionDirection( 0 );
		pPage->setTransitionFadeColor( 0 );
	}
}

FadeEffect EffectMigration::GetFadeEffect( const SdPage* pPage )
{
	const TransitionPresetList & rPresetList = TransitionPreset::getTransitionPresetList();
    TransitionPresetList::const_iterator aIt( rPresetList.begin());
    const TransitionPresetList::const_iterator aEndIt( rPresetList.end());
    for( ; aIt != aEndIt; ++aIt )
    {
        if( ( (*aIt)->getTransition() == pPage->getTransitionType() ) && 
			( (*aIt)->getSubtype() == pPage->getTransitionSubtype() ) &&
			( (*aIt)->getDirection() == pPage->getTransitionDirection() ) &&
			( (*aIt)->getFadeColor() == pPage->getTransitionFadeColor() ) )
		{
			const OUString& aPresetId = (*aIt)->getPresetId();

			deprecated_FadeEffect_conversion_table_entry* pEntry = deprecated_FadeEffect_conversion_table;
			while( (pEntry->meFadeEffect != FadeEffect_NONE) && (!aPresetId.equalsAscii( pEntry->mpPresetId ) ) )
				pEntry++;

			return pEntry->meFadeEffect;
		}
	}
	return FadeEffect_NONE;
}

struct deprecated_AnimationEffect_conversion_table_entry
{
	AnimationEffect	meEffect;
	const sal_Char* mpPresetId;
	const sal_Char* mpPresetSubType;
}
deprecated_AnimationEffect_conversion_table[] =
{
// OOo 1.x entrance effects
	{ AnimationEffect_APPEAR, "ooo-entrance-appear",0 },

	{ AnimationEffect_FADE_TO_CENTER, "ooo-entrance-box","in" },
	{ AnimationEffect_FADE_FROM_CENTER, "ooo-entrance-box","out" },

	{ AnimationEffect_VERTICAL_CHECKERBOARD, "ooo-entrance-checkerboard","downward" },
	{ AnimationEffect_HORIZONTAL_CHECKERBOARD, "ooo-entrance-checkerboard","across" },

	{ AnimationEffect_FADE_FROM_UPPERLEFT, "ooo-entrance-diagonal-squares","right-to-bottom" },
	{ AnimationEffect_FADE_FROM_UPPERRIGHT, "ooo-entrance-diagonal-squares","left-to-bottom" },
	{ AnimationEffect_FADE_FROM_LOWERLEFT, "ooo-entrance-diagonal-squares","right-to-top" },
	{ AnimationEffect_FADE_FROM_LOWERRIGHT, "ooo-entrance-diagonal-squares","left-to-top" },

	{ AnimationEffect_DISSOLVE, "ooo-entrance-dissolve-in",0 },

	{ AnimationEffect_MOVE_FROM_LEFT, "ooo-entrance-fly-in","from-left" },
	{ AnimationEffect_MOVE_FROM_TOP, "ooo-entrance-fly-in","from-top" },
	{ AnimationEffect_MOVE_FROM_RIGHT, "ooo-entrance-fly-in","from-right" },
	{ AnimationEffect_MOVE_FROM_BOTTOM, "ooo-entrance-fly-in","from-bottom" },
	{ AnimationEffect_MOVE_FROM_UPPERLEFT, "ooo-entrance-fly-in","from-top-left" },
	{ AnimationEffect_MOVE_FROM_UPPERRIGHT, "ooo-entrance-fly-in","from-top-right" },
	{ AnimationEffect_MOVE_FROM_LOWERRIGHT, "ooo-entrance-fly-in","from-bottom-right" },
	{ AnimationEffect_MOVE_FROM_LOWERLEFT, "ooo-entrance-fly-in","from-bottom-left" },

	{ AnimationEffect_MOVE_FROM_BOTTOM,	"ooo-entrance-fly-in-slow", "from-bottom" },
	{ AnimationEffect_MOVE_FROM_LEFT, "ooo-entrance-fly-in-slow", "from-left" },
	{ AnimationEffect_MOVE_FROM_RIGHT, "ooo-entrance-fly-in-slow", "from-right" },
	{ AnimationEffect_MOVE_FROM_TOP, "ooo-entrance-fly-in-slow", "from-top" },

	{ AnimationEffect_MOVE_SHORT_FROM_LEFT, "ooo-entrance-peek-in","from-left" },
	{ AnimationEffect_MOVE_SHORT_FROM_TOP, "ooo-entrance-peek-in","from-top" },
	{ AnimationEffect_MOVE_SHORT_FROM_RIGHT, "ooo-entrance-peek-in","from-right" },
	{ AnimationEffect_MOVE_SHORT_FROM_BOTTOM, "ooo-entrance-peek-in","from-bottom" },

	{ AnimationEffect_VERTICAL_LINES, "ooo-entrance-random-bars","horizontal" },
	{ AnimationEffect_HORIZONTAL_LINES, "ooo-entrance-random-bars","vertical" },

	{ AnimationEffect_RANDOM, "ooo-entrance-random",0 },

	{ AnimationEffect_CLOSE_VERTICAL, "ooo-entrance-split","horizontal-in" },
	{ AnimationEffect_CLOSE_HORIZONTAL, "ooo-entrance-split","vertical-in" },
	{ AnimationEffect_OPEN_VERTICAL, "ooo-entrance-split","horizontal-out" },
	{ AnimationEffect_OPEN_HORIZONTAL, "ooo-entrance-split","vertical-out" },

	{ AnimationEffect_VERTICAL_STRIPES, "ooo-entrance-venetian-blinds","horizontal" },
	{ AnimationEffect_HORIZONTAL_STRIPES, "ooo-entrance-venetian-blinds","vertical" },

	{ AnimationEffect_FADE_FROM_LEFT, "ooo-entrance-wipe","from-left" },
	{ AnimationEffect_FADE_FROM_TOP, "ooo-entrance-wipe","from-bottom" },
	{ AnimationEffect_FADE_FROM_RIGHT, "ooo-entrance-wipe","from-right" },
	{ AnimationEffect_FADE_FROM_BOTTOM, "ooo-entrance-wipe","from-top" },

	{ AnimationEffect_HORIZONTAL_ROTATE, "ooo-entrance-swivel","vertical" },
	{ AnimationEffect_VERTICAL_ROTATE, "ooo-entrance-swivel","horizontal" },

	{ AnimationEffect_STRETCH_FROM_LEFT, "ooo-entrance-stretchy","from-left" },
	{ AnimationEffect_STRETCH_FROM_UPPERLEFT, "ooo-entrance-stretchy","from-top-left" },
	{ AnimationEffect_STRETCH_FROM_TOP, "ooo-entrance-stretchy","from-top" },
	{ AnimationEffect_STRETCH_FROM_UPPERRIGHT, "ooo-entrance-stretchy","from-top-right" },
	{ AnimationEffect_STRETCH_FROM_RIGHT, "ooo-entrance-stretchy","from-right" },
	{ AnimationEffect_STRETCH_FROM_LOWERRIGHT, "ooo-entrance-stretchy","from-bottom-right" },
	{ AnimationEffect_STRETCH_FROM_BOTTOM, "ooo-entrance-stretchy","from-bottom" },
	{ AnimationEffect_STRETCH_FROM_LOWERLEFT, "ooo-entrance-stretchy","from-bottom-left" },

	{ AnimationEffect_HORIZONTAL_STRETCH, "ooo-entrance-expand", 0 },

	{ AnimationEffect_CLOCKWISE, "ooo-entrance-wheel","1" },
	{ AnimationEffect_COUNTERCLOCKWISE, "ooo-entrance-clock-wipe","counter-clockwise" },

	{ AnimationEffect_SPIRALIN_LEFT, "ooo-entrance-spiral-wipe", "from-top-left-clockwise" },
	{ AnimationEffect_SPIRALIN_RIGHT, "ooo-entrance-spiral-wipe", "from-top-right-counter-clockwise" },
	{ AnimationEffect_SPIRALOUT_LEFT, "ooo-entrance-spiral-wipe", "from-center-clockwise" },
	{ AnimationEffect_SPIRALOUT_RIGHT, "ooo-entrance-spiral-wipe", "from-center-counter-clockwise" },

	{ AnimationEffect_WAVYLINE_FROM_LEFT, "ooo-entrance-snake-wipe","from-top-left-vertical" },
	{ AnimationEffect_WAVYLINE_FROM_TOP, "ooo-entrance-snake-wipe","from-top-left-horizontal" },
	{ AnimationEffect_WAVYLINE_FROM_RIGHT, "ooo-entrance-snake-wipe","from-bottom-right-vertical" },
	{ AnimationEffect_WAVYLINE_FROM_BOTTOM, "ooo-entrance-snake-wipe","from-bottom-right-horizontal" },

// ooo 1.x exit effects
	{ AnimationEffect_HIDE, "ooo-exit-disappear",0 },
	{ AnimationEffect_MOVE_TO_LEFT, "ooo-exit-fly-out", "from-right" },
	{ AnimationEffect_MOVE_TO_TOP, "ooo-exit-fly-out", "from-bottom" },
	{ AnimationEffect_MOVE_TO_RIGHT, "ooo-exit-fly-out", "from-left" },
	{ AnimationEffect_MOVE_TO_BOTTOM, "ooo-exit-fly-out", "from-top" },
	{ AnimationEffect_MOVE_TO_UPPERLEFT, "ooo-exit-fly-out", "from-top-right" },
	{ AnimationEffect_MOVE_TO_UPPERRIGHT, "ooo-exit-fly-out", "from-top-left" },
	{ AnimationEffect_MOVE_TO_LOWERRIGHT, "ooo-exit-fly-out", "from-bottom-left" },
	{ AnimationEffect_MOVE_TO_LOWERLEFT, "ooo-exit-fly-out", "from-bottom-right" },
	{ AnimationEffect_MOVE_SHORT_TO_LEFT, "ooo-exit-peek-out", "from-right" },
	{ AnimationEffect_MOVE_SHORT_TO_UPPERLEFT, "ooo-exit-peek-out", "from-right" },
	{ AnimationEffect_MOVE_SHORT_TO_TOP, "ooo-exit-peek-out", "from-bottom" },
	{ AnimationEffect_MOVE_SHORT_TO_UPPERRIGHT, "ooo-exit-peek-out", "from-bottom" },
	{ AnimationEffect_MOVE_SHORT_TO_RIGHT, "ooo-exit-peek-out", "from-left" },
	{ AnimationEffect_MOVE_SHORT_TO_LOWERRIGHT, "ooo-exit-peek-out","from-left" },
	{ AnimationEffect_MOVE_SHORT_TO_BOTTOM, "ooo-exit-peek-out", "from-top" },
	{ AnimationEffect_MOVE_SHORT_TO_LOWERLEFT, "ooo-exit-peek-out", "from-top" },

// no matching in OOo 2.x
	{ AnimationEffect_MOVE_SHORT_FROM_UPPERLEFT, "ooo-entrance-peek-in","from-left" },
	{ AnimationEffect_MOVE_SHORT_FROM_UPPERRIGHT, "ooo-entrance-peek-in","from-top" },
	{ AnimationEffect_MOVE_SHORT_FROM_LOWERRIGHT, "ooo-entrance-peek-in","from-right" },
	{ AnimationEffect_MOVE_SHORT_FROM_LOWERLEFT, "ooo-entrance-peek-in","from-bottom" },
	{ AnimationEffect_LASER_FROM_LEFT, "ooo-entrance-fly-in","from-left" },
	{ AnimationEffect_LASER_FROM_TOP, "ooo-entrance-fly-in","from-top" },
	{ AnimationEffect_LASER_FROM_RIGHT, "ooo-entrance-fly-in","from-right" },
	{ AnimationEffect_LASER_FROM_BOTTOM, "ooo-entrance-fly-in","from-bottom" },
	{ AnimationEffect_LASER_FROM_UPPERLEFT, "ooo-entrance-fly-in","from-top-left" },
	{ AnimationEffect_LASER_FROM_UPPERRIGHT, "ooo-entrance-fly-in","from-top-right" },
	{ AnimationEffect_LASER_FROM_LOWERLEFT, "ooo-entrance-fly-in","from-bottom-left" },
	{ AnimationEffect_LASER_FROM_LOWERRIGHT, "ooo-entrance-fly-in","from-bottom-right" },

// no matching in OOo 1.x

	{ AnimationEffect_FADE_TO_CENTER, "ooo-entrance-circle", "in" },
	{ AnimationEffect_FADE_FROM_CENTER, "ooo-entrance-circle", "out" },
	{ AnimationEffect_FADE_TO_CENTER, "ooo-entrance-diamond", "in" },
	{ AnimationEffect_FADE_FROM_CENTER, "ooo-entrance-diamond", "out" },
	{ AnimationEffect_FADE_TO_CENTER, "ooo-entrance-plus", "in" },
	{ AnimationEffect_FADE_FROM_CENTER, "ooo-entrance-plus", "out" },
	{ AnimationEffect_CLOCKWISE, "ooo-entrance-wedge", 0 },
	{ AnimationEffect_CLOCKWISE, "ooo-entrance-wheel", "2" },
	{ AnimationEffect_CLOCKWISE, "ooo-entrance-wheel", "3" },
	{ AnimationEffect_CLOCKWISE, "ooo-entrance-wheel", "4" },
	{ AnimationEffect_CLOCKWISE, "ooo-entrance-wheel", "8" },

	{ AnimationEffect_MOVE_FROM_RIGHT, "ooo-entrance-boomerang", 0 },
	{ AnimationEffect_MOVE_FROM_UPPERRIGHT, "ooo-entrance-bounce", 0 },
	{ AnimationEffect_MOVE_FROM_BOTTOM, "ooo-entrance-curve-up", 0 },
	{ AnimationEffect_MOVE_FROM_TOP, "ooo-entrance-float", 0 },
	{ AnimationEffect_MOVE_FROM_LEFT, "ooo-entrance-glide", 0 },
	{ AnimationEffect_MOVE_FROM_BOTTOM, "ooo-entrance-magnify", 0 },
	{ AnimationEffect_HORIZONTAL_ROTATE, "ooo-entrance-pinwheel", 0 },
	{ AnimationEffect_MOVE_FROM_LEFT, "ooo-entrance-breaks", 0 },
	{ AnimationEffect_MOVE_FROM_LEFT, "ooo-entrance-sling", 0 },
	{ AnimationEffect_MOVE_FROM_LEFT, "ooo-entrance-spiral-in", 0 },
	{ AnimationEffect_MOVE_FROM_LEFT, "ooo-entrance-thread", 0 },
	{ AnimationEffect_MOVE_FROM_BOTTOM, "ooo-entrance-ascend", 0 },
	{ AnimationEffect_MOVE_FROM_BOTTOM, "ooo-entrance-center-revolve", 0 },
	{ AnimationEffect_APPEAR, "ooo-entrance-compress", 0 },
	{ AnimationEffect_MOVE_SHORT_FROM_TOP, "ooo-entrance-descend", 0 },
	{ AnimationEffect_MOVE_SHORT_FROM_LEFT, "ooo-entrance-ease-in", 0 },
	{ AnimationEffect_MOVE_FROM_BOTTOM, "ooo-entrance-rise-up", 0 },
	{ AnimationEffect_HORIZONTAL_ROTATE, "ooo-entrance-spin-in", 0 },
	{ AnimationEffect_STRETCH_FROM_LEFT, "ooo-entrance-stretchy", "across" },
	{ AnimationEffect_STRETCH_FROM_TOP, "ooo-entrance-stretchy", "downward" },

	{ AnimationEffect_FADE_FROM_CENTER, "ooo-entrance-zoom","in" },
	{ AnimationEffect_FADE_FROM_CENTER, "ooo-entrance-zoom","in-slightly" },
	{ AnimationEffect_FADE_FROM_CENTER, "ooo-entrance-zoom","in-from-screen-center" },
	{ AnimationEffect_FADE_TO_CENTER, "ooo-entrance-zoom","out" },
	{ AnimationEffect_FADE_TO_CENTER, "ooo-entrance-zoom","out-slightly" },
	{ AnimationEffect_FADE_TO_CENTER, "ooo-entrance-zoom","out-from-screen-center" },

	{ AnimationEffect_DISSOLVE, "ooo-entrance-fade-in", 0 },
	{ AnimationEffect_DISSOLVE, "ooo-entrance-fade-in-and-zoom", 0 },
	{ AnimationEffect_DISSOLVE, "ooo-entrance-fade-in-and-swivel", 0 },

// open
/*
	{ AnimationEffect_ZOOM_IN_FROM_LEFT, "ooo-entrance-zoom","in" },
	{ AnimationEffect_ZOOM_IN_FROM_UPPERLEFT, "ooo-entrance-zoom","in" },
	{ AnimationEffect_ZOOM_IN_FROM_TOP, "ooo-entrance-zoom","in" },
	{ AnimationEffect_ZOOM_IN_FROM_UPPERRIGHT, "ooo-entrance-zoom","in" },
	{ AnimationEffect_ZOOM_IN_FROM_RIGHT, "ooo-entrance-zoom","in" },
	{ AnimationEffect_ZOOM_IN_FROM_LOWERRIGHT, "ooo-entrance-zoom","in" },
	{ AnimationEffect_ZOOM_IN_FROM_BOTTOM, "ooo-entrance-zoom","in" },
	{ AnimationEffect_ZOOM_IN_FROM_LOWERLEFT, "ooo-entrance-zoom","in" },
	{ AnimationEffect_ZOOM_IN_FROM_CENTER, "ooo-entrance-zoom","in" },

	{ AnimationEffect_ZOOM_OUT_FROM_LEFT, "ooo-entrance-appear",0 },
	{ AnimationEffect_ZOOM_OUT_FROM_UPPERLEFT, "ooo-entrance-appear",0 },
	{ AnimationEffect_ZOOM_OUT_FROM_TOP, "ooo-entrance-appear",0 },
	{ AnimationEffect_ZOOM_OUT_FROM_UPPERRIGHT, "ooo-entrance-appear",0 },
	{ AnimationEffect_ZOOM_OUT_FROM_RIGHT, "ooo-entrance-appear",0 },
	{ AnimationEffect_ZOOM_OUT_FROM_LOWERRIGHT, "ooo-entrance-appear",0 },
	{ AnimationEffect_ZOOM_OUT_FROM_BOTTOM, "ooo-entrance-appear",0 },
	{ AnimationEffect_ZOOM_OUT_FROM_LOWERLEFT, "ooo-entrance-appear",0 },
	{ AnimationEffect_ZOOM_OUT_FROM_CENTER, "ooo-entrance-appear",0 },
	{ AnimationEffect_PATH, "ooo-entrance-spiral-in",0 },
*/
	{ AnimationEffect_NONE, 0, 0 }
};

EffectSequence::iterator ImplFindEffect( MainSequencePtr& pMainSequence, const Reference< XShape >& rShape, sal_Int16 nSubItem )
{
	EffectSequence::iterator aIter;
	
	for( aIter = pMainSequence->getBegin(); aIter != pMainSequence->getEnd(); aIter++ )
	{
		CustomAnimationEffectPtr pEffect( (*aIter) );
		if( (pEffect->getTargetShape() == rShape) && (pEffect->getTargetSubItem() == nSubItem) )
			break;
	}

	return aIter;
}

static bool implIsInsideGroup( SdrObject* pObj )
{
	return pObj && pObj->GetObjList() && pObj->GetObjList()->GetUpList();
}

void EffectMigration::SetAnimationEffect( SvxShape* pShape, AnimationEffect eEffect )
{
	DBG_ASSERT( pShape && pShape->GetSdrObject() && pShape->GetSdrObject()->GetPage(),
				"sd::EffectMigration::SetAnimationEffect(), invalid argument!" );
	if( !pShape || !pShape->GetSdrObject() || !pShape->GetSdrObject()->GetPage() )
		return;

	SdrObject* pObj = pShape->GetSdrObject();
	if( implIsInsideGroup( pObj ) )
		return;

	OUString aPresetId;
	OUString aPresetSubType;

	if( !ConvertAnimationEffect( eEffect, aPresetId, aPresetSubType ) )
	{
		DBG_ERROR( "sd::EffectMigration::SetAnimationEffect(), no mapping for given AnimationEffect value" );
		return;
	}

	const CustomAnimationPresets& rPresets = CustomAnimationPresets::getCustomAnimationPresets();

	CustomAnimationPresetPtr pPreset( rPresets.getEffectDescriptor( aPresetId ) );
	sd::MainSequencePtr pMainSequence = static_cast<SdPage*>(pObj->GetPage())->getMainSequence();

	if( pPreset.get() && pMainSequence.get() )
	{
		const Reference< XShape > xShape( pShape );

		EffectSequence::iterator aIterOnlyBackground( ImplFindEffect( pMainSequence, xShape, ShapeAnimationSubType::ONLY_BACKGROUND ) );
		EffectSequence::iterator aIterAsWhole( ImplFindEffect( pMainSequence, xShape, ShapeAnimationSubType::AS_WHOLE ) );
		const EffectSequence::iterator aEnd( pMainSequence->getEnd() );

		bool bEffectCreated = false;

		if( (aIterOnlyBackground == aEnd) && (aIterAsWhole == aEnd) )
		{
			// check if there is already an text effect for this shape
			EffectSequence::iterator aIterOnlyText( ImplFindEffect( pMainSequence, xShape, ShapeAnimationSubType::ONLY_TEXT ) );
			if( aIterOnlyText != aEnd )
			{
				// check if this is an animation text group
				sal_Int32 nGroupId = (*aIterOnlyText)->getGroupId();
				if( nGroupId >= 0 )
				{
					CustomAnimationTextGroupPtr pGroup = pMainSequence->findGroup( nGroupId );
					if( pGroup.get() )
					{
						// add an effect to animate the shape
						pMainSequence->setAnimateForm( pGroup, true );

						// find this effect
						EffectSequence::iterator aIter( ImplFindEffect( pMainSequence, xShape, ShapeAnimationSubType::ONLY_BACKGROUND ) );

						if( aIter != aEnd )
						{
							if( ((*aIter)->getPresetId() != aPresetId) ||
								((*aIter)->getPresetSubType() != aPresetSubType) )
							{
								(*aIter)->replaceNode( pPreset->create( aPresetSubType ) );
								pMainSequence->rebuild();
								bEffectCreated = true;
							}
						}
					}
				}
			}

			if( !bEffectCreated )
			{
				// if there is not yet an effect that target this shape, we generate one
				// we insert the shape effect before it
				Reference< XAnimationNode > xNode( pPreset->create( aPresetSubType ) );
				DBG_ASSERT( xNode.is(), "EffectMigration::SetAnimationEffect(), could not create preset!" );
				if( xNode.is() )
				{
					CustomAnimationEffectPtr pEffect( new CustomAnimationEffect( xNode ) );
					pEffect->setTarget( makeAny( xShape ) );
					SdPage* pPage = dynamic_cast< SdPage* >( pObj->GetPage() );
					const bool bManual = (pPage == 0) || (pPage->GetPresChange() == PRESCHANGE_MANUAL);
					if( !bManual )
						pEffect->setNodeType( EffectNodeType::AFTER_PREVIOUS );

					pMainSequence->append( pEffect );

					if( ( pObj->GetObjInventor() == SdrInventor ) && ( pObj->GetObjIdentifier() == OBJ_OUTLINETEXT ) )
					{
						// special case for outline text, effects are always mapped to text group effect
						pMainSequence->
							createTextGroup( pEffect, 10, bManual ? -1 : 0.0, sal_False, sal_False );
					}
				}
			}
		}
		else
		{
			// if there is already an effect targeting this shape
			// just replace it
			CustomAnimationEffectPtr pEffect;
			if( aIterAsWhole != aEnd )
			{
				pEffect = (*aIterAsWhole);
			}
			else
			{
				pEffect = (*aIterOnlyBackground);
			}

			if( pEffect.get() )
			{
				if( (pEffect->getPresetId() != aPresetId) ||
					(pEffect->getPresetSubType() != aPresetSubType) )
				{
					pMainSequence->replace( pEffect, pPreset, aPresetSubType );
				}
			}
		}
	}
}

// --------------------------------------------------------------------

AnimationEffect EffectMigration::GetAnimationEffect( SvxShape* pShape )
{
	OUString aPresetId;
	OUString aPresetSubType;

	SdrObject* pObj = pShape->GetSdrObject();
	sd::MainSequencePtr pMainSequence = static_cast<SdPage*>(pObj->GetPage())->getMainSequence();

	if( pMainSequence.get() )
	{
		const Reference< XShape > xShape( pShape );

		EffectSequence::iterator aIter;
		
		for( aIter = pMainSequence->getBegin(); aIter != pMainSequence->getEnd(); aIter++ )
		{
			CustomAnimationEffectPtr pEffect( (*aIter) );
			if( pEffect->getTargetShape() == xShape )
			{
				if( (pEffect->getTargetSubItem() == ShapeAnimationSubType::ONLY_BACKGROUND) ||
					(pEffect->getTargetSubItem() == ShapeAnimationSubType::AS_WHOLE))
				{
					if( pEffect->getDuration() != 0.1 ) // ignore appear effects created from old text effect import
					{
						aPresetId = (*aIter)->getPresetId();
						aPresetSubType = (*aIter)->getPresetSubType();
						break;
					}
				}
			}
		}
	}

	// now find old effect
	AnimationEffect	eEffect = AnimationEffect_NONE;

	if( !ConvertPreset( aPresetId, &aPresetSubType, eEffect ) )
		ConvertPreset( aPresetId, 0, eEffect );

	return eEffect;
}


// --------------------------------------------------------------------

void EffectMigration::SetTextAnimationEffect( SvxShape* pShape, AnimationEffect eEffect )
{
	DBG_ASSERT( pShape && pShape->GetSdrObject() && pShape->GetSdrObject()->GetPage(),
				"sd::EffectMigration::SetAnimationEffect(), invalid argument!" );
	if( !pShape || !pShape->GetSdrObject() || !pShape->GetSdrObject()->GetPage() )
		return;

	SdrObject* pObj = pShape->GetSdrObject();
	if( implIsInsideGroup( pObj ) )
		return;

	// first map the deprecated AnimationEffect to a preset and subtype
	OUString aPresetId;
	OUString aPresetSubType;

	if( !ConvertAnimationEffect( eEffect, aPresetId, aPresetSubType ) )
	{
		DBG_ERROR( "sd::EffectMigration::SetAnimationEffect(), no mapping for given AnimationEffect value" );
		return;
	}

	SdrTextObj* pTextObj = dynamic_cast< SdrTextObj* >( pObj );

	// ignore old text effects on shape without text
	if( (pTextObj == 0) || (!pTextObj->HasText()) )
		return;

	const CustomAnimationPresets& rPresets = CustomAnimationPresets::getCustomAnimationPresets();

	// create an effect from this preset
	CustomAnimationPresetPtr pPreset( rPresets.getEffectDescriptor( aPresetId ) );

	sd::MainSequencePtr pMainSequence = static_cast<SdPage*>(pObj->GetPage())->getMainSequence();

	if( pPreset.get() && pMainSequence.get() )
	{
		const Reference< XShape > xShape( pShape );

		EffectSequence::iterator aIterOnlyText( ImplFindEffect( pMainSequence, xShape, ShapeAnimationSubType::ONLY_TEXT ) );
		const EffectSequence::iterator aEnd( pMainSequence->getEnd() );

		CustomAnimationTextGroupPtr pGroup;

		// is there already an animation text group for this shape?
		if( aIterOnlyText != aEnd )
		{
			const sal_Int32 nGroupId = (*aIterOnlyText)->getGroupId();
			if( nGroupId >= 0 )
				pGroup = pMainSequence->findGroup( nGroupId );
		}

		// if there is not yet a group, create it
		if( pGroup.get() == 0 )
		{
			CustomAnimationEffectPtr pShapeEffect;

			EffectSequence::iterator aIterOnlyBackground( ImplFindEffect( pMainSequence, xShape, ShapeAnimationSubType::ONLY_BACKGROUND ) );
			if( aIterOnlyBackground != aEnd )
			{
				pShapeEffect = (*aIterOnlyBackground);
			}
			else 
			{
				EffectSequence::iterator aIterAsWhole( ImplFindEffect( pMainSequence, xShape, ShapeAnimationSubType::AS_WHOLE ) );
				if( aIterAsWhole != aEnd )
				{
					pShapeEffect = (*aIterAsWhole);
				}
				else
				{
					OUString aEmpty;
					CustomAnimationPresetPtr pShapePreset( rPresets.getEffectDescriptor( OUString( RTL_CONSTASCII_USTRINGPARAM( "ooo-entrance-appear" ) ) ) );

					Reference< XAnimationNode > xNode( pPreset->create( aEmpty ) );
					DBG_ASSERT( xNode.is(), "EffectMigration::SetTextAnimationEffect(), could not create preset!" );
					if( xNode.is() )
					{
						pShapeEffect.reset( new CustomAnimationEffect( xNode ) );
						pShapeEffect->setTarget( makeAny( xShape ) );
						pShapeEffect->setDuration( 0.1 );
						pMainSequence->append( pShapeEffect );

						SdPage* pPage = dynamic_cast< SdPage* >( pObj->GetPage() );
						if( pPage && pPage->GetPresChange() != PRESCHANGE_MANUAL )
							pShapeEffect->setNodeType( EffectNodeType::AFTER_PREVIOUS );
					}
				}
			}

			if( pShapeEffect.get() )
			{
				SdPage* pPage = dynamic_cast< SdPage* >( pObj->GetPage() );
				const bool bManual = (pPage == 0) || (pPage->GetPresChange() == PRESCHANGE_MANUAL);

				// now create effects for each paragraph
				pGroup = 
					pMainSequence->
						createTextGroup( pShapeEffect, 10, bManual ? -1 : 0.0, sal_True, sal_False );
			}
		}

		if( pGroup.get() != 0 )
		{
			const bool bLaserEffect = (eEffect >= AnimationEffect_LASER_FROM_LEFT) && (eEffect <= AnimationEffect_LASER_FROM_LOWERRIGHT);

			// now we have a group, so check if all effects are same as we like to have them
			const EffectSequence& rEffects = pGroup->getEffects();

			EffectSequence::const_iterator aIter;
			for( aIter = rEffects.begin(); aIter != rEffects.end(); aIter++ )
			{
				// only work on paragraph targets
				if( (*aIter)->getTarget().getValueType() == ::getCppuType((const ParagraphTarget*)0) )
				{
					if( ((*aIter)->getPresetId() != aPresetId) ||
						((*aIter)->getPresetSubType() != aPresetSubType) )
					{
						(*aIter)->replaceNode( pPreset->create( aPresetSubType ) );
					}

					if( bLaserEffect )
                    {
						(*aIter)->setIterateType( TextAnimationType::BY_LETTER );
						(*aIter)->setIterateInterval( 0.5 );// TODO:
                                                             // Determine
                                                             // interval
                                                             // according
                                                             // to
                                                             // total
                                                             // effect
                                                             // duration
                    }
				}
			}
		}
		pMainSequence->rebuild();
	}
}

// --------------------------------------------------------------------

AnimationEffect EffectMigration::GetTextAnimationEffect( SvxShape* pShape )
{
	OUString aPresetId;
	OUString aPresetSubType;

	SdrObject* pObj = pShape->GetSdrObject();
	if( pObj )
	{
		sd::MainSequencePtr pMainSequence = static_cast<SdPage*>(pObj->GetPage())->getMainSequence();

		if( pMainSequence.get() )
		{
			const Reference< XShape > xShape( pShape );
			EffectSequence::iterator aIter( ImplFindEffect( pMainSequence, xShape, ShapeAnimationSubType::ONLY_TEXT ) );
			if( aIter != pMainSequence->getEnd() )
			{
				aPresetId = (*aIter)->getPresetId();
				aPresetSubType = (*aIter)->getPresetSubType();
			}
		}
	}

	// now find old effect
	AnimationEffect	eEffect = AnimationEffect_NONE;

	if( !ConvertPreset( aPresetId, &aPresetSubType, eEffect ) )
		ConvertPreset( aPresetId, 0, eEffect );

	return eEffect;
}

// --------------------------------------------------------------------

bool EffectMigration::ConvertPreset( const OUString& rPresetId, const OUString* pPresetSubType, AnimationEffect& rEffect )
{
	rEffect = AnimationEffect_NONE;
	if( rPresetId.getLength() )
	{
		// first try a match for preset id and subtype
		deprecated_AnimationEffect_conversion_table_entry* p = deprecated_AnimationEffect_conversion_table;
		while( p->mpPresetId )
		{
			if( rPresetId.equalsAscii( p->mpPresetId ) && 
				(( p->mpPresetSubType == 0 ) ||
				 ( pPresetSubType == 0) ||
				 ( pPresetSubType->equalsAscii( p->mpPresetSubType )) ) )
			{
				rEffect = p->meEffect;
				return true;
			}
			p++;
		}
		return false;
	}
	else
	{
		// empty preset id means AnimationEffect_NONE
		return true;
	}
}

// --------------------------------------------------------------------

bool EffectMigration::ConvertAnimationEffect( const AnimationEffect& rEffect, OUString& rPresetId, OUString& rPresetSubType )
{
	deprecated_AnimationEffect_conversion_table_entry* p = deprecated_AnimationEffect_conversion_table;
	while( p->mpPresetId )
	{
		if( p->meEffect == rEffect )
		{
			rPresetId = OUString::createFromAscii( p->mpPresetId );
			rPresetSubType = OUString::createFromAscii( p->mpPresetSubType );
			return true;
		}
		p++;
	}

	return false;
}

// --------------------------------------------------------------------

double EffectMigration::ConvertAnimationSpeed( AnimationSpeed eSpeed )
{
	double fDuration;
	switch( eSpeed )
	{
	case AnimationSpeed_SLOW: fDuration = 2.0; break;
	case AnimationSpeed_FAST: fDuration = 0.5; break;
	//case AnimationSpeed_MEDIUM:
	default:
		fDuration = 1.0; break;
	}
	return fDuration;
}
// --------------------------------------------------------------------

void EffectMigration::SetAnimationSpeed( SvxShape* pShape, AnimationSpeed eSpeed )
{
	DBG_ASSERT( pShape && pShape->GetSdrObject() && pShape->GetSdrObject()->GetPage(),
				"sd::EffectMigration::SetAnimationEffect(), invalid argument!" );
	if( !pShape || !pShape->GetSdrObject() || !pShape->GetSdrObject()->GetPage() )
		return;

	SdrObject* pObj = pShape->GetSdrObject();
	if( implIsInsideGroup( pObj ) )
		return;

	double fDuration = ConvertAnimationSpeed( eSpeed );

	sd::MainSequencePtr pMainSequence = static_cast<SdPage*>(pObj->GetPage())->getMainSequence();

	const Reference< XShape > xShape( pShape );

	EffectSequence::iterator aIter;
	bool bNeedRebuild = false;
	
	for( aIter = pMainSequence->getBegin(); aIter != pMainSequence->getEnd(); aIter++ )
	{
		CustomAnimationEffectPtr pEffect( (*aIter) );
		if( pEffect->getTargetShape() == xShape )
		{
			if( pEffect->getDuration() != 0.1 )
				pEffect->setDuration( fDuration );
			bNeedRebuild = true;
		}
	}

	if( bNeedRebuild )
		pMainSequence->rebuild();
}

// --------------------------------------------------------------------

AnimationSpeed EffectMigration::GetAnimationSpeed( SvxShape* pShape )
{
	SdrObject* pObj = pShape->GetSdrObject();
	sd::MainSequencePtr pMainSequence = static_cast<SdPage*>(pObj->GetPage())->getMainSequence();

	const Reference< XShape > xShape( pShape );

	EffectSequence::iterator aIter;

	double fDuration = 1.0;

	for( aIter = pMainSequence->getBegin(); aIter != pMainSequence->getEnd(); aIter++ )
	{
		CustomAnimationEffectPtr pEffect( (*aIter) );
		if( pEffect->getTargetShape() == xShape )
		{
			if( pEffect->getDuration() != 0.1 )
			{
				fDuration = pEffect->getDuration();
				break;
			}
		}
	}

	return ConvertDuration( fDuration );
}

// --------------------------------------------------------------------

AnimationSpeed EffectMigration::ConvertDuration( double fDuration )
{
	AnimationSpeed eSpeed;

	if( fDuration < 1.0 )
		eSpeed = AnimationSpeed_FAST;
	else if( fDuration > 1.5 )
		eSpeed = AnimationSpeed_SLOW;
	else
		eSpeed = AnimationSpeed_MEDIUM;

	return eSpeed;
}

// --------------------------------------------------------------------

void EffectMigration::SetDimColor( SvxShape* pShape, sal_Int32 nColor )
{
	DBG_ASSERT( pShape && pShape->GetSdrObject() && pShape->GetSdrObject()->GetPage(),
				"sd::EffectMigration::SetAnimationEffect(), invalid argument!" );
	if( !pShape || !pShape->GetSdrObject() || !pShape->GetSdrObject()->GetPage() )
		return;

	SdrObject* pObj = pShape->GetSdrObject();
	if( implIsInsideGroup( pObj ) )
		return;

	sd::MainSequencePtr pMainSequence = static_cast<SdPage*>(pObj->GetPage())->getMainSequence();

	const Reference< XShape > xShape( pShape );

	EffectSequence::iterator aIter;
	bool bNeedRebuild = false;
	
	for( aIter = pMainSequence->getBegin(); aIter != pMainSequence->getEnd(); aIter++ )
	{
		CustomAnimationEffectPtr pEffect( (*aIter) );
		if( pEffect->getTargetShape() == xShape )
		{
			pEffect->setHasAfterEffect( true );
			pEffect->setDimColor( makeAny( nColor ) );
			pEffect->setAfterEffectOnNext( true );
			bNeedRebuild = true;
		}
	}

	if( bNeedRebuild )
		pMainSequence->rebuild();
}

// --------------------------------------------------------------------

sal_Int32 EffectMigration::GetDimColor( SvxShape* pShape )
{
	sal_Int32 nColor = 0;
	if( pShape )
	{
		SdrObject* pObj = pShape->GetSdrObject();
		if( pObj && pObj->GetPage() )
		{
			sd::MainSequencePtr pMainSequence = static_cast<SdPage*>(pObj->GetPage())->getMainSequence();

			const Reference< XShape > xShape( pShape );
			EffectSequence::iterator aIter;
			
			for( aIter = pMainSequence->getBegin(); aIter != pMainSequence->getEnd(); aIter++ )
			{
				CustomAnimationEffectPtr pEffect( (*aIter) );
				if( (pEffect->getTargetShape() == xShape) && 
					pEffect->getDimColor().hasValue() &&
					pEffect->hasAfterEffect())
				{
					pEffect->getDimColor() >>= nColor;
					break;
				}
			}
		}
	}

	return nColor;
}

// --------------------------------------------------------------------


void EffectMigration::SetDimHide( SvxShape* pShape, sal_Bool bDimHide )
{
	DBG_ASSERT( pShape && pShape->GetSdrObject() && pShape->GetSdrObject()->GetPage(),
				"sd::EffectMigration::SetAnimationEffect(), invalid argument!" );
	if( !pShape || !pShape->GetSdrObject() || !pShape->GetSdrObject()->GetPage() )
		return;

	SdrObject* pObj = pShape->GetSdrObject();
	if( implIsInsideGroup( pObj ) )
		return;

	Any aEmpty;

	sd::MainSequencePtr pMainSequence = static_cast<SdPage*>(pObj->GetPage())->getMainSequence();

	const Reference< XShape > xShape( pShape );

	EffectSequence::iterator aIter;
	bool bNeedRebuild = false;
	
	for( aIter = pMainSequence->getBegin(); aIter != pMainSequence->getEnd(); aIter++ )
	{
		CustomAnimationEffectPtr pEffect( (*aIter) );
		if( pEffect->getTargetShape() == xShape )
		{
			pEffect->setHasAfterEffect( bDimHide ? true : false );
			if( bDimHide )
				pEffect->setDimColor( aEmpty );
			pEffect->setAfterEffectOnNext( false );
			bNeedRebuild = true;
		}
	}

	if( bNeedRebuild )
		pMainSequence->rebuild();
}

// --------------------------------------------------------------------

sal_Bool EffectMigration::GetDimHide( SvxShape* pShape )
{
	sal_Bool bRet = sal_False;
	if( pShape )
	{
		SdrObject* pObj = pShape->GetSdrObject();
		if( pObj && pObj->GetPage() )
		{
			sd::MainSequencePtr pMainSequence = static_cast<SdPage*>(pObj->GetPage())->getMainSequence();

			const Reference< XShape > xShape( pShape );

			EffectSequence::iterator aIter;
			for( aIter = pMainSequence->getBegin(); aIter != pMainSequence->getEnd(); aIter++ )
			{
				CustomAnimationEffectPtr pEffect( (*aIter) );
				if( pEffect->getTargetShape() == xShape )
				{
					bRet = pEffect->hasAfterEffect() &&
							!pEffect->getDimColor().hasValue() &&
							(!pEffect->IsAfterEffectOnNext());
					break;
				}
			}
		}
	}

	return bRet;
}

// --------------------------------------------------------------------

void EffectMigration::SetDimPrevious( SvxShape* pShape, sal_Bool bDimPrevious )
{
	DBG_ASSERT( pShape && pShape->GetSdrObject() && pShape->GetSdrObject()->GetPage(),
				"sd::EffectMigration::SetAnimationEffect(), invalid argument!" );
	if( !pShape || !pShape->GetSdrObject() || !pShape->GetSdrObject()->GetPage() )
		return;

	SdrObject* pObj = pShape->GetSdrObject();
	if( implIsInsideGroup( pObj ) )
		return;

	Any aColor;

	if( bDimPrevious )
		aColor <<= (sal_Int32)COL_LIGHTGRAY;

	sd::MainSequencePtr pMainSequence = static_cast<SdPage*>(pObj->GetPage())->getMainSequence();

	const Reference< XShape > xShape( pShape );

	EffectSequence::iterator aIter;
	bool bNeedRebuild = false;
	
	for( aIter = pMainSequence->getBegin(); aIter != pMainSequence->getEnd(); aIter++ )
	{
		CustomAnimationEffectPtr pEffect( (*aIter) );
		if( pEffect->getTargetShape() == xShape )
		{
			pEffect->setHasAfterEffect( bDimPrevious );
			if( !bDimPrevious || !pEffect->getDimColor().hasValue() )
				pEffect->setDimColor( aColor );
			pEffect->setAfterEffectOnNext( true );
			bNeedRebuild = true;
		}
	}

	if( bNeedRebuild )
		pMainSequence->rebuild();
}

// --------------------------------------------------------------------

sal_Bool EffectMigration::GetDimPrevious( SvxShape* pShape )
{
	sal_Bool bRet = sal_False;
	if( pShape )
	{
		SdrObject* pObj = pShape->GetSdrObject();
		if( pObj && pObj->GetPage() )
		{
			sd::MainSequencePtr pMainSequence = static_cast<SdPage*>(pObj->GetPage())->getMainSequence();

			const Reference< XShape > xShape( pShape );

			EffectSequence::iterator aIter;
			for( aIter = pMainSequence->getBegin(); aIter != pMainSequence->getEnd(); aIter++ )
			{
				CustomAnimationEffectPtr pEffect( (*aIter) );
				if( pEffect->getTargetShape() == xShape )
				{
					bRet = pEffect->hasAfterEffect() &&
							pEffect->getDimColor().hasValue() &&
							pEffect->IsAfterEffectOnNext();
					break;
				}
			}
		}
	}

	return bRet;
}

// --------------------------------------------------------------------

void EffectMigration::SetPresentationOrder( SvxShape* pShape, sal_Int32 nNewPos )
{
	if( !pShape || !pShape->GetSdrObject() || !pShape->GetSdrObject()->GetPage() )
		return;

	SdrObject* pObj = pShape->GetSdrObject();
	sd::MainSequencePtr pMainSequence = static_cast<SdPage*>(pObj->GetPage())->getMainSequence();

	EffectSequence& rSequence = pMainSequence->getSequence();
	sal_Int32 nPos;
	sal_Int32 nCurrentPos = -1;
	std::vector< std::vector< EffectSequence::iterator > > aEffectVector(1);

	if( !rSequence.empty() )
	{
		Reference< XShape > xThis( pShape );
		Reference< XShape > xCurrent;
	
		EffectSequence::iterator aIter( rSequence.begin() );
		EffectSequence::iterator aEnd( rSequence.end() );
		for( nPos = 0; aIter != aEnd; aIter++ )
		{
			CustomAnimationEffectPtr pEffect = (*aIter);

			if( !xCurrent.is() )
			{
				xCurrent = pEffect->getTargetShape();
			}
			else if( pEffect->getTargetShape() != xCurrent )
			{
				nPos++;
				xCurrent = pEffect->getTargetShape();
				aEffectVector.resize( nPos+1 );
			}

			// is this the first effect for xThis shape?
			if(( nCurrentPos == -1 ) && ( xCurrent == xThis ) )
			{
				nCurrentPos = nPos;
			}

			aEffectVector[nPos].push_back( aIter );
		}
	}

	// check if there is at least one effect for xThis
	if( nCurrentPos == -1 )
	{
		DBG_ERROR("sd::EffectMigration::SetPresentationOrder() failed cause this shape has no effect" );
		return;
	}

	// check trivial case
	if( nCurrentPos != nNewPos )
	{
		std::vector< CustomAnimationEffectPtr > aEffects;

		std::vector< EffectSequence::iterator >::iterator aIter( aEffectVector[nCurrentPos].begin() );
		std::vector< EffectSequence::iterator >::iterator aEnd( aEffectVector[nCurrentPos].end() );
		while( aIter != aEnd )
		{
			aEffects.push_back( (*(*aIter)) );
			rSequence.erase( (*aIter++) );
		}
		
		if( nNewPos > nCurrentPos )
			nNewPos++;

		std::vector< CustomAnimationEffectPtr >::iterator aTempIter( aEffects.begin() );
		std::vector< CustomAnimationEffectPtr >::iterator aTempEnd( aEffects.end() );

		if( nNewPos == (sal_Int32)aEffectVector.size() )
		{
			while( aTempIter != aTempEnd )
			{
				rSequence.push_back( (*aTempIter++) );
			}
		}
		else
		{
			EffectSequence::iterator aPos( aEffectVector[nNewPos][0] );
			while( aTempIter != aTempEnd )
			{
				rSequence.insert( aPos, (*aTempIter++) );
			}
		}
	}
}

// --------------------------------------------------------------------

/** Returns the position of the given SdrObject in the Presentation order.
 *  This function returns -1 if the SdrObject is not in the Presentation order
 *  or if its the path-object.
 */
sal_Int32 EffectMigration::GetPresentationOrder( SvxShape* pShape )
{
	sal_Int32 nPos = -1, nFound = -1;

	SdrObject* pObj = pShape->GetSdrObject();
	sd::MainSequencePtr pMainSequence = static_cast<SdPage*>(pObj->GetPage())->getMainSequence();

	EffectSequence& rSequence = pMainSequence->getSequence();

	Reference< XShape > xThis( pShape );
	Reference< XShape > xCurrent;

	EffectSequence::iterator aIter( rSequence.begin() );
	EffectSequence::iterator aEnd( rSequence.end() );
	for( ; aIter != aEnd; aIter++ )
	{
		CustomAnimationEffectPtr pEffect = (*aIter);

		if( !xCurrent.is() || pEffect->getTargetShape() != xCurrent )
		{
			nPos++;
			xCurrent = pEffect->getTargetShape();

			// is this the first effect for xThis shape?
			if( xCurrent == xThis )
			{
				nFound = nPos;
				break;
			}
		}
	}

	return nFound;
}

// --------------------------------------------------------------------

void EffectMigration::UpdateSoundEffect( SvxShape* pShape, SdAnimationInfo* pInfo )
{
	if( pInfo )
	{
		SdrObject* pObj = pShape->GetSdrObject();
		sd::MainSequencePtr pMainSequence = static_cast<SdPage*>(pObj->GetPage())->getMainSequence();

		const Reference< XShape > xShape( pShape );

		EffectSequence::iterator aIter;
		bool bNeedRebuild = false;
		
		OUString aSoundFile;
		if( pInfo->mbSoundOn )
			aSoundFile = pInfo->maSoundFile;

		for( aIter = pMainSequence->getBegin(); aIter != pMainSequence->getEnd(); aIter++ )
		{
			CustomAnimationEffectPtr pEffect( (*aIter) );
			if( pEffect->getTargetShape() == xShape )
			{
				if( aSoundFile.getLength() )
				{
					pEffect->createAudio( makeAny( aSoundFile ) );
				}
				else
				{
					pEffect->removeAudio();
				}
				bNeedRebuild = true;
			}
		}

		if( bNeedRebuild )
			pMainSequence->rebuild();
	}
}

// --------------------------------------------------------------------

OUString EffectMigration::GetSoundFile( SvxShape* pShape )
{
	OUString aSoundFile;

	if( pShape )
	{
		SdrObject* pObj = pShape->GetSdrObject();
		if( pObj && pObj->GetPage() )
		{
			sd::MainSequencePtr pMainSequence = static_cast<SdPage*>(pObj->GetPage())->getMainSequence();

			const Reference< XShape > xShape( pShape );

			EffectSequence::iterator aIter;
			
			for(	aIter = pMainSequence->getBegin();
					(aSoundFile.getLength() == 0) && (aIter != pMainSequence->getEnd());
					aIter++ )
			{
				CustomAnimationEffectPtr pEffect( (*aIter) );
				if( pEffect->getTargetShape() == xShape )
				{
					if( pEffect->getAudio().is() )
						pEffect->getAudio()->getSource() >>= aSoundFile;
				}
			}
		}
	}
	return aSoundFile;
}

// --------------------------------------------------------------------

sal_Bool EffectMigration::GetSoundOn( SvxShape* pShape )
{
	return GetSoundFile( pShape ).getLength() != 0;
}

// --------------------------------------------------------------------

void EffectMigration::SetAnimationPath( SvxShape* pShape, SdrPathObj* pPathObj )
{
	if( pShape && pPathObj )
	{
		SdrObject* pObj = pShape->GetSdrObject();

		if( pObj )
		{
			//sd::MainSequencePtr pMainSequence = static_cast<SdPage*>(pObj->GetPage())->getMainSequence();

			const Reference< XShape > xShape( pShape );
			SdPage* pPage = dynamic_cast< SdPage* >( pPathObj ? pPathObj->GetPage() : 0 );
			if( pPage )
			{
				boost::shared_ptr< sd::MainSequence > pMainSequence( pPage->getMainSequence() );
				if( pMainSequence.get() )
					CustomAnimationEffectPtr pCreated( pMainSequence->append( *pPathObj, makeAny( xShape ), -1.0 ) );
			}
		}
	}
}


