15b190011SAndrew Rist /**************************************************************
2cdf0e10cSrcweir  *
35b190011SAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
45b190011SAndrew Rist  * or more contributor license agreements.  See the NOTICE file
55b190011SAndrew Rist  * distributed with this work for additional information
65b190011SAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
75b190011SAndrew Rist  * to you under the Apache License, Version 2.0 (the
85b190011SAndrew Rist  * "License"); you may not use this file except in compliance
95b190011SAndrew Rist  * with the License.  You may obtain a copy of the License at
105b190011SAndrew Rist  *
115b190011SAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
125b190011SAndrew Rist  *
135b190011SAndrew Rist  * Unless required by applicable law or agreed to in writing,
145b190011SAndrew Rist  * software distributed under the License is distributed on an
155b190011SAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
165b190011SAndrew Rist  * KIND, either express or implied.  See the License for the
175b190011SAndrew Rist  * specific language governing permissions and limitations
185b190011SAndrew Rist  * under the License.
195b190011SAndrew Rist  *
205b190011SAndrew Rist  *************************************************************/
215b190011SAndrew Rist 
225b190011SAndrew Rist 
23cdf0e10cSrcweir 
24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
25cdf0e10cSrcweir #include "precompiled_sd.hxx"
26cdf0e10cSrcweir #include <tools/debug.hxx>
27cdf0e10cSrcweir #include <com/sun/star/util/XCloneable.hpp>
28cdf0e10cSrcweir #include <com/sun/star/animations/AnimationFill.hpp>
29cdf0e10cSrcweir #include <com/sun/star/container/XEnumerationAccess.hpp>
30cdf0e10cSrcweir #include <com/sun/star/presentation/EffectNodeType.hpp>
31cdf0e10cSrcweir #include <com/sun/star/presentation/EffectCommands.hpp>
32cdf0e10cSrcweir #include <com/sun/star/presentation/EffectPresetClass.hpp>
33cdf0e10cSrcweir #include <com/sun/star/presentation/ParagraphTarget.hpp>
34cdf0e10cSrcweir #include <com/sun/star/lang/XInitialization.hpp>
35cdf0e10cSrcweir #include <com/sun/star/presentation/ShapeAnimationSubType.hpp>
36cdf0e10cSrcweir #include <com/sun/star/animations/AnimationNodeType.hpp>
37cdf0e10cSrcweir #include <com/sun/star/animations/XCommand.hpp>
38cdf0e10cSrcweir #include <com/sun/star/animations/AnimationTransformType.hpp>
39cdf0e10cSrcweir #include <com/sun/star/animations/XIterateContainer.hpp>
40cdf0e10cSrcweir #include <com/sun/star/animations/XAnimateTransform.hpp>
41cdf0e10cSrcweir #include <com/sun/star/animations/Event.hpp>
42cdf0e10cSrcweir #include <com/sun/star/animations/EventTrigger.hpp>
43cdf0e10cSrcweir #include <com/sun/star/animations/Timing.hpp>
44cdf0e10cSrcweir #include <com/sun/star/drawing/XDrawPage.hpp>
45cdf0e10cSrcweir #include <com/sun/star/text/XText.hpp>
46cdf0e10cSrcweir #include <com/sun/star/animations/XAnimate.hpp>
47cdf0e10cSrcweir #include <com/sun/star/beans/NamedValue.hpp>
48cdf0e10cSrcweir #include <com/sun/star/beans/XPropertySet.hpp>
49cdf0e10cSrcweir #include <com/sun/star/util/XChangesNotifier.hpp>
50cdf0e10cSrcweir #include <com/sun/star/animations/XAnimateMotion.hpp>
51cdf0e10cSrcweir #include <comphelper/processfactory.hxx>
52cdf0e10cSrcweir #include <comphelper/sequence.hxx>
53cdf0e10cSrcweir #include <com/sun/star/lang/Locale.hpp>
54cdf0e10cSrcweir #include <com/sun/star/i18n/XBreakIterator.hpp>
55cdf0e10cSrcweir #include <com/sun/star/i18n/CharacterIteratorMode.hpp>
56cdf0e10cSrcweir #ifndef _COM_SUN_STAR_TEXT_WORDTYPE_HPP_
57cdf0e10cSrcweir #include <com/sun/star/i18n/WordType.hpp>
58cdf0e10cSrcweir #endif
59cdf0e10cSrcweir #include <com/sun/star/presentation/TextAnimationType.hpp>
60cdf0e10cSrcweir 
61cdf0e10cSrcweir #include <basegfx/polygon/b2dpolypolygon.hxx>
62cdf0e10cSrcweir #include <basegfx/polygon/b2dpolypolygontools.hxx>
63cdf0e10cSrcweir #include <basegfx/matrix/b2dhommatrix.hxx>
64cdf0e10cSrcweir #include <basegfx/range/b2drange.hxx>
65cdf0e10cSrcweir #include <basegfx/matrix/b2dhommatrixtools.hxx>
66cdf0e10cSrcweir 
67cdf0e10cSrcweir #include <algorithm>
68cdf0e10cSrcweir 
69cdf0e10cSrcweir #include <cppuhelper/implbase1.hxx>
70cdf0e10cSrcweir 
71cdf0e10cSrcweir #include <drawinglayer/geometry/viewinformation2d.hxx>
72cdf0e10cSrcweir #include <svx/sdr/contact/viewcontact.hxx>
73cdf0e10cSrcweir #include <svx/svdopath.hxx>
74cdf0e10cSrcweir #include <svx/svdpage.hxx>
75cdf0e10cSrcweir #include <svx/unoapi.hxx>
76cdf0e10cSrcweir #include "CustomAnimationEffect.hxx"
77cdf0e10cSrcweir #include <CustomAnimationPreset.hxx>
78cdf0e10cSrcweir #include "animations.hxx"
79cdf0e10cSrcweir 
80cdf0e10cSrcweir using namespace ::com::sun::star;
81cdf0e10cSrcweir using namespace ::com::sun::star::presentation;
82cdf0e10cSrcweir using namespace ::com::sun::star::animations;
83cdf0e10cSrcweir 
84cdf0e10cSrcweir using ::rtl::OUString;
85cdf0e10cSrcweir using ::com::sun::star::uno::Reference;
86cdf0e10cSrcweir using ::com::sun::star::uno::Sequence;
87cdf0e10cSrcweir using ::com::sun::star::uno::XInterface;
88cdf0e10cSrcweir using ::com::sun::star::uno::UNO_QUERY;
89cdf0e10cSrcweir using ::com::sun::star::uno::UNO_QUERY_THROW;
90cdf0e10cSrcweir using ::com::sun::star::uno::Any;
91cdf0e10cSrcweir using ::com::sun::star::uno::makeAny;
92cdf0e10cSrcweir using ::com::sun::star::uno::Exception;
93cdf0e10cSrcweir using ::com::sun::star::uno::RuntimeException;
94cdf0e10cSrcweir using ::com::sun::star::container::XEnumerationAccess;
95cdf0e10cSrcweir using ::com::sun::star::container::XEnumeration;
96cdf0e10cSrcweir using ::com::sun::star::beans::NamedValue;
97cdf0e10cSrcweir using ::com::sun::star::container::XChild;
98cdf0e10cSrcweir using ::com::sun::star::container::XElementAccess;
99cdf0e10cSrcweir using ::com::sun::star::drawing::XShape;
100cdf0e10cSrcweir using ::com::sun::star::lang::XInitialization;
101cdf0e10cSrcweir using ::com::sun::star::drawing::XShapes;
102cdf0e10cSrcweir using ::com::sun::star::drawing::XDrawPage;
103cdf0e10cSrcweir using ::com::sun::star::text::XText;
104cdf0e10cSrcweir using ::com::sun::star::text::XTextRange;
105cdf0e10cSrcweir using ::com::sun::star::beans::XPropertySet;
106cdf0e10cSrcweir using ::com::sun::star::lang::XMultiServiceFactory;
107cdf0e10cSrcweir using ::com::sun::star::util::XCloneable;
108cdf0e10cSrcweir using ::com::sun::star::lang::Locale;
109cdf0e10cSrcweir using ::com::sun::star::util::XChangesNotifier;
110cdf0e10cSrcweir using ::com::sun::star::util::XChangesListener;
111cdf0e10cSrcweir 
112cdf0e10cSrcweir namespace sd
113cdf0e10cSrcweir {
114cdf0e10cSrcweir class MainSequenceChangeGuard
115cdf0e10cSrcweir {
116cdf0e10cSrcweir public:
117cdf0e10cSrcweir 	MainSequenceChangeGuard( EffectSequenceHelper* pSequence )
118cdf0e10cSrcweir 	{
119cdf0e10cSrcweir 		mpMainSequence = dynamic_cast< MainSequence* >( pSequence );
120cdf0e10cSrcweir 		if( mpMainSequence == 0 )
121cdf0e10cSrcweir 		{
122cdf0e10cSrcweir 			InteractiveSequence* pI = dynamic_cast< InteractiveSequence* >( pSequence );
123cdf0e10cSrcweir 			if( pI )
124cdf0e10cSrcweir 				mpMainSequence = pI->mpMainSequence;
125cdf0e10cSrcweir 		}
126cdf0e10cSrcweir 		DBG_ASSERT( mpMainSequence, "sd::MainSequenceChangeGuard::MainSequenceChangeGuard(), no main sequence to guard!" );
127cdf0e10cSrcweir 
128cdf0e10cSrcweir 		if( mpMainSequence )
129cdf0e10cSrcweir 			mpMainSequence->mbIgnoreChanges++;
130cdf0e10cSrcweir 	}
131cdf0e10cSrcweir 
132cdf0e10cSrcweir 	~MainSequenceChangeGuard()
133cdf0e10cSrcweir 	{
134cdf0e10cSrcweir 		if( mpMainSequence )
135cdf0e10cSrcweir 			mpMainSequence->mbIgnoreChanges++;
136cdf0e10cSrcweir 	}
137cdf0e10cSrcweir 
138cdf0e10cSrcweir private:
139cdf0e10cSrcweir 	MainSequence* mpMainSequence;
140cdf0e10cSrcweir };
141cdf0e10cSrcweir 
142cdf0e10cSrcweir CustomAnimationEffect::CustomAnimationEffect( const ::com::sun::star::uno::Reference< ::com::sun::star::animations::XAnimationNode >& xNode )
143cdf0e10cSrcweir :	mnNodeType(-1),
144cdf0e10cSrcweir 	mnPresetClass(-1),
145cdf0e10cSrcweir 	mfBegin(-1.0),
146cdf0e10cSrcweir 	mfDuration(-1.0),
147cdf0e10cSrcweir 	mfAbsoluteDuration(-1.0),
148cdf0e10cSrcweir 	mnGroupId(-1),
149cdf0e10cSrcweir 	mnIterateType(0),
150cdf0e10cSrcweir 	mfIterateInterval(0.0),
151cdf0e10cSrcweir 	mnParaDepth( -1 ),
152cdf0e10cSrcweir 	mbHasText(sal_False),
153cdf0e10cSrcweir 	mfAcceleration( 1.0 ),
154cdf0e10cSrcweir 	mfDecelerate( 1.0 ),
155cdf0e10cSrcweir 	mbAutoReverse(false),
156cdf0e10cSrcweir 	mnTargetSubItem(0),
157cdf0e10cSrcweir 	mnCommand(0),
158cdf0e10cSrcweir 	mpEffectSequence( 0 ),
159cdf0e10cSrcweir 	mbHasAfterEffect(false),
160cdf0e10cSrcweir 	mbAfterEffectOnNextEffect(false)
161cdf0e10cSrcweir {
162cdf0e10cSrcweir 	setNode( xNode );
163cdf0e10cSrcweir }
164cdf0e10cSrcweir 
165cdf0e10cSrcweir // --------------------------------------------------------------------
166cdf0e10cSrcweir 
167cdf0e10cSrcweir void CustomAnimationEffect::setNode( const ::com::sun::star::uno::Reference< ::com::sun::star::animations::XAnimationNode >& xNode )
168cdf0e10cSrcweir {
169cdf0e10cSrcweir 	mxNode = xNode;
170cdf0e10cSrcweir 	mxAudio.clear();
171cdf0e10cSrcweir 
172cdf0e10cSrcweir 	Sequence< NamedValue > aUserData( mxNode->getUserData() );
173cdf0e10cSrcweir 	sal_Int32 nLength = aUserData.getLength();
174cdf0e10cSrcweir 	const NamedValue* p = aUserData.getConstArray();
175cdf0e10cSrcweir 
176cdf0e10cSrcweir 	while( nLength-- )
177cdf0e10cSrcweir 	{
178cdf0e10cSrcweir         if( p->Name.equalsAscii( "node-type" ) )
179cdf0e10cSrcweir 		{
180cdf0e10cSrcweir 			p->Value >>= mnNodeType;
181cdf0e10cSrcweir 		}
182cdf0e10cSrcweir 		else if( p->Name.equalsAscii( "preset-id" ) )
183cdf0e10cSrcweir 		{
184cdf0e10cSrcweir 			p->Value >>= maPresetId;
185cdf0e10cSrcweir 		}
186cdf0e10cSrcweir 		else if( p->Name.equalsAscii( "preset-sub-type" ) )
187cdf0e10cSrcweir 		{
188cdf0e10cSrcweir 			p->Value >>= maPresetSubType;
189cdf0e10cSrcweir 		}
190cdf0e10cSrcweir 		else if( p->Name.equalsAscii( "preset-class" ) )
191cdf0e10cSrcweir 		{
192cdf0e10cSrcweir 			p->Value >>= mnPresetClass;
193cdf0e10cSrcweir 		}
194cdf0e10cSrcweir 		else if( p->Name.equalsAscii( "preset-property" ) )
195cdf0e10cSrcweir 		{
196cdf0e10cSrcweir 			p->Value >>= maProperty;
197cdf0e10cSrcweir 		}
198cdf0e10cSrcweir 		else if( p->Name.equalsAscii( "group-id" ) )
199cdf0e10cSrcweir 		{
200cdf0e10cSrcweir 			p->Value >>= mnGroupId;
201cdf0e10cSrcweir 		}
202cdf0e10cSrcweir 
203cdf0e10cSrcweir 		p++;
204cdf0e10cSrcweir 	}
205cdf0e10cSrcweir 
206cdf0e10cSrcweir 	// get effect start time
207cdf0e10cSrcweir 	mxNode->getBegin() >>= mfBegin;
208cdf0e10cSrcweir 
209cdf0e10cSrcweir 	mfAcceleration = mxNode->getAcceleration();
210cdf0e10cSrcweir 	mfDecelerate = mxNode->getDecelerate();
211cdf0e10cSrcweir 	mbAutoReverse = mxNode->getAutoReverse();
212cdf0e10cSrcweir 
213cdf0e10cSrcweir 	// get iteration data
214cdf0e10cSrcweir 	Reference< XIterateContainer > xIter( mxNode, UNO_QUERY );
215cdf0e10cSrcweir 	if( xIter.is() )
216cdf0e10cSrcweir 	{
217cdf0e10cSrcweir 		mfIterateInterval = xIter->getIterateInterval();
218cdf0e10cSrcweir 		mnIterateType = xIter->getIterateType();
219cdf0e10cSrcweir 		maTarget = xIter->getTarget();
220cdf0e10cSrcweir 		mnTargetSubItem = xIter->getSubItem();
221cdf0e10cSrcweir 	}
222cdf0e10cSrcweir 	else
223cdf0e10cSrcweir 	{
224cdf0e10cSrcweir 		mfIterateInterval = 0.0f;
225cdf0e10cSrcweir 		mnIterateType = 0;
226cdf0e10cSrcweir 	}
227cdf0e10cSrcweir 
228cdf0e10cSrcweir 	// calculate effect duration and get target shape
229cdf0e10cSrcweir 	Reference< XEnumerationAccess > xEnumerationAccess( mxNode, UNO_QUERY );
230cdf0e10cSrcweir 	if( xEnumerationAccess.is() )
231cdf0e10cSrcweir 	{
232cdf0e10cSrcweir 		Reference< XEnumeration > xEnumeration( xEnumerationAccess->createEnumeration(), UNO_QUERY );
233cdf0e10cSrcweir 		if( xEnumeration.is() )
234cdf0e10cSrcweir 		{
235cdf0e10cSrcweir 			while( xEnumeration->hasMoreElements() )
236cdf0e10cSrcweir 			{
237cdf0e10cSrcweir 				Reference< XAnimationNode > xChildNode( xEnumeration->nextElement(), UNO_QUERY );
238cdf0e10cSrcweir 				if( !xChildNode.is() )
239cdf0e10cSrcweir 					continue;
240cdf0e10cSrcweir 
241cdf0e10cSrcweir 				if( xChildNode->getType() == AnimationNodeType::AUDIO )
242cdf0e10cSrcweir 				{
243cdf0e10cSrcweir 					mxAudio.set( xChildNode, UNO_QUERY );
244cdf0e10cSrcweir 				}
245cdf0e10cSrcweir 				else if( xChildNode->getType() == AnimationNodeType::COMMAND )
246cdf0e10cSrcweir 				{
247cdf0e10cSrcweir 					Reference< XCommand > xCommand( xChildNode, UNO_QUERY );
248cdf0e10cSrcweir 					if( xCommand.is() )
249cdf0e10cSrcweir 					{
250cdf0e10cSrcweir 						mnCommand = xCommand->getCommand();
251cdf0e10cSrcweir 						if( !maTarget.hasValue() )
252cdf0e10cSrcweir 							maTarget = xCommand->getTarget();
253cdf0e10cSrcweir 					}
254cdf0e10cSrcweir 				}
255cdf0e10cSrcweir 				else
256cdf0e10cSrcweir 				{
257cdf0e10cSrcweir 					double fBegin = 0.0;
258cdf0e10cSrcweir 					double fDuration = 0.0;
259cdf0e10cSrcweir 					xChildNode->getBegin() >>= fBegin;
260cdf0e10cSrcweir 					xChildNode->getDuration() >>= fDuration;
261cdf0e10cSrcweir 
262cdf0e10cSrcweir 					fDuration += fBegin;
263cdf0e10cSrcweir 					if( fDuration > mfDuration )
264cdf0e10cSrcweir 						mfDuration = fDuration;
265cdf0e10cSrcweir 
266cdf0e10cSrcweir 					// no target shape yet?
267cdf0e10cSrcweir 					if( !maTarget.hasValue() )
268cdf0e10cSrcweir 					{
269cdf0e10cSrcweir 						// go get it boys!
270cdf0e10cSrcweir 						Reference< XAnimate > xAnimate( xChildNode, UNO_QUERY );
271cdf0e10cSrcweir 						if( xAnimate.is() )
272cdf0e10cSrcweir 						{
273cdf0e10cSrcweir 							maTarget = xAnimate->getTarget();
274cdf0e10cSrcweir 							mnTargetSubItem = xAnimate->getSubItem();
275cdf0e10cSrcweir 						}
276cdf0e10cSrcweir 					}
277cdf0e10cSrcweir 				}
278cdf0e10cSrcweir 			}
279cdf0e10cSrcweir 		}
280cdf0e10cSrcweir 	}
281cdf0e10cSrcweir 
282cdf0e10cSrcweir 	mfAbsoluteDuration = mfDuration;
283cdf0e10cSrcweir 	checkForText();
284cdf0e10cSrcweir }
285cdf0e10cSrcweir 
286cdf0e10cSrcweir // --------------------------------------------------------------------
287cdf0e10cSrcweir 
288cdf0e10cSrcweir sal_Int32 CustomAnimationEffect::getNumberOfSubitems( const Any& aTarget, sal_Int16 nIterateType )
289cdf0e10cSrcweir {
290cdf0e10cSrcweir 	sal_Int32 nSubItems = 0;
291cdf0e10cSrcweir 
292cdf0e10cSrcweir 	try
293cdf0e10cSrcweir 	{
294cdf0e10cSrcweir 		// first get target text
295cdf0e10cSrcweir 		sal_Int32 nOnlyPara = -1;
296cdf0e10cSrcweir 
297cdf0e10cSrcweir 		Reference< XText > xShape;
298cdf0e10cSrcweir 		aTarget >>= xShape;
299cdf0e10cSrcweir 		if( !xShape.is() )
300cdf0e10cSrcweir 		{
301cdf0e10cSrcweir 			ParagraphTarget aParaTarget;
302cdf0e10cSrcweir 			if( aTarget >>= aParaTarget )
303cdf0e10cSrcweir 			{
304cdf0e10cSrcweir 				xShape.set( aParaTarget.Shape, UNO_QUERY );
305cdf0e10cSrcweir 				nOnlyPara = aParaTarget.Paragraph;
306cdf0e10cSrcweir 			}
307cdf0e10cSrcweir 		}
308cdf0e10cSrcweir 
309cdf0e10cSrcweir 		// now use the break iterator to iterate over the given text
310cdf0e10cSrcweir 		// and count the sub items
311cdf0e10cSrcweir 
312cdf0e10cSrcweir 		if( xShape.is() )
313cdf0e10cSrcweir 		{
314cdf0e10cSrcweir 			// TODO/LATER: Optimize this, don't create a break iterator each time
315cdf0e10cSrcweir 			Reference< lang::XMultiServiceFactory > xMSF( ::comphelper::getProcessServiceFactory() );
316cdf0e10cSrcweir 			Reference < i18n::XBreakIterator > xBI( xMSF->createInstance( OUString::createFromAscii( "com.sun.star.i18n.BreakIterator" ) ), UNO_QUERY );
317cdf0e10cSrcweir 			DBG_ASSERT( xBI.is(), "sd::CustomAnimationEffect::getNumberOfSubitems(), could not create a 'com.sun.star.i18n.BreakIterator'!" );
318cdf0e10cSrcweir 
319cdf0e10cSrcweir 			if( xBI.is() )
320cdf0e10cSrcweir 			{
321cdf0e10cSrcweir 				Reference< XEnumerationAccess > xEA( xShape, UNO_QUERY_THROW );
322cdf0e10cSrcweir 				Reference< XEnumeration > xEnumeration( xEA->createEnumeration(), UNO_QUERY_THROW );
323cdf0e10cSrcweir 				Locale aLocale;
324cdf0e10cSrcweir 				const OUString aStrLocaleName( RTL_CONSTASCII_USTRINGPARAM("CharLocale") );
325cdf0e10cSrcweir 				Reference< XTextRange > xParagraph;
326cdf0e10cSrcweir 
327cdf0e10cSrcweir 				sal_Int32 nPara = 0;
328cdf0e10cSrcweir 				while( xEnumeration->hasMoreElements() )
329cdf0e10cSrcweir 				{
330cdf0e10cSrcweir 					xEnumeration->nextElement() >>= xParagraph;
331cdf0e10cSrcweir 
332cdf0e10cSrcweir 					// skip this if its not the only paragraph we want to count
333cdf0e10cSrcweir 					if( (nOnlyPara != -1) && (nOnlyPara != nPara ) )
334cdf0e10cSrcweir 						continue;
335cdf0e10cSrcweir 
336cdf0e10cSrcweir 					if( nIterateType == TextAnimationType::BY_PARAGRAPH )
337cdf0e10cSrcweir 					{
338cdf0e10cSrcweir 						nSubItems++;
339cdf0e10cSrcweir 					}
340cdf0e10cSrcweir 					else
341cdf0e10cSrcweir 					{
342cdf0e10cSrcweir 						const OUString aText( xParagraph->getString() );
343cdf0e10cSrcweir 						Reference< XPropertySet > xSet( xParagraph, UNO_QUERY_THROW );
344cdf0e10cSrcweir 						xSet->getPropertyValue( aStrLocaleName ) >>= aLocale;
345cdf0e10cSrcweir 
346cdf0e10cSrcweir 						sal_Int32 nPos;
347cdf0e10cSrcweir 						const sal_Int32 nEndPos = aText.getLength();
348cdf0e10cSrcweir 
349cdf0e10cSrcweir 						if( nIterateType == TextAnimationType::BY_WORD )
350cdf0e10cSrcweir 						{
351cdf0e10cSrcweir 							for( nPos = 0; nPos < nEndPos; nPos++ )
352cdf0e10cSrcweir 							{
353cdf0e10cSrcweir 								nPos = xBI->getWordBoundary(aText, nPos, aLocale, i18n::WordType::ANY_WORD, sal_True).endPos;
354cdf0e10cSrcweir 								nSubItems++;
355cdf0e10cSrcweir 							}
356cdf0e10cSrcweir 							break;
357cdf0e10cSrcweir 						}
358cdf0e10cSrcweir 						else
359cdf0e10cSrcweir 						{
360cdf0e10cSrcweir 							sal_Int32 nDone;
361cdf0e10cSrcweir 							for( nPos = 0; nPos < nEndPos; nPos++ )
362cdf0e10cSrcweir 							{
363cdf0e10cSrcweir 								nPos = xBI->nextCharacters(aText, nPos, aLocale, i18n::CharacterIteratorMode::SKIPCELL, 0, nDone);
364cdf0e10cSrcweir 								nSubItems++;
365cdf0e10cSrcweir 							}
366cdf0e10cSrcweir 						}
367cdf0e10cSrcweir 					}
368cdf0e10cSrcweir 
369cdf0e10cSrcweir 					if( nPara == nOnlyPara )
370cdf0e10cSrcweir 						break;
371cdf0e10cSrcweir 
372cdf0e10cSrcweir 					nPara++;
373cdf0e10cSrcweir 				}
374cdf0e10cSrcweir 			}
375cdf0e10cSrcweir 		}
376cdf0e10cSrcweir 	}
377cdf0e10cSrcweir 	catch( Exception& e )
378cdf0e10cSrcweir 	{
379cdf0e10cSrcweir 		(void)e;
380cdf0e10cSrcweir 		nSubItems = 0;
381cdf0e10cSrcweir 		DBG_ERROR( "sd::CustomAnimationEffect::getNumberOfSubitems(), exception cought!" );
382cdf0e10cSrcweir 	}
383cdf0e10cSrcweir 
384cdf0e10cSrcweir 	return nSubItems;
385cdf0e10cSrcweir }
386cdf0e10cSrcweir 
387cdf0e10cSrcweir // --------------------------------------------------------------------
388cdf0e10cSrcweir 
389cdf0e10cSrcweir CustomAnimationEffect::~CustomAnimationEffect()
390cdf0e10cSrcweir {
391cdf0e10cSrcweir }
392cdf0e10cSrcweir 
393cdf0e10cSrcweir // --------------------------------------------------------------------
394cdf0e10cSrcweir 
395cdf0e10cSrcweir CustomAnimationEffectPtr CustomAnimationEffect::clone() const
396cdf0e10cSrcweir {
397cdf0e10cSrcweir 	Reference< XCloneable > xCloneable( mxNode, UNO_QUERY_THROW );
398cdf0e10cSrcweir 	Reference< XAnimationNode > xNode( xCloneable->createClone(), UNO_QUERY_THROW );
399cdf0e10cSrcweir 	CustomAnimationEffectPtr pEffect( new CustomAnimationEffect( xNode ) );
400cdf0e10cSrcweir 	pEffect->setEffectSequence( getEffectSequence() );
401cdf0e10cSrcweir 	return pEffect;
402cdf0e10cSrcweir }
403cdf0e10cSrcweir 
404cdf0e10cSrcweir // --------------------------------------------------------------------
405cdf0e10cSrcweir 
406cdf0e10cSrcweir sal_Int32 CustomAnimationEffect::get_node_type( const Reference< XAnimationNode >& xNode )
407cdf0e10cSrcweir {
408cdf0e10cSrcweir 	sal_Int16 nNodeType = -1;
409cdf0e10cSrcweir 
410cdf0e10cSrcweir 	if( xNode.is() )
411cdf0e10cSrcweir 	{
412cdf0e10cSrcweir 		Sequence< NamedValue > aUserData( xNode->getUserData() );
413cdf0e10cSrcweir 		sal_Int32 nLength = aUserData.getLength();
414cdf0e10cSrcweir 		if( nLength )
415cdf0e10cSrcweir 		{
416cdf0e10cSrcweir 			const NamedValue* p = aUserData.getConstArray();
417cdf0e10cSrcweir 			while( nLength-- )
418cdf0e10cSrcweir 			{
419cdf0e10cSrcweir 				if( p->Name.equalsAscii( "node-type" ) )
420cdf0e10cSrcweir 				{
421cdf0e10cSrcweir 					p->Value >>= nNodeType;
422cdf0e10cSrcweir 					break;
423cdf0e10cSrcweir 				}
424cdf0e10cSrcweir 				p++;
425cdf0e10cSrcweir 			}
426cdf0e10cSrcweir 		}
427cdf0e10cSrcweir 	}
428cdf0e10cSrcweir 
429cdf0e10cSrcweir 	return nNodeType;
430cdf0e10cSrcweir }
431cdf0e10cSrcweir 
432cdf0e10cSrcweir // --------------------------------------------------------------------
433cdf0e10cSrcweir 
434cdf0e10cSrcweir void CustomAnimationEffect::setPresetClass( sal_Int16 nPresetClass )
435cdf0e10cSrcweir {
436cdf0e10cSrcweir 	if( mnPresetClass != nPresetClass )
437cdf0e10cSrcweir 	{
438cdf0e10cSrcweir 		mnPresetClass = nPresetClass;
439cdf0e10cSrcweir 		if( mxNode.is() )
440cdf0e10cSrcweir 		{
441cdf0e10cSrcweir 			// first try to find a "preset-class" entry in the user data
442cdf0e10cSrcweir 			// and change it
443cdf0e10cSrcweir 			Sequence< NamedValue > aUserData( mxNode->getUserData() );
444cdf0e10cSrcweir 			sal_Int32 nLength = aUserData.getLength();
445cdf0e10cSrcweir 			bool bFound = false;
446cdf0e10cSrcweir 			if( nLength )
447cdf0e10cSrcweir 			{
448cdf0e10cSrcweir 				NamedValue* p = aUserData.getArray();
449cdf0e10cSrcweir 				while( nLength-- )
450cdf0e10cSrcweir 				{
451cdf0e10cSrcweir 					if( p->Name.equalsAscii( "preset-class" ) )
452cdf0e10cSrcweir 					{
453cdf0e10cSrcweir 						p->Value <<= mnPresetClass;
454cdf0e10cSrcweir 						bFound = true;
455cdf0e10cSrcweir 						break;
456cdf0e10cSrcweir 					}
457cdf0e10cSrcweir 					p++;
458cdf0e10cSrcweir 				}
459cdf0e10cSrcweir 			}
460cdf0e10cSrcweir 
461cdf0e10cSrcweir 			// no "node-type" entry inside user data, so add it
462cdf0e10cSrcweir 			if( !bFound )
463cdf0e10cSrcweir 			{
464cdf0e10cSrcweir 				nLength = aUserData.getLength();
465cdf0e10cSrcweir 				aUserData.realloc( nLength + 1);
466cdf0e10cSrcweir 				aUserData[nLength].Name = OUString( RTL_CONSTASCII_USTRINGPARAM( "preset-class" ) );
467cdf0e10cSrcweir 				aUserData[nLength].Value <<= mnPresetClass;
468cdf0e10cSrcweir 			}
469cdf0e10cSrcweir 
470cdf0e10cSrcweir 			mxNode->setUserData( aUserData );
471cdf0e10cSrcweir 		}
472cdf0e10cSrcweir 	}
473cdf0e10cSrcweir }
474cdf0e10cSrcweir 
475cdf0e10cSrcweir void CustomAnimationEffect::setNodeType( sal_Int16 nNodeType )
476cdf0e10cSrcweir {
477cdf0e10cSrcweir 	if( mnNodeType != nNodeType )
478cdf0e10cSrcweir 	{
479cdf0e10cSrcweir 		mnNodeType = nNodeType;
480cdf0e10cSrcweir 		if( mxNode.is() )
481cdf0e10cSrcweir 		{
482cdf0e10cSrcweir 			// first try to find a "node-type" entry in the user data
483cdf0e10cSrcweir 			// and change it
484cdf0e10cSrcweir 			Sequence< NamedValue > aUserData( mxNode->getUserData() );
485cdf0e10cSrcweir 			sal_Int32 nLength = aUserData.getLength();
486cdf0e10cSrcweir 			bool bFound = false;
487cdf0e10cSrcweir 			if( nLength )
488cdf0e10cSrcweir 			{
489cdf0e10cSrcweir 				NamedValue* p = aUserData.getArray();
490cdf0e10cSrcweir 				while( nLength-- )
491cdf0e10cSrcweir 				{
492cdf0e10cSrcweir 					if( p->Name.equalsAscii( "node-type" ) )
493cdf0e10cSrcweir 					{
494cdf0e10cSrcweir 						p->Value <<= mnNodeType;
495cdf0e10cSrcweir 						bFound = true;
496cdf0e10cSrcweir 						break;
497cdf0e10cSrcweir 					}
498cdf0e10cSrcweir 					p++;
499cdf0e10cSrcweir 				}
500cdf0e10cSrcweir 			}
501cdf0e10cSrcweir 
502cdf0e10cSrcweir 			// no "node-type" entry inside user data, so add it
503cdf0e10cSrcweir 			if( !bFound )
504cdf0e10cSrcweir 			{
505cdf0e10cSrcweir 				nLength = aUserData.getLength();
506cdf0e10cSrcweir 				aUserData.realloc( nLength + 1);
507cdf0e10cSrcweir 				aUserData[nLength].Name = OUString( RTL_CONSTASCII_USTRINGPARAM( "node-type" ) );
508cdf0e10cSrcweir 				aUserData[nLength].Value <<= mnNodeType;
509cdf0e10cSrcweir 			}
510cdf0e10cSrcweir 
511cdf0e10cSrcweir 			mxNode->setUserData( aUserData );
512cdf0e10cSrcweir 		}
513cdf0e10cSrcweir 	}
514cdf0e10cSrcweir }
515cdf0e10cSrcweir 
516cdf0e10cSrcweir // --------------------------------------------------------------------
517cdf0e10cSrcweir 
518cdf0e10cSrcweir void CustomAnimationEffect::setGroupId( sal_Int32 nGroupId )
519cdf0e10cSrcweir {
520cdf0e10cSrcweir 	mnGroupId = nGroupId;
521cdf0e10cSrcweir 	if( mxNode.is() )
522cdf0e10cSrcweir 	{
523cdf0e10cSrcweir 		// first try to find a "group-id" entry in the user data
524cdf0e10cSrcweir 		// and change it
525cdf0e10cSrcweir 		Sequence< NamedValue > aUserData( mxNode->getUserData() );
526cdf0e10cSrcweir 		sal_Int32 nLength = aUserData.getLength();
527cdf0e10cSrcweir 		bool bFound = false;
528cdf0e10cSrcweir 		if( nLength )
529cdf0e10cSrcweir 		{
530cdf0e10cSrcweir 			NamedValue* p = aUserData.getArray();
531cdf0e10cSrcweir 			while( nLength-- )
532cdf0e10cSrcweir 			{
533cdf0e10cSrcweir 				if( p->Name.equalsAscii( "group-id" ) )
534cdf0e10cSrcweir 				{
535cdf0e10cSrcweir 					p->Value <<= mnGroupId;
536cdf0e10cSrcweir 					bFound = true;
537cdf0e10cSrcweir 					break;
538cdf0e10cSrcweir 				}
539cdf0e10cSrcweir 				p++;
540cdf0e10cSrcweir 			}
541cdf0e10cSrcweir 		}
542cdf0e10cSrcweir 
543cdf0e10cSrcweir 		// no "node-type" entry inside user data, so add it
544cdf0e10cSrcweir 		if( !bFound )
545cdf0e10cSrcweir 		{
546cdf0e10cSrcweir 			nLength = aUserData.getLength();
547cdf0e10cSrcweir 			aUserData.realloc( nLength + 1);
548cdf0e10cSrcweir 			aUserData[nLength].Name = OUString( RTL_CONSTASCII_USTRINGPARAM( "group-id" ) );
549cdf0e10cSrcweir 			aUserData[nLength].Value <<= mnGroupId;
550cdf0e10cSrcweir 		}
551cdf0e10cSrcweir 
552cdf0e10cSrcweir 		mxNode->setUserData( aUserData );
553cdf0e10cSrcweir 	}
554cdf0e10cSrcweir }
555cdf0e10cSrcweir 
556cdf0e10cSrcweir // --------------------------------------------------------------------
557cdf0e10cSrcweir 
558cdf0e10cSrcweir /** checks if the text for this effect has changed and updates internal flags.
559cdf0e10cSrcweir 	returns true if something changed.
560cdf0e10cSrcweir */
561cdf0e10cSrcweir bool CustomAnimationEffect::checkForText()
562cdf0e10cSrcweir {
563cdf0e10cSrcweir 	bool bChange = false;
564cdf0e10cSrcweir 
565cdf0e10cSrcweir 	Reference< XText > xText;
566cdf0e10cSrcweir 
567cdf0e10cSrcweir 	if( maTarget.getValueType() == ::getCppuType((const ParagraphTarget*)0) )
568cdf0e10cSrcweir 	{
569cdf0e10cSrcweir 		// calc para depth
570cdf0e10cSrcweir 		ParagraphTarget aParaTarget;
571cdf0e10cSrcweir 		maTarget >>= aParaTarget;
572cdf0e10cSrcweir 
573cdf0e10cSrcweir 		xText = Reference< XText >::query( aParaTarget.Shape );
574cdf0e10cSrcweir 
575cdf0e10cSrcweir 		// get paragraph
576cdf0e10cSrcweir 		if( xText.is() )
577cdf0e10cSrcweir 		{
578cdf0e10cSrcweir 			Reference< XEnumerationAccess > xEA( xText, UNO_QUERY );
579cdf0e10cSrcweir 			if( xEA.is() )
580cdf0e10cSrcweir 			{
581cdf0e10cSrcweir 				Reference< XEnumeration > xEnumeration( xEA->createEnumeration(), UNO_QUERY );
582cdf0e10cSrcweir 				if( xEnumeration.is() )
583cdf0e10cSrcweir 				{
584cdf0e10cSrcweir 					sal_Bool bHasText = xEnumeration->hasMoreElements();
585cdf0e10cSrcweir 					bChange |= bHasText != mbHasText;
586cdf0e10cSrcweir 					mbHasText = bHasText;
587cdf0e10cSrcweir 
588cdf0e10cSrcweir 					sal_Int32 nPara = aParaTarget.Paragraph;
589cdf0e10cSrcweir 
590cdf0e10cSrcweir 					while( xEnumeration->hasMoreElements() && nPara-- )
591cdf0e10cSrcweir 						xEnumeration->nextElement();
592cdf0e10cSrcweir 
593cdf0e10cSrcweir 					if( xEnumeration->hasMoreElements() )
594cdf0e10cSrcweir 					{
595cdf0e10cSrcweir 						Reference< XPropertySet > xParaSet;
596cdf0e10cSrcweir 						xEnumeration->nextElement() >>= xParaSet;
597cdf0e10cSrcweir 						if( xParaSet.is() )
598cdf0e10cSrcweir 						{
599cdf0e10cSrcweir 							sal_Int32 nParaDepth = 0;
600cdf0e10cSrcweir 							const OUString strNumberingLevel( RTL_CONSTASCII_USTRINGPARAM("NumberingLevel") );
601cdf0e10cSrcweir 							xParaSet->getPropertyValue( strNumberingLevel ) >>= nParaDepth;
602cdf0e10cSrcweir 							bChange |= nParaDepth != mnParaDepth;
603cdf0e10cSrcweir 							mnParaDepth = nParaDepth;
604cdf0e10cSrcweir 						}
605cdf0e10cSrcweir 					}
606cdf0e10cSrcweir 				}
607cdf0e10cSrcweir 			}
608cdf0e10cSrcweir 		}
609cdf0e10cSrcweir 	}
610cdf0e10cSrcweir 	else
611cdf0e10cSrcweir 	{
612cdf0e10cSrcweir 		maTarget >>= xText;
613cdf0e10cSrcweir 		sal_Bool bHasText = xText.is() && xText->getString().getLength();
614cdf0e10cSrcweir 		bChange |= bHasText != mbHasText;
615cdf0e10cSrcweir 		mbHasText = bHasText;
616cdf0e10cSrcweir 	}
617cdf0e10cSrcweir 
618cdf0e10cSrcweir 	bChange |= calculateIterateDuration();
619cdf0e10cSrcweir 	return bChange;
620cdf0e10cSrcweir }
621cdf0e10cSrcweir 
622cdf0e10cSrcweir bool CustomAnimationEffect::calculateIterateDuration()
623cdf0e10cSrcweir {
624cdf0e10cSrcweir 	bool bChange = false;
625cdf0e10cSrcweir 
626cdf0e10cSrcweir 	// if we have an iteration, we must also calculate the
627cdf0e10cSrcweir 	// 'true' container duration, that is
628cdf0e10cSrcweir 	// ( ( is form animated ) ? [contained effects duration] : 0 ) +
629cdf0e10cSrcweir 	// ( [number of animated children] - 1 ) * [interval-delay] + [contained effects duration]
630cdf0e10cSrcweir 	Reference< XIterateContainer > xIter( mxNode, UNO_QUERY );
631cdf0e10cSrcweir 	if( xIter.is() )
632cdf0e10cSrcweir 	{
633cdf0e10cSrcweir 		double fDuration = mfDuration;
634cdf0e10cSrcweir 		const double fSubEffectDuration = mfDuration;
635cdf0e10cSrcweir 
636cdf0e10cSrcweir 		if( mnTargetSubItem != ShapeAnimationSubType::ONLY_BACKGROUND ) // does not make sense for iterate container but better check
637cdf0e10cSrcweir 		{
638cdf0e10cSrcweir 			const sal_Int32 nSubItems = getNumberOfSubitems( maTarget, mnIterateType );
639cdf0e10cSrcweir 			if( nSubItems )
640cdf0e10cSrcweir 			{
641cdf0e10cSrcweir 				const double f = (nSubItems-1) * mfIterateInterval;
642cdf0e10cSrcweir 				fDuration += f;
643cdf0e10cSrcweir 			}
644cdf0e10cSrcweir 		}
645cdf0e10cSrcweir 
646cdf0e10cSrcweir 		// if we also animate the form first, we have to add the
647cdf0e10cSrcweir 		// sub effect duration to the whole effect duration
648cdf0e10cSrcweir 		if( mnTargetSubItem == ShapeAnimationSubType::AS_WHOLE )
649cdf0e10cSrcweir 			fDuration += fSubEffectDuration;
650cdf0e10cSrcweir 
651cdf0e10cSrcweir 		bChange |= fDuration != mfAbsoluteDuration;
652cdf0e10cSrcweir 		mfAbsoluteDuration = fDuration;
653cdf0e10cSrcweir 	}
654cdf0e10cSrcweir 
655cdf0e10cSrcweir 	return bChange;
656cdf0e10cSrcweir }
657cdf0e10cSrcweir 
658cdf0e10cSrcweir // --------------------------------------------------------------------
659cdf0e10cSrcweir 
660cdf0e10cSrcweir void CustomAnimationEffect::setTarget( const ::com::sun::star::uno::Any& rTarget )
661cdf0e10cSrcweir {
662cdf0e10cSrcweir 	try
663cdf0e10cSrcweir 	{
664cdf0e10cSrcweir 		maTarget = rTarget;
665cdf0e10cSrcweir 
666cdf0e10cSrcweir 		// first, check special case for random node
667cdf0e10cSrcweir 		Reference< XInitialization > xInit( mxNode, UNO_QUERY );
668cdf0e10cSrcweir 		if( xInit.is() )
669cdf0e10cSrcweir 		{
670cdf0e10cSrcweir 			const Sequence< Any > aArgs( &maTarget, 1 );
671cdf0e10cSrcweir 			xInit->initialize( aArgs );
672cdf0e10cSrcweir 		}
673cdf0e10cSrcweir 		else
674cdf0e10cSrcweir 		{
675cdf0e10cSrcweir 			Reference< XIterateContainer > xIter( mxNode, UNO_QUERY );
676cdf0e10cSrcweir 			if( xIter.is() )
677cdf0e10cSrcweir 			{
678cdf0e10cSrcweir 				xIter->setTarget(maTarget);
679cdf0e10cSrcweir 			}
680cdf0e10cSrcweir 			else
681cdf0e10cSrcweir 			{
682cdf0e10cSrcweir 				Reference< XEnumerationAccess > xEnumerationAccess( mxNode, UNO_QUERY );
683cdf0e10cSrcweir 				if( xEnumerationAccess.is() )
684cdf0e10cSrcweir 				{
685cdf0e10cSrcweir 					Reference< XEnumeration > xEnumeration( xEnumerationAccess->createEnumeration(), UNO_QUERY );
686cdf0e10cSrcweir 					if( xEnumeration.is() )
687cdf0e10cSrcweir 					{
688cdf0e10cSrcweir 						while( xEnumeration->hasMoreElements() )
689cdf0e10cSrcweir 						{
690cdf0e10cSrcweir 							const Any aElem( xEnumeration->nextElement() );
691cdf0e10cSrcweir 							Reference< XAnimate > xAnimate( aElem, UNO_QUERY );
692cdf0e10cSrcweir 							if( xAnimate.is() )
693cdf0e10cSrcweir 								xAnimate->setTarget( rTarget );
694cdf0e10cSrcweir                             else
695cdf0e10cSrcweir                             {
696cdf0e10cSrcweir                                 Reference< XCommand > xCommand( aElem, UNO_QUERY );
697cdf0e10cSrcweir                                 if( xCommand.is() )
698cdf0e10cSrcweir                                     xCommand->setTarget( rTarget );
699cdf0e10cSrcweir                             }
700cdf0e10cSrcweir 						}
701cdf0e10cSrcweir 					}
702cdf0e10cSrcweir 				}
703cdf0e10cSrcweir 			}
704cdf0e10cSrcweir 		}
705cdf0e10cSrcweir 		checkForText();
706cdf0e10cSrcweir 	}
707cdf0e10cSrcweir 	catch( Exception& )
708cdf0e10cSrcweir 	{
709cdf0e10cSrcweir 		DBG_ERROR( "sd::CustomAnimationEffect::setTarget(), exception cought!" );
710cdf0e10cSrcweir 	}
711cdf0e10cSrcweir }
712cdf0e10cSrcweir 
713cdf0e10cSrcweir // --------------------------------------------------------------------
714cdf0e10cSrcweir 
715cdf0e10cSrcweir void CustomAnimationEffect::setTargetSubItem( sal_Int16 nSubItem )
716cdf0e10cSrcweir {
717cdf0e10cSrcweir 	try
718cdf0e10cSrcweir 	{
719cdf0e10cSrcweir 		mnTargetSubItem = nSubItem;
720cdf0e10cSrcweir 
721cdf0e10cSrcweir 		Reference< XIterateContainer > xIter( mxNode, UNO_QUERY );
722cdf0e10cSrcweir 		if( xIter.is() )
723cdf0e10cSrcweir 		{
724cdf0e10cSrcweir 			xIter->setSubItem(mnTargetSubItem);
725cdf0e10cSrcweir 		}
726cdf0e10cSrcweir 		else
727cdf0e10cSrcweir 		{
728cdf0e10cSrcweir 			Reference< XEnumerationAccess > xEnumerationAccess( mxNode, UNO_QUERY );
729cdf0e10cSrcweir 			if( xEnumerationAccess.is() )
730cdf0e10cSrcweir 			{
731cdf0e10cSrcweir 				Reference< XEnumeration > xEnumeration( xEnumerationAccess->createEnumeration(), UNO_QUERY );
732cdf0e10cSrcweir 				if( xEnumeration.is() )
733cdf0e10cSrcweir 				{
734cdf0e10cSrcweir 					while( xEnumeration->hasMoreElements() )
735cdf0e10cSrcweir 					{
736cdf0e10cSrcweir 						Reference< XAnimate > xAnimate( xEnumeration->nextElement(), UNO_QUERY );
737cdf0e10cSrcweir 						if( xAnimate.is() )
738cdf0e10cSrcweir 							xAnimate->setSubItem( mnTargetSubItem );
739cdf0e10cSrcweir 					}
740cdf0e10cSrcweir 				}
741cdf0e10cSrcweir 			}
742cdf0e10cSrcweir 		}
743cdf0e10cSrcweir 	}
744cdf0e10cSrcweir 	catch( Exception& )
745cdf0e10cSrcweir 	{
746cdf0e10cSrcweir 		DBG_ERROR( "sd::CustomAnimationEffect::setTargetSubItem(), exception cought!" );
747cdf0e10cSrcweir 	}
748cdf0e10cSrcweir }
749cdf0e10cSrcweir 
750cdf0e10cSrcweir // --------------------------------------------------------------------
751cdf0e10cSrcweir 
752cdf0e10cSrcweir void CustomAnimationEffect::setDuration( double fDuration )
753cdf0e10cSrcweir {
754cdf0e10cSrcweir 	if( (mfDuration != -1.0) && (mfDuration != fDuration) ) try
755cdf0e10cSrcweir 	{
756cdf0e10cSrcweir 		double fScale = fDuration / mfDuration;
757cdf0e10cSrcweir 		mfDuration = fDuration;
758cdf0e10cSrcweir 		mfAbsoluteDuration = mfDuration;
759cdf0e10cSrcweir 
760cdf0e10cSrcweir 		// calculate effect duration and get target shape
761cdf0e10cSrcweir 		Reference< XEnumerationAccess > xEnumerationAccess( mxNode, UNO_QUERY );
762cdf0e10cSrcweir 		if( xEnumerationAccess.is() )
763cdf0e10cSrcweir 		{
764cdf0e10cSrcweir 			Reference< XEnumeration > xEnumeration( xEnumerationAccess->createEnumeration(), UNO_QUERY );
765cdf0e10cSrcweir 			if( xEnumeration.is() )
766cdf0e10cSrcweir 			{
767cdf0e10cSrcweir 				while( xEnumeration->hasMoreElements() )
768cdf0e10cSrcweir 				{
769cdf0e10cSrcweir 					Reference< XAnimationNode > xChildNode( xEnumeration->nextElement(), UNO_QUERY );
770cdf0e10cSrcweir 					if( !xChildNode.is() )
771cdf0e10cSrcweir 						continue;
772cdf0e10cSrcweir 
773cdf0e10cSrcweir 
774cdf0e10cSrcweir 					double fChildBegin = 0.0;
775cdf0e10cSrcweir 					xChildNode->getBegin() >>= fChildBegin;
776cdf0e10cSrcweir 					if(  fChildBegin != 0.0 )
777cdf0e10cSrcweir 					{
778cdf0e10cSrcweir 						fChildBegin *= fScale;
779cdf0e10cSrcweir 						xChildNode->setBegin( makeAny( fChildBegin ) );
780cdf0e10cSrcweir 					}
781cdf0e10cSrcweir 
782cdf0e10cSrcweir 					double fChildDuration = 0.0;
783cdf0e10cSrcweir 					xChildNode->getDuration() >>= fChildDuration;
784cdf0e10cSrcweir 					if( fChildDuration != 0.0 )
785cdf0e10cSrcweir 					{
786cdf0e10cSrcweir 						fChildDuration *= fScale;
787cdf0e10cSrcweir 						xChildNode->setDuration( makeAny( fChildDuration ) );
788cdf0e10cSrcweir 					}
789cdf0e10cSrcweir 				}
790cdf0e10cSrcweir 			}
791cdf0e10cSrcweir 		}
792cdf0e10cSrcweir 		calculateIterateDuration();
793cdf0e10cSrcweir 	}
794cdf0e10cSrcweir 	catch( Exception& )
795cdf0e10cSrcweir 	{
796cdf0e10cSrcweir 		DBG_ERROR( "sd::CustomAnimationEffect::setDuration(), exception cought!" );
797cdf0e10cSrcweir 	}
798cdf0e10cSrcweir }
799cdf0e10cSrcweir 
800cdf0e10cSrcweir // --------------------------------------------------------------------
801cdf0e10cSrcweir 
802cdf0e10cSrcweir void CustomAnimationEffect::setBegin( double fBegin )
803cdf0e10cSrcweir {
804cdf0e10cSrcweir 	if( mxNode.is() ) try
805cdf0e10cSrcweir 	{
806cdf0e10cSrcweir 		mfBegin = fBegin;
807cdf0e10cSrcweir 		mxNode->setBegin( makeAny( fBegin ) );
808cdf0e10cSrcweir 	}
809cdf0e10cSrcweir 	catch( Exception& )
810cdf0e10cSrcweir 	{
811cdf0e10cSrcweir 		DBG_ERROR( "sd::CustomAnimationEffect::setBegin(), exception cought!" );
812cdf0e10cSrcweir 	}
813cdf0e10cSrcweir }
814cdf0e10cSrcweir 
815cdf0e10cSrcweir // --------------------------------------------------------------------
816cdf0e10cSrcweir 
817cdf0e10cSrcweir void CustomAnimationEffect::setAcceleration( double fAcceleration )
818cdf0e10cSrcweir {
819cdf0e10cSrcweir 	if( mxNode.is() ) try
820cdf0e10cSrcweir 	{
821cdf0e10cSrcweir 		mfAcceleration = fAcceleration;
822cdf0e10cSrcweir 		mxNode->setAcceleration( fAcceleration );
823cdf0e10cSrcweir 	}
824cdf0e10cSrcweir 	catch( Exception& )
825cdf0e10cSrcweir 	{
826cdf0e10cSrcweir 		DBG_ERROR( "sd::CustomAnimationEffect::setAcceleration(), exception cought!" );
827cdf0e10cSrcweir 	}
828cdf0e10cSrcweir }
829cdf0e10cSrcweir // --------------------------------------------------------------------
830cdf0e10cSrcweir 
831cdf0e10cSrcweir void CustomAnimationEffect::setDecelerate( double fDecelerate )
832cdf0e10cSrcweir {
833cdf0e10cSrcweir 	if( mxNode.is() ) try
834cdf0e10cSrcweir 	{
835cdf0e10cSrcweir 		mfDecelerate = fDecelerate;
836cdf0e10cSrcweir 		mxNode->setDecelerate( fDecelerate );
837cdf0e10cSrcweir 	}
838cdf0e10cSrcweir 	catch( Exception& )
839cdf0e10cSrcweir 	{
840cdf0e10cSrcweir 		DBG_ERROR( "sd::CustomAnimationEffect::setDecelerate(), exception cought!" );
841cdf0e10cSrcweir 	}
842cdf0e10cSrcweir }
843cdf0e10cSrcweir 
844cdf0e10cSrcweir // --------------------------------------------------------------------
845cdf0e10cSrcweir 
846cdf0e10cSrcweir void CustomAnimationEffect::setAutoReverse( sal_Bool bAutoReverse )
847cdf0e10cSrcweir {
848cdf0e10cSrcweir 	if( mxNode.is() ) try
849cdf0e10cSrcweir 	{
850cdf0e10cSrcweir 		mbAutoReverse = bAutoReverse;
851cdf0e10cSrcweir 		mxNode->setAutoReverse( bAutoReverse );
852cdf0e10cSrcweir 	}
853cdf0e10cSrcweir 	catch( Exception& )
854cdf0e10cSrcweir 	{
855cdf0e10cSrcweir 		DBG_ERROR( "sd::CustomAnimationEffect::setAutoReverse(), exception cought!" );
856cdf0e10cSrcweir 	}
857cdf0e10cSrcweir }
858cdf0e10cSrcweir 
859cdf0e10cSrcweir // --------------------------------------------------------------------
860cdf0e10cSrcweir 
861cdf0e10cSrcweir void CustomAnimationEffect::replaceNode( const ::com::sun::star::uno::Reference< ::com::sun::star::animations::XAnimationNode >& xNode )
862cdf0e10cSrcweir {
863cdf0e10cSrcweir 	sal_Int16 nNodeType = mnNodeType;
864cdf0e10cSrcweir 	Any aTarget = maTarget;
865cdf0e10cSrcweir 
866cdf0e10cSrcweir 	double fBegin = mfBegin;
867cdf0e10cSrcweir 	double fDuration = mfDuration;
868cdf0e10cSrcweir 	double fAcceleration = mfAcceleration;
869cdf0e10cSrcweir 	double fDecelerate = mfDecelerate ;
870cdf0e10cSrcweir 	sal_Bool bAutoReverse = mbAutoReverse;
871cdf0e10cSrcweir 	Reference< XAudio > xAudio( mxAudio );
872cdf0e10cSrcweir 	sal_Int16 nIterateType = mnIterateType;
873cdf0e10cSrcweir 	double fIterateInterval = mfIterateInterval;
874cdf0e10cSrcweir 	sal_Int16 nSubItem = mnTargetSubItem;
875cdf0e10cSrcweir 
876cdf0e10cSrcweir 	setNode( xNode );
877cdf0e10cSrcweir 
878cdf0e10cSrcweir 	setAudio( xAudio );
879cdf0e10cSrcweir 	setNodeType( nNodeType );
880cdf0e10cSrcweir 	setTarget( aTarget );
881cdf0e10cSrcweir 	setTargetSubItem( nSubItem );
882cdf0e10cSrcweir 	setDuration( fDuration );
883cdf0e10cSrcweir 	setBegin( fBegin );
884cdf0e10cSrcweir 
885cdf0e10cSrcweir 	setAcceleration( fAcceleration );
886cdf0e10cSrcweir 	setDecelerate( fDecelerate );
887cdf0e10cSrcweir 	setAutoReverse( bAutoReverse );
888cdf0e10cSrcweir 
889cdf0e10cSrcweir 	if( nIterateType != mnIterateType )
890cdf0e10cSrcweir 		setIterateType( nIterateType );
891cdf0e10cSrcweir 
892cdf0e10cSrcweir 	if( mnIterateType && ( fIterateInterval != mfIterateInterval ) )
893cdf0e10cSrcweir 		setIterateInterval( fIterateInterval );
894cdf0e10cSrcweir }
895cdf0e10cSrcweir 
896cdf0e10cSrcweir // --------------------------------------------------------------------
897cdf0e10cSrcweir 
898cdf0e10cSrcweir Reference< XShape > CustomAnimationEffect::getTargetShape() const
899cdf0e10cSrcweir {
900cdf0e10cSrcweir 	Reference< XShape > xShape;
901cdf0e10cSrcweir 	maTarget >>= xShape;
902cdf0e10cSrcweir 	if( !xShape.is() )
903cdf0e10cSrcweir 	{
904cdf0e10cSrcweir 		ParagraphTarget aParaTarget;
905cdf0e10cSrcweir 		if( maTarget >>= aParaTarget )
906cdf0e10cSrcweir 			xShape = aParaTarget.Shape;
907cdf0e10cSrcweir 	}
908cdf0e10cSrcweir 
909cdf0e10cSrcweir 	return xShape;
910cdf0e10cSrcweir }
911cdf0e10cSrcweir 
912cdf0e10cSrcweir // --------------------------------------------------------------------
913cdf0e10cSrcweir 
914cdf0e10cSrcweir Any	CustomAnimationEffect::getRepeatCount() const
915cdf0e10cSrcweir {
916cdf0e10cSrcweir 	if( mxNode.is() )
917cdf0e10cSrcweir 	{
918cdf0e10cSrcweir 		return mxNode->getRepeatCount();
919cdf0e10cSrcweir 	}
920cdf0e10cSrcweir 	else
921cdf0e10cSrcweir 	{
922cdf0e10cSrcweir 		Any aAny;
923cdf0e10cSrcweir 		return aAny;
924cdf0e10cSrcweir 	}
925cdf0e10cSrcweir }
926cdf0e10cSrcweir 
927cdf0e10cSrcweir // --------------------------------------------------------------------
928cdf0e10cSrcweir 
929cdf0e10cSrcweir Any	CustomAnimationEffect::getEnd() const
930cdf0e10cSrcweir {
931cdf0e10cSrcweir 	if( mxNode.is() )
932cdf0e10cSrcweir 	{
933cdf0e10cSrcweir 		return mxNode->getEnd();
934cdf0e10cSrcweir 	}
935cdf0e10cSrcweir 	else
936cdf0e10cSrcweir 	{
937cdf0e10cSrcweir 		Any aAny;
938cdf0e10cSrcweir 		return aAny;
939cdf0e10cSrcweir 	}
940cdf0e10cSrcweir }
941cdf0e10cSrcweir 
942cdf0e10cSrcweir // --------------------------------------------------------------------
943cdf0e10cSrcweir 
944cdf0e10cSrcweir sal_Int16 CustomAnimationEffect::getFill() const
945cdf0e10cSrcweir {
946cdf0e10cSrcweir 	if( mxNode.is() )
947cdf0e10cSrcweir 		return mxNode->getFill();
948cdf0e10cSrcweir 	else
949cdf0e10cSrcweir 		return 0;
950cdf0e10cSrcweir }
951cdf0e10cSrcweir 
952cdf0e10cSrcweir // --------------------------------------------------------------------
953cdf0e10cSrcweir 
954cdf0e10cSrcweir void CustomAnimationEffect::setRepeatCount( const Any& rRepeatCount )
955cdf0e10cSrcweir {
956cdf0e10cSrcweir 	if( mxNode.is() )
957cdf0e10cSrcweir 		mxNode->setRepeatCount( rRepeatCount );
958cdf0e10cSrcweir }
959cdf0e10cSrcweir 
960cdf0e10cSrcweir // --------------------------------------------------------------------
961cdf0e10cSrcweir 
962cdf0e10cSrcweir void CustomAnimationEffect::setEnd( const Any& rEnd )
963cdf0e10cSrcweir {
964cdf0e10cSrcweir 	if( mxNode.is() )
965cdf0e10cSrcweir 		mxNode->setEnd( rEnd );
966cdf0e10cSrcweir }
967cdf0e10cSrcweir 
968cdf0e10cSrcweir // --------------------------------------------------------------------
969cdf0e10cSrcweir 
970cdf0e10cSrcweir void CustomAnimationEffect::setFill( sal_Int16 nFill )
971cdf0e10cSrcweir {
972cdf0e10cSrcweir 	if( mxNode.is() )
973cdf0e10cSrcweir 		mxNode->setFill( nFill );
974cdf0e10cSrcweir }
975cdf0e10cSrcweir 
976cdf0e10cSrcweir // --------------------------------------------------------------------
977cdf0e10cSrcweir 
978cdf0e10cSrcweir Reference< XAnimationNode > CustomAnimationEffect::createAfterEffectNode() const throw (Exception)
979cdf0e10cSrcweir {
980cdf0e10cSrcweir 	DBG_ASSERT( mbHasAfterEffect, "sd::CustomAnimationEffect::createAfterEffectNode(), this node has no after effect!" );
981cdf0e10cSrcweir 
982cdf0e10cSrcweir 	Reference< XMultiServiceFactory > xMsf( ::comphelper::getProcessServiceFactory() );
983cdf0e10cSrcweir 
984cdf0e10cSrcweir 	const char* pServiceName = maDimColor.hasValue() ?
985cdf0e10cSrcweir 		"com.sun.star.animations.AnimateColor" : "com.sun.star.animations.AnimateSet";
986cdf0e10cSrcweir 
987cdf0e10cSrcweir 	Reference< XAnimate > xAnimate( xMsf->createInstance(OUString::createFromAscii(pServiceName) ), UNO_QUERY_THROW );
988cdf0e10cSrcweir 
989cdf0e10cSrcweir 	Any aTo;
990cdf0e10cSrcweir 	OUString aAttributeName;
991cdf0e10cSrcweir 
992cdf0e10cSrcweir 	if( maDimColor.hasValue() )
993cdf0e10cSrcweir 	{
994cdf0e10cSrcweir 		aTo = maDimColor;
995cdf0e10cSrcweir 		aAttributeName = OUString( RTL_CONSTASCII_USTRINGPARAM( "DimColor" ) );
996cdf0e10cSrcweir 	}
997cdf0e10cSrcweir 	else
998cdf0e10cSrcweir 	{
999cdf0e10cSrcweir 		aTo = makeAny( (sal_Bool)sal_False );
1000cdf0e10cSrcweir 		aAttributeName = OUString( RTL_CONSTASCII_USTRINGPARAM( "Visibility" ) );
1001cdf0e10cSrcweir 	}
1002cdf0e10cSrcweir 
1003cdf0e10cSrcweir 	Any aBegin;
1004cdf0e10cSrcweir 	if( !mbAfterEffectOnNextEffect ) // sameClick
1005cdf0e10cSrcweir 	{
1006cdf0e10cSrcweir 		Event aEvent;
1007cdf0e10cSrcweir 
1008cdf0e10cSrcweir 		aEvent.Source <<= getNode();
1009cdf0e10cSrcweir 		aEvent.Trigger = EventTrigger::END_EVENT;
1010cdf0e10cSrcweir 		aEvent.Repeat = 0;
1011cdf0e10cSrcweir 
1012cdf0e10cSrcweir 		aBegin <<= aEvent;
1013cdf0e10cSrcweir 	}
1014cdf0e10cSrcweir 	else
1015cdf0e10cSrcweir 	{
1016cdf0e10cSrcweir 		aBegin <<= (double)0.0;
1017cdf0e10cSrcweir 	}
1018cdf0e10cSrcweir 
1019cdf0e10cSrcweir 	xAnimate->setBegin( aBegin );
1020cdf0e10cSrcweir 	xAnimate->setTo( aTo );
1021cdf0e10cSrcweir 	xAnimate->setAttributeName( aAttributeName );
1022cdf0e10cSrcweir 
1023cdf0e10cSrcweir 	xAnimate->setDuration( makeAny( (double)0.001 ) );
1024cdf0e10cSrcweir 	xAnimate->setFill( AnimationFill::HOLD );
1025cdf0e10cSrcweir 	xAnimate->setTarget( maTarget );
1026cdf0e10cSrcweir 
1027cdf0e10cSrcweir 	return Reference< XAnimationNode >( xAnimate, UNO_QUERY_THROW );
1028cdf0e10cSrcweir }
1029cdf0e10cSrcweir 
1030cdf0e10cSrcweir // --------------------------------------------------------------------
1031cdf0e10cSrcweir 
1032cdf0e10cSrcweir void CustomAnimationEffect::setIterateType( sal_Int16 nIterateType )
1033cdf0e10cSrcweir {
1034cdf0e10cSrcweir 	if( mnIterateType != nIterateType ) try
1035cdf0e10cSrcweir 	{
1036cdf0e10cSrcweir 		// do we need to exchange the container node?
1037cdf0e10cSrcweir 		if( (mnIterateType == 0) || (nIterateType == 0) )
1038cdf0e10cSrcweir 		{
1039cdf0e10cSrcweir 			sal_Int16 nTargetSubItem = mnTargetSubItem;
1040cdf0e10cSrcweir 
1041cdf0e10cSrcweir 			Reference< XMultiServiceFactory > xMsf( ::comphelper::getProcessServiceFactory() );
1042cdf0e10cSrcweir 			const char * pServiceName =
1043cdf0e10cSrcweir 				nIterateType ? "com.sun.star.animations.IterateContainer" : "com.sun.star.animations.ParallelTimeContainer";
1044cdf0e10cSrcweir 			Reference< XTimeContainer > xNewContainer(
1045cdf0e10cSrcweir 				xMsf->createInstance( OUString::createFromAscii(pServiceName) ), UNO_QUERY_THROW );
1046cdf0e10cSrcweir 
1047cdf0e10cSrcweir 			Reference< XTimeContainer > xOldContainer( mxNode, UNO_QUERY_THROW );
1048cdf0e10cSrcweir 			Reference< XEnumerationAccess > xEnumerationAccess( mxNode, UNO_QUERY_THROW );
1049cdf0e10cSrcweir 			Reference< XEnumeration > xEnumeration( xEnumerationAccess->createEnumeration(), UNO_QUERY_THROW );
1050cdf0e10cSrcweir 			while( xEnumeration->hasMoreElements() )
1051cdf0e10cSrcweir 			{
1052cdf0e10cSrcweir 				Reference< XAnimationNode > xChildNode( xEnumeration->nextElement(), UNO_QUERY_THROW );
1053cdf0e10cSrcweir 				xOldContainer->removeChild( xChildNode );
1054cdf0e10cSrcweir 				xNewContainer->appendChild( xChildNode );
1055cdf0e10cSrcweir 			}
1056cdf0e10cSrcweir 
1057cdf0e10cSrcweir 			Reference< XAnimationNode > xNewNode( xNewContainer, UNO_QUERY_THROW );
1058cdf0e10cSrcweir 
1059cdf0e10cSrcweir 			xNewNode->setBegin( mxNode->getBegin() );
1060cdf0e10cSrcweir 			xNewNode->setDuration( mxNode->getDuration() );
1061cdf0e10cSrcweir 			xNewNode->setEnd( mxNode->getEnd() );
1062cdf0e10cSrcweir 			xNewNode->setEndSync( mxNode->getEndSync() );
1063cdf0e10cSrcweir 			xNewNode->setRepeatCount( mxNode->getRepeatCount() );
1064cdf0e10cSrcweir 			xNewNode->setFill( mxNode->getFill() );
1065cdf0e10cSrcweir 			xNewNode->setFillDefault( mxNode->getFillDefault() );
1066cdf0e10cSrcweir 			xNewNode->setRestart( mxNode->getRestart() );
1067cdf0e10cSrcweir 			xNewNode->setRestartDefault( mxNode->getRestartDefault() );
1068cdf0e10cSrcweir 			xNewNode->setAcceleration( mxNode->getAcceleration() );
1069cdf0e10cSrcweir 			xNewNode->setDecelerate( mxNode->getDecelerate() );
1070cdf0e10cSrcweir 			xNewNode->setAutoReverse( mxNode->getAutoReverse() );
1071cdf0e10cSrcweir 			xNewNode->setRepeatDuration( mxNode->getRepeatDuration() );
1072cdf0e10cSrcweir 			xNewNode->setEndSync( mxNode->getEndSync() );
1073cdf0e10cSrcweir 			xNewNode->setRepeatCount( mxNode->getRepeatCount() );
1074cdf0e10cSrcweir 			xNewNode->setUserData( mxNode->getUserData() );
1075cdf0e10cSrcweir 
1076cdf0e10cSrcweir 			mxNode = xNewNode;
1077cdf0e10cSrcweir 
1078cdf0e10cSrcweir 			Any aTarget;
1079cdf0e10cSrcweir 			if( nIterateType )
1080cdf0e10cSrcweir 			{
1081cdf0e10cSrcweir 				Reference< XIterateContainer > xIter( mxNode, UNO_QUERY_THROW );
1082cdf0e10cSrcweir 				xIter->setTarget(maTarget);
1083cdf0e10cSrcweir 				xIter->setSubItem( nTargetSubItem );
1084cdf0e10cSrcweir 			}
1085cdf0e10cSrcweir 			else
1086cdf0e10cSrcweir 			{
1087cdf0e10cSrcweir 				aTarget = maTarget;
1088cdf0e10cSrcweir 			}
1089cdf0e10cSrcweir 
1090cdf0e10cSrcweir 			Reference< XEnumerationAccess > xEA( mxNode, UNO_QUERY_THROW );
1091cdf0e10cSrcweir 			Reference< XEnumeration > xE( xEA->createEnumeration(), UNO_QUERY_THROW );
1092cdf0e10cSrcweir 			while( xE->hasMoreElements() )
1093cdf0e10cSrcweir 			{
1094cdf0e10cSrcweir 				Reference< XAnimate > xAnimate( xE->nextElement(), UNO_QUERY );
1095cdf0e10cSrcweir 				if( xAnimate.is() )
1096cdf0e10cSrcweir 				{
1097cdf0e10cSrcweir 					xAnimate->setTarget( aTarget );
1098cdf0e10cSrcweir 					xAnimate->setSubItem( nTargetSubItem );
1099cdf0e10cSrcweir 				}
1100cdf0e10cSrcweir 			}
1101cdf0e10cSrcweir 		}
1102cdf0e10cSrcweir 
1103cdf0e10cSrcweir 		mnIterateType = nIterateType;
1104cdf0e10cSrcweir 
1105cdf0e10cSrcweir 		// if we have an iteration container, we must set its type
1106cdf0e10cSrcweir 		if( mnIterateType )
1107cdf0e10cSrcweir 		{
1108cdf0e10cSrcweir 			Reference< XIterateContainer > xIter( mxNode, UNO_QUERY_THROW );
1109cdf0e10cSrcweir 			xIter->setIterateType( nIterateType );
1110cdf0e10cSrcweir 		}
1111cdf0e10cSrcweir 
1112cdf0e10cSrcweir 		checkForText();
1113cdf0e10cSrcweir 	}
1114cdf0e10cSrcweir 	catch( Exception& e )
1115cdf0e10cSrcweir 	{
1116cdf0e10cSrcweir 		(void)e;
1117cdf0e10cSrcweir 		DBG_ERROR( "sd::CustomAnimationEffect::setIterateType(), Exception cought!" );
1118cdf0e10cSrcweir 	}
1119cdf0e10cSrcweir }
1120cdf0e10cSrcweir 
1121cdf0e10cSrcweir // --------------------------------------------------------------------
1122cdf0e10cSrcweir 
1123cdf0e10cSrcweir void CustomAnimationEffect::setIterateInterval( double fIterateInterval )
1124cdf0e10cSrcweir {
1125cdf0e10cSrcweir 	if( mfIterateInterval != fIterateInterval )
1126cdf0e10cSrcweir 	{
1127cdf0e10cSrcweir 		Reference< XIterateContainer > xIter( mxNode, UNO_QUERY );
1128cdf0e10cSrcweir 
1129cdf0e10cSrcweir 		DBG_ASSERT( xIter.is(), "sd::CustomAnimationEffect::setIterateInterval(), not an iteration node" );
1130cdf0e10cSrcweir 		if( xIter.is() )
1131cdf0e10cSrcweir 		{
1132cdf0e10cSrcweir 			mfIterateInterval = fIterateInterval;
1133cdf0e10cSrcweir 			xIter->setIterateInterval( fIterateInterval );
1134cdf0e10cSrcweir 		}
1135cdf0e10cSrcweir 
1136cdf0e10cSrcweir 		calculateIterateDuration();
1137cdf0e10cSrcweir 	}
1138cdf0e10cSrcweir }
1139cdf0e10cSrcweir 
1140cdf0e10cSrcweir // --------------------------------------------------------------------
1141cdf0e10cSrcweir 
1142cdf0e10cSrcweir ::rtl::OUString	CustomAnimationEffect::getPath() const
1143cdf0e10cSrcweir {
1144cdf0e10cSrcweir 	::rtl::OUString aPath;
1145cdf0e10cSrcweir 
1146cdf0e10cSrcweir 	if( mxNode.is() ) try
1147cdf0e10cSrcweir 	{
1148cdf0e10cSrcweir 		Reference< XEnumerationAccess > xEnumerationAccess( mxNode, UNO_QUERY_THROW );
1149cdf0e10cSrcweir 		Reference< XEnumeration > xEnumeration( xEnumerationAccess->createEnumeration(), UNO_QUERY_THROW );
1150cdf0e10cSrcweir 		while( xEnumeration->hasMoreElements() )
1151cdf0e10cSrcweir 		{
1152cdf0e10cSrcweir 			Reference< XAnimateMotion > xMotion( xEnumeration->nextElement(), UNO_QUERY );
1153cdf0e10cSrcweir 			if( xMotion.is() )
1154cdf0e10cSrcweir 			{
1155cdf0e10cSrcweir 				xMotion->getPath() >>= aPath;
1156cdf0e10cSrcweir 				break;
1157cdf0e10cSrcweir 			}
1158cdf0e10cSrcweir 		}
1159cdf0e10cSrcweir 	}
1160cdf0e10cSrcweir 	catch( Exception& e )
1161cdf0e10cSrcweir 	{
1162cdf0e10cSrcweir 		(void)e;
1163cdf0e10cSrcweir 		DBG_ERROR("sd::CustomAnimationEffect::getPath(), exception cought!" );
1164cdf0e10cSrcweir 	}
1165cdf0e10cSrcweir 
1166cdf0e10cSrcweir 	return aPath;
1167cdf0e10cSrcweir }
1168cdf0e10cSrcweir 
1169cdf0e10cSrcweir // --------------------------------------------------------------------
1170cdf0e10cSrcweir 
1171cdf0e10cSrcweir void CustomAnimationEffect::setPath( const ::rtl::OUString& rPath )
1172cdf0e10cSrcweir {
1173cdf0e10cSrcweir 	if( mxNode.is() ) try
1174cdf0e10cSrcweir 	{
1175cdf0e10cSrcweir 		Reference< XEnumerationAccess > xEnumerationAccess( mxNode, UNO_QUERY_THROW );
1176cdf0e10cSrcweir 		Reference< XEnumeration > xEnumeration( xEnumerationAccess->createEnumeration(), UNO_QUERY_THROW );
1177cdf0e10cSrcweir 		while( xEnumeration->hasMoreElements() )
1178cdf0e10cSrcweir 		{
1179cdf0e10cSrcweir 			Reference< XAnimateMotion > xMotion( xEnumeration->nextElement(), UNO_QUERY );
1180cdf0e10cSrcweir 			if( xMotion.is() )
1181cdf0e10cSrcweir 			{
1182cdf0e10cSrcweir 
1183cdf0e10cSrcweir 				MainSequenceChangeGuard aGuard( mpEffectSequence );
1184cdf0e10cSrcweir 				xMotion->setPath( Any( rPath ) );
1185cdf0e10cSrcweir 				break;
1186cdf0e10cSrcweir 			}
1187cdf0e10cSrcweir 		}
1188cdf0e10cSrcweir 	}
1189cdf0e10cSrcweir 	catch( Exception& e )
1190cdf0e10cSrcweir 	{
1191cdf0e10cSrcweir 		(void)e;
1192cdf0e10cSrcweir 		DBG_ERROR("sd::CustomAnimationEffect::setPath(), exception cought!" );
1193cdf0e10cSrcweir 	}
1194cdf0e10cSrcweir }
1195cdf0e10cSrcweir 
1196cdf0e10cSrcweir // --------------------------------------------------------------------
1197cdf0e10cSrcweir 
1198cdf0e10cSrcweir Any CustomAnimationEffect::getProperty( sal_Int32 nNodeType, const OUString& rAttributeName, EValue eValue )
1199cdf0e10cSrcweir {
1200cdf0e10cSrcweir 	Any aProperty;
1201cdf0e10cSrcweir 	if( mxNode.is() ) try
1202cdf0e10cSrcweir 	{
1203cdf0e10cSrcweir 		Reference< XEnumerationAccess > xEnumerationAccess( mxNode, UNO_QUERY );
1204cdf0e10cSrcweir 		if( xEnumerationAccess.is() )
1205cdf0e10cSrcweir 		{
1206cdf0e10cSrcweir 			Reference< XEnumeration > xEnumeration( xEnumerationAccess->createEnumeration(), UNO_QUERY );
1207cdf0e10cSrcweir 			if( xEnumeration.is() )
1208cdf0e10cSrcweir 			{
1209cdf0e10cSrcweir 				while( xEnumeration->hasMoreElements() && !aProperty.hasValue() )
1210cdf0e10cSrcweir 				{
1211cdf0e10cSrcweir 					Reference< XAnimate > xAnimate( xEnumeration->nextElement(), UNO_QUERY );
1212cdf0e10cSrcweir 					if( !xAnimate.is() )
1213cdf0e10cSrcweir 						continue;
1214cdf0e10cSrcweir 
1215cdf0e10cSrcweir 					if( xAnimate->getType() == nNodeType )
1216cdf0e10cSrcweir 					{
1217cdf0e10cSrcweir 						if( xAnimate->getAttributeName() == rAttributeName )
1218cdf0e10cSrcweir 						{
1219cdf0e10cSrcweir 							switch( eValue )
1220cdf0e10cSrcweir 							{
1221cdf0e10cSrcweir 							case VALUE_FROM: aProperty = xAnimate->getFrom(); break;
1222cdf0e10cSrcweir 							case VALUE_TO:   aProperty = xAnimate->getTo(); break;
1223cdf0e10cSrcweir 							case VALUE_BY:   aProperty = xAnimate->getBy(); break;
1224cdf0e10cSrcweir 							case VALUE_FIRST:
1225cdf0e10cSrcweir 							case VALUE_LAST:
1226cdf0e10cSrcweir 								{
1227cdf0e10cSrcweir 									Sequence<Any> aValues( xAnimate->getValues() );
1228cdf0e10cSrcweir 									if( aValues.hasElements() )
1229cdf0e10cSrcweir 										aProperty =  aValues[ eValue == VALUE_FIRST ? 0 : aValues.getLength() - 1 ];
1230cdf0e10cSrcweir 								}
1231cdf0e10cSrcweir 								break;
1232cdf0e10cSrcweir 							}
1233cdf0e10cSrcweir 						}
1234cdf0e10cSrcweir 					}
1235cdf0e10cSrcweir 				}
1236cdf0e10cSrcweir 			}
1237cdf0e10cSrcweir 		}
1238cdf0e10cSrcweir 	}
1239cdf0e10cSrcweir 	catch( Exception& e )
1240cdf0e10cSrcweir 	{
1241cdf0e10cSrcweir 		(void)e;
1242cdf0e10cSrcweir 		DBG_ERROR("sd::CustomAnimationEffect::getProperty(), exception cought!" );
1243cdf0e10cSrcweir 	}
1244cdf0e10cSrcweir 
1245cdf0e10cSrcweir 	return aProperty;
1246cdf0e10cSrcweir }
1247cdf0e10cSrcweir 
1248cdf0e10cSrcweir // --------------------------------------------------------------------
1249cdf0e10cSrcweir 
1250cdf0e10cSrcweir bool CustomAnimationEffect::setProperty( sal_Int32 nNodeType, const OUString& rAttributeName, EValue eValue, const Any& rValue )
1251cdf0e10cSrcweir {
1252cdf0e10cSrcweir 	bool bChanged = false;
1253cdf0e10cSrcweir 	if( mxNode.is() ) try
1254cdf0e10cSrcweir 	{
1255cdf0e10cSrcweir 		Reference< XEnumerationAccess > xEnumerationAccess( mxNode, UNO_QUERY );
1256cdf0e10cSrcweir 		if( xEnumerationAccess.is() )
1257cdf0e10cSrcweir 		{
1258cdf0e10cSrcweir 			Reference< XEnumeration > xEnumeration( xEnumerationAccess->createEnumeration(), UNO_QUERY );
1259cdf0e10cSrcweir 			if( xEnumeration.is() )
1260cdf0e10cSrcweir 			{
1261cdf0e10cSrcweir 				while( xEnumeration->hasMoreElements() )
1262cdf0e10cSrcweir 				{
1263cdf0e10cSrcweir 					Reference< XAnimate > xAnimate( xEnumeration->nextElement(), UNO_QUERY );
1264cdf0e10cSrcweir 					if( !xAnimate.is() )
1265cdf0e10cSrcweir 						continue;
1266cdf0e10cSrcweir 
1267cdf0e10cSrcweir 					if( xAnimate->getType() == nNodeType )
1268cdf0e10cSrcweir 					{
1269cdf0e10cSrcweir 						if( xAnimate->getAttributeName() == rAttributeName )
1270cdf0e10cSrcweir 						{
1271cdf0e10cSrcweir 							switch( eValue )
1272cdf0e10cSrcweir 							{
1273cdf0e10cSrcweir 							case VALUE_FROM:
1274cdf0e10cSrcweir 								if( xAnimate->getFrom() != rValue )
1275cdf0e10cSrcweir 								{
1276cdf0e10cSrcweir 									xAnimate->setFrom( rValue );
1277cdf0e10cSrcweir 									bChanged = true;
1278cdf0e10cSrcweir 								}
1279cdf0e10cSrcweir 								break;
1280cdf0e10cSrcweir 							case VALUE_TO:
1281cdf0e10cSrcweir 								if( xAnimate->getTo() != rValue )
1282cdf0e10cSrcweir 								{
1283cdf0e10cSrcweir 									xAnimate->setTo( rValue );
1284cdf0e10cSrcweir 									bChanged = true;
1285cdf0e10cSrcweir 								}
1286cdf0e10cSrcweir 								break;
1287cdf0e10cSrcweir 							case VALUE_BY:
1288cdf0e10cSrcweir 								if( xAnimate->getTo() != rValue )
1289cdf0e10cSrcweir 								{
1290cdf0e10cSrcweir 									xAnimate->setBy( rValue );
1291cdf0e10cSrcweir 									bChanged = true;
1292cdf0e10cSrcweir 								}
1293cdf0e10cSrcweir 								break;
1294cdf0e10cSrcweir 							case VALUE_FIRST:
1295cdf0e10cSrcweir 							case VALUE_LAST:
1296cdf0e10cSrcweir 								{
1297cdf0e10cSrcweir 									Sequence<Any> aValues( xAnimate->getValues() );
1298cdf0e10cSrcweir 									if( !aValues.hasElements() )
1299cdf0e10cSrcweir 										aValues.realloc(1);
1300cdf0e10cSrcweir 
1301cdf0e10cSrcweir 									sal_Int32 nIndex = eValue == VALUE_FIRST ? 0 : aValues.getLength() - 1;
1302cdf0e10cSrcweir 
1303cdf0e10cSrcweir 									if( aValues[ nIndex ] != rValue )
1304cdf0e10cSrcweir 									{
1305cdf0e10cSrcweir 										aValues[ nIndex ] = rValue;
1306cdf0e10cSrcweir 										xAnimate->setValues( aValues );
1307cdf0e10cSrcweir 										bChanged = true;
1308cdf0e10cSrcweir 									}
1309cdf0e10cSrcweir 								}
1310cdf0e10cSrcweir 							}
1311cdf0e10cSrcweir 						}
1312cdf0e10cSrcweir 					}
1313cdf0e10cSrcweir 				}
1314cdf0e10cSrcweir 			}
1315cdf0e10cSrcweir 		}
1316cdf0e10cSrcweir 	}
1317cdf0e10cSrcweir 	catch( Exception& e )
1318cdf0e10cSrcweir 	{
1319cdf0e10cSrcweir 		(void)e;
1320cdf0e10cSrcweir 		DBG_ERROR("sd::CustomAnimationEffect::setProperty(), exception cought!" );
1321cdf0e10cSrcweir 	}
1322cdf0e10cSrcweir 
1323cdf0e10cSrcweir 	return bChanged;
1324cdf0e10cSrcweir }
1325cdf0e10cSrcweir 
1326cdf0e10cSrcweir // --------------------------------------------------------------------
1327cdf0e10cSrcweir 
1328cdf0e10cSrcweir static bool implIsColorAttribute( const OUString& rAttributeName )
1329cdf0e10cSrcweir {
1330cdf0e10cSrcweir 	return rAttributeName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("FillColor") ) ||
1331cdf0e10cSrcweir 		   rAttributeName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("LineColor") ) ||
1332cdf0e10cSrcweir 		   rAttributeName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("CharColor") );
1333cdf0e10cSrcweir }
1334cdf0e10cSrcweir 
1335cdf0e10cSrcweir // --------------------------------------------------------------------
1336cdf0e10cSrcweir 
1337cdf0e10cSrcweir Any CustomAnimationEffect::getColor( sal_Int32 nIndex )
1338cdf0e10cSrcweir {
1339cdf0e10cSrcweir 	Any aColor;
1340cdf0e10cSrcweir 	if( mxNode.is() ) try
1341cdf0e10cSrcweir 	{
1342cdf0e10cSrcweir 		Reference< XEnumerationAccess > xEnumerationAccess( mxNode, UNO_QUERY );
1343cdf0e10cSrcweir 		if( xEnumerationAccess.is() )
1344cdf0e10cSrcweir 		{
1345cdf0e10cSrcweir 			Reference< XEnumeration > xEnumeration( xEnumerationAccess->createEnumeration(), UNO_QUERY );
1346cdf0e10cSrcweir 			if( xEnumeration.is() )
1347cdf0e10cSrcweir 			{
1348cdf0e10cSrcweir 				while( xEnumeration->hasMoreElements() && !aColor.hasValue() )
1349cdf0e10cSrcweir 				{
1350cdf0e10cSrcweir 					Reference< XAnimate > xAnimate( xEnumeration->nextElement(), UNO_QUERY );
1351cdf0e10cSrcweir 					if( !xAnimate.is() )
1352cdf0e10cSrcweir 						continue;
1353cdf0e10cSrcweir 
1354cdf0e10cSrcweir 					switch( xAnimate->getType() )
1355cdf0e10cSrcweir 					{
1356cdf0e10cSrcweir 					case AnimationNodeType::SET:
1357cdf0e10cSrcweir 					case AnimationNodeType::ANIMATE:
1358cdf0e10cSrcweir 						if( !implIsColorAttribute( xAnimate->getAttributeName() ) )
1359cdf0e10cSrcweir 							break;
1360cdf0e10cSrcweir 					case AnimationNodeType::ANIMATECOLOR:
1361cdf0e10cSrcweir 						Sequence<Any> aValues( xAnimate->getValues() );
1362cdf0e10cSrcweir 						if( aValues.hasElements() )
1363cdf0e10cSrcweir 						{
1364cdf0e10cSrcweir 							if( aValues.getLength() > nIndex )
1365cdf0e10cSrcweir 								aColor = aValues[nIndex];
1366cdf0e10cSrcweir 						}
1367cdf0e10cSrcweir 						else if( nIndex == 0 )
1368cdf0e10cSrcweir 							aColor = xAnimate->getFrom();
1369cdf0e10cSrcweir 						else
1370cdf0e10cSrcweir 							aColor = xAnimate->getTo();
1371cdf0e10cSrcweir 					}
1372cdf0e10cSrcweir 				}
1373cdf0e10cSrcweir 			}
1374cdf0e10cSrcweir 		}
1375cdf0e10cSrcweir 	}
1376cdf0e10cSrcweir 	catch( Exception& e )
1377cdf0e10cSrcweir 	{
1378cdf0e10cSrcweir 		(void)e;
1379cdf0e10cSrcweir 		DBG_ERROR("sd::CustomAnimationEffect::getColor(), exception cought!" );
1380cdf0e10cSrcweir 	}
1381cdf0e10cSrcweir 
1382cdf0e10cSrcweir 	return aColor;
1383cdf0e10cSrcweir }
1384cdf0e10cSrcweir 
1385cdf0e10cSrcweir // --------------------------------------------------------------------
1386cdf0e10cSrcweir 
1387cdf0e10cSrcweir void CustomAnimationEffect::setColor( sal_Int32 nIndex, const Any& rColor )
1388cdf0e10cSrcweir {
1389cdf0e10cSrcweir 	if( mxNode.is() ) try
1390cdf0e10cSrcweir 	{
1391cdf0e10cSrcweir 		Reference< XEnumerationAccess > xEnumerationAccess( mxNode, UNO_QUERY );
1392cdf0e10cSrcweir 		if( xEnumerationAccess.is() )
1393cdf0e10cSrcweir 		{
1394cdf0e10cSrcweir 			Reference< XEnumeration > xEnumeration( xEnumerationAccess->createEnumeration(), UNO_QUERY );
1395cdf0e10cSrcweir 			if( xEnumeration.is() )
1396cdf0e10cSrcweir 			{
1397cdf0e10cSrcweir 				while( xEnumeration->hasMoreElements() )
1398cdf0e10cSrcweir 				{
1399cdf0e10cSrcweir 					Reference< XAnimate > xAnimate( xEnumeration->nextElement(), UNO_QUERY );
1400cdf0e10cSrcweir 					if( !xAnimate.is() )
1401cdf0e10cSrcweir 						continue;
1402cdf0e10cSrcweir 
1403cdf0e10cSrcweir 					switch( xAnimate->getType() )
1404cdf0e10cSrcweir 					{
1405cdf0e10cSrcweir 					case AnimationNodeType::SET:
1406cdf0e10cSrcweir 					case AnimationNodeType::ANIMATE:
1407cdf0e10cSrcweir 						if( !implIsColorAttribute( xAnimate->getAttributeName() ) )
1408cdf0e10cSrcweir 							break;
1409cdf0e10cSrcweir 					case AnimationNodeType::ANIMATECOLOR:
1410cdf0e10cSrcweir 					{
1411cdf0e10cSrcweir 						Sequence<Any> aValues( xAnimate->getValues() );
1412cdf0e10cSrcweir 						if( aValues.hasElements() )
1413cdf0e10cSrcweir 						{
1414cdf0e10cSrcweir 							if( aValues.getLength() > nIndex )
1415cdf0e10cSrcweir 							{
1416cdf0e10cSrcweir 								aValues[nIndex] = rColor;
1417cdf0e10cSrcweir 								xAnimate->setValues( aValues );
1418cdf0e10cSrcweir 							}
1419cdf0e10cSrcweir 						}
1420cdf0e10cSrcweir 						else if( (nIndex == 0) && xAnimate->getFrom().hasValue() )
1421cdf0e10cSrcweir 							xAnimate->setFrom(rColor);
1422cdf0e10cSrcweir 						else if( (nIndex == 1) && xAnimate->getTo().hasValue() )
1423cdf0e10cSrcweir 							xAnimate->setTo(rColor);
1424cdf0e10cSrcweir 					}
1425cdf0e10cSrcweir 					break;
1426cdf0e10cSrcweir 
1427cdf0e10cSrcweir 					}
1428cdf0e10cSrcweir 				}
1429cdf0e10cSrcweir 			}
1430cdf0e10cSrcweir 		}
1431cdf0e10cSrcweir 	}
1432cdf0e10cSrcweir 	catch( Exception& e )
1433cdf0e10cSrcweir 	{
1434cdf0e10cSrcweir 		(void)e;
1435cdf0e10cSrcweir 		DBG_ERROR("sd::CustomAnimationEffect::setColor(), exception cought!" );
1436cdf0e10cSrcweir 	}
1437cdf0e10cSrcweir }
1438cdf0e10cSrcweir 
1439cdf0e10cSrcweir // --------------------------------------------------------------------
1440cdf0e10cSrcweir 
1441cdf0e10cSrcweir Any CustomAnimationEffect::getTransformationProperty( sal_Int32 nTransformType, EValue eValue )
1442cdf0e10cSrcweir {
1443cdf0e10cSrcweir 	Any aProperty;
1444cdf0e10cSrcweir 	if( mxNode.is() ) try
1445cdf0e10cSrcweir 	{
1446cdf0e10cSrcweir 		Reference< XEnumerationAccess > xEnumerationAccess( mxNode, UNO_QUERY );
1447cdf0e10cSrcweir 		if( xEnumerationAccess.is() )
1448cdf0e10cSrcweir 		{
1449cdf0e10cSrcweir 			Reference< XEnumeration > xEnumeration( xEnumerationAccess->createEnumeration(), UNO_QUERY );
1450cdf0e10cSrcweir 			if( xEnumeration.is() )
1451cdf0e10cSrcweir 			{
1452cdf0e10cSrcweir 				while( xEnumeration->hasMoreElements() && !aProperty.hasValue() )
1453cdf0e10cSrcweir 				{
1454cdf0e10cSrcweir 					Reference< XAnimateTransform > xTransform( xEnumeration->nextElement(), UNO_QUERY );
1455cdf0e10cSrcweir 					if( !xTransform.is() )
1456cdf0e10cSrcweir 						continue;
1457cdf0e10cSrcweir 
1458cdf0e10cSrcweir 					if( xTransform->getTransformType() == nTransformType )
1459cdf0e10cSrcweir 					{
1460cdf0e10cSrcweir 						switch( eValue )
1461cdf0e10cSrcweir 						{
1462cdf0e10cSrcweir 						case VALUE_FROM: aProperty = xTransform->getFrom(); break;
1463cdf0e10cSrcweir 						case VALUE_TO:   aProperty = xTransform->getTo(); break;
1464cdf0e10cSrcweir 						case VALUE_BY:   aProperty = xTransform->getBy(); break;
1465cdf0e10cSrcweir 						case VALUE_FIRST:
1466cdf0e10cSrcweir 						case VALUE_LAST:
1467cdf0e10cSrcweir 							{
1468cdf0e10cSrcweir 								Sequence<Any> aValues( xTransform->getValues() );
1469cdf0e10cSrcweir 								if( aValues.hasElements() )
1470cdf0e10cSrcweir 									aProperty =  aValues[ eValue == VALUE_FIRST ? 0 : aValues.getLength() - 1 ];
1471cdf0e10cSrcweir 							}
1472cdf0e10cSrcweir 							break;
1473cdf0e10cSrcweir 						}
1474cdf0e10cSrcweir 					}
1475cdf0e10cSrcweir 				}
1476cdf0e10cSrcweir 			}
1477cdf0e10cSrcweir 		}
1478cdf0e10cSrcweir 	}
1479cdf0e10cSrcweir 	catch( Exception& e )
1480cdf0e10cSrcweir 	{
1481cdf0e10cSrcweir 		(void)e;
1482cdf0e10cSrcweir 		DBG_ERROR("sd::CustomAnimationEffect::getTransformationProperty(), exception cought!" );
1483cdf0e10cSrcweir 	}
1484cdf0e10cSrcweir 
1485cdf0e10cSrcweir 	return aProperty;
1486cdf0e10cSrcweir }
1487cdf0e10cSrcweir 
1488cdf0e10cSrcweir // --------------------------------------------------------------------
1489cdf0e10cSrcweir 
1490cdf0e10cSrcweir bool CustomAnimationEffect::setTransformationProperty( sal_Int32 nTransformType, EValue eValue, const Any& rValue )
1491cdf0e10cSrcweir {
1492cdf0e10cSrcweir 	bool bChanged = false;
1493cdf0e10cSrcweir 	if( mxNode.is() ) try
1494cdf0e10cSrcweir 	{
1495cdf0e10cSrcweir 		Reference< XEnumerationAccess > xEnumerationAccess( mxNode, UNO_QUERY );
1496cdf0e10cSrcweir 		if( xEnumerationAccess.is() )
1497cdf0e10cSrcweir 		{
1498cdf0e10cSrcweir 			Reference< XEnumeration > xEnumeration( xEnumerationAccess->createEnumeration(), UNO_QUERY );
1499cdf0e10cSrcweir 			if( xEnumeration.is() )
1500cdf0e10cSrcweir 			{
1501cdf0e10cSrcweir 				while( xEnumeration->hasMoreElements() )
1502cdf0e10cSrcweir 				{
1503cdf0e10cSrcweir 					Reference< XAnimateTransform > xTransform( xEnumeration->nextElement(), UNO_QUERY );
1504cdf0e10cSrcweir 					if( !xTransform.is() )
1505cdf0e10cSrcweir 						continue;
1506cdf0e10cSrcweir 
1507cdf0e10cSrcweir 					if( xTransform->getTransformType() == nTransformType )
1508cdf0e10cSrcweir 					{
1509cdf0e10cSrcweir 						switch( eValue )
1510cdf0e10cSrcweir 						{
1511cdf0e10cSrcweir 						case VALUE_FROM:
1512cdf0e10cSrcweir 							if( xTransform->getFrom() != rValue )
1513cdf0e10cSrcweir 							{
1514cdf0e10cSrcweir 								xTransform->setFrom( rValue );
1515cdf0e10cSrcweir 								bChanged = true;
1516cdf0e10cSrcweir 							}
1517cdf0e10cSrcweir 							break;
1518cdf0e10cSrcweir 						case VALUE_TO:
1519cdf0e10cSrcweir 							if( xTransform->getTo() != rValue )
1520cdf0e10cSrcweir 							{
1521cdf0e10cSrcweir 								xTransform->setTo( rValue );
1522cdf0e10cSrcweir 								bChanged = true;
1523cdf0e10cSrcweir 							}
1524cdf0e10cSrcweir 							break;
1525cdf0e10cSrcweir 						case VALUE_BY:
1526cdf0e10cSrcweir 							if( xTransform->getBy() != rValue )
1527cdf0e10cSrcweir 							{
1528cdf0e10cSrcweir 								xTransform->setBy( rValue );
1529cdf0e10cSrcweir 								bChanged = true;
1530cdf0e10cSrcweir 							}
1531cdf0e10cSrcweir 							break;
1532cdf0e10cSrcweir 						case VALUE_FIRST:
1533cdf0e10cSrcweir 						case VALUE_LAST:
1534cdf0e10cSrcweir 							{
1535cdf0e10cSrcweir 								Sequence<Any> aValues( xTransform->getValues() );
1536cdf0e10cSrcweir 								if( !aValues.hasElements() )
1537cdf0e10cSrcweir 									aValues.realloc(1);
1538cdf0e10cSrcweir 
1539cdf0e10cSrcweir 								sal_Int32 nIndex = eValue == VALUE_FIRST ? 0 : aValues.getLength() - 1;
1540cdf0e10cSrcweir 								if( aValues[nIndex] != rValue )
1541cdf0e10cSrcweir 								{
1542cdf0e10cSrcweir 									aValues[nIndex] = rValue;
1543cdf0e10cSrcweir 									xTransform->setValues( aValues );
1544cdf0e10cSrcweir 									bChanged = true;
1545cdf0e10cSrcweir 								}
1546cdf0e10cSrcweir 							}
1547cdf0e10cSrcweir 						}
1548cdf0e10cSrcweir 					}
1549cdf0e10cSrcweir 				}
1550cdf0e10cSrcweir 			}
1551cdf0e10cSrcweir 		}
1552cdf0e10cSrcweir 	}
1553cdf0e10cSrcweir 	catch( Exception& e )
1554cdf0e10cSrcweir 	{
1555cdf0e10cSrcweir 		(void)e;
1556cdf0e10cSrcweir 		DBG_ERROR("sd::CustomAnimationEffect::setTransformationProperty(), exception cought!" );
1557cdf0e10cSrcweir 	}
1558cdf0e10cSrcweir 
1559cdf0e10cSrcweir 	return bChanged;
1560cdf0e10cSrcweir }
1561cdf0e10cSrcweir 
1562cdf0e10cSrcweir // --------------------------------------------------------------------
1563cdf0e10cSrcweir 
1564cdf0e10cSrcweir void CustomAnimationEffect::createAudio( const ::com::sun::star::uno::Any& rSource, double fVolume /* = 1.0 */ )
1565cdf0e10cSrcweir {
1566cdf0e10cSrcweir 	DBG_ASSERT( !mxAudio.is(), "sd::CustomAnimationEffect::createAudio(), node already has an audio!" );
1567cdf0e10cSrcweir 
1568cdf0e10cSrcweir 	if( !mxAudio.is() ) try
1569cdf0e10cSrcweir 	{
1570cdf0e10cSrcweir 		Reference< XMultiServiceFactory > xMsf( ::comphelper::getProcessServiceFactory() );
1571cdf0e10cSrcweir 		Reference< XAudio > xAudio( xMsf->createInstance( OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.animations.Audio") ) ), UNO_QUERY_THROW );
1572cdf0e10cSrcweir 		xAudio->setSource( rSource );
1573cdf0e10cSrcweir 		xAudio->setVolume( fVolume );
1574cdf0e10cSrcweir 		setAudio( xAudio );
1575cdf0e10cSrcweir 	}
1576cdf0e10cSrcweir 	catch( Exception& e )
1577cdf0e10cSrcweir 	{
1578cdf0e10cSrcweir 		(void)e;
1579cdf0e10cSrcweir 		DBG_ERROR("sd::CustomAnimationEffect::createAudio(), exception cought!" );
1580cdf0e10cSrcweir 	}
1581cdf0e10cSrcweir }
1582cdf0e10cSrcweir 
1583cdf0e10cSrcweir // --------------------------------------------------------------------
1584cdf0e10cSrcweir 
1585cdf0e10cSrcweir static Reference< XCommand > findCommandNode( const Reference< XAnimationNode >& xRootNode )
1586cdf0e10cSrcweir {
1587cdf0e10cSrcweir 	Reference< XCommand > xCommand;
1588cdf0e10cSrcweir 
1589cdf0e10cSrcweir 	if( xRootNode.is() ) try
1590cdf0e10cSrcweir 	{
1591cdf0e10cSrcweir 		Reference< XEnumerationAccess > xEnumerationAccess( xRootNode, UNO_QUERY_THROW );
1592cdf0e10cSrcweir 		Reference< XEnumeration > xEnumeration( xEnumerationAccess->createEnumeration(), UNO_QUERY_THROW );
1593cdf0e10cSrcweir 		while( !xCommand.is() && xEnumeration->hasMoreElements() )
1594cdf0e10cSrcweir 		{
1595cdf0e10cSrcweir 			Reference< XAnimationNode > xNode( xEnumeration->nextElement(), UNO_QUERY );
1596cdf0e10cSrcweir 			if( xNode.is() && (xNode->getType() == AnimationNodeType::COMMAND) )
1597cdf0e10cSrcweir 				xCommand.set( xNode, UNO_QUERY_THROW );
1598cdf0e10cSrcweir 		}
1599cdf0e10cSrcweir 	}
1600cdf0e10cSrcweir 	catch( Exception& e )
1601cdf0e10cSrcweir 	{
1602cdf0e10cSrcweir 		(void)e;
1603cdf0e10cSrcweir 		DBG_ERROR("sd::findCommandNode(), exception caught!" );
1604cdf0e10cSrcweir 	}
1605cdf0e10cSrcweir 
1606cdf0e10cSrcweir 	return xCommand;
1607cdf0e10cSrcweir }
1608cdf0e10cSrcweir 
1609cdf0e10cSrcweir void CustomAnimationEffect::removeAudio()
1610cdf0e10cSrcweir {
1611cdf0e10cSrcweir 	try
1612cdf0e10cSrcweir 	{
1613cdf0e10cSrcweir 		Reference< XAnimationNode > xChild;
1614cdf0e10cSrcweir 
1615cdf0e10cSrcweir 		if( mxAudio.is() )
1616cdf0e10cSrcweir 		{
1617cdf0e10cSrcweir 			xChild.set( mxAudio, UNO_QUERY );
1618cdf0e10cSrcweir 			mxAudio.clear();
1619cdf0e10cSrcweir 		}
1620cdf0e10cSrcweir 		else if( mnCommand == EffectCommands::STOPAUDIO )
1621cdf0e10cSrcweir 		{
1622cdf0e10cSrcweir 			xChild.set( findCommandNode( mxNode ), UNO_QUERY );
1623cdf0e10cSrcweir 			mnCommand = 0;
1624cdf0e10cSrcweir 		}
1625cdf0e10cSrcweir 
1626cdf0e10cSrcweir 		if( xChild.is() )
1627cdf0e10cSrcweir 		{
1628cdf0e10cSrcweir 			Reference< XTimeContainer > xContainer( mxNode, UNO_QUERY );
1629cdf0e10cSrcweir 			if( xContainer.is() )
1630cdf0e10cSrcweir 				xContainer->removeChild( xChild );
1631cdf0e10cSrcweir 		}
1632cdf0e10cSrcweir 	}
1633cdf0e10cSrcweir 	catch( Exception& e )
1634cdf0e10cSrcweir 	{
1635cdf0e10cSrcweir 		(void)e;
1636cdf0e10cSrcweir 		DBG_ERROR("sd::CustomAnimationEffect::removeAudio(), exception caught!" );
1637cdf0e10cSrcweir 	}
1638cdf0e10cSrcweir 
1639cdf0e10cSrcweir }
1640cdf0e10cSrcweir 
1641cdf0e10cSrcweir // --------------------------------------------------------------------
1642cdf0e10cSrcweir 
1643cdf0e10cSrcweir void CustomAnimationEffect::setAudio( const Reference< ::com::sun::star::animations::XAudio >& xAudio )
1644cdf0e10cSrcweir {
1645cdf0e10cSrcweir 	if( mxAudio != xAudio ) try
1646cdf0e10cSrcweir 	{
1647cdf0e10cSrcweir 		removeAudio();
1648cdf0e10cSrcweir 		mxAudio = xAudio;
1649cdf0e10cSrcweir 		Reference< XTimeContainer > xContainer( mxNode, UNO_QUERY );
1650cdf0e10cSrcweir 		Reference< XAnimationNode > xChild( mxAudio, UNO_QUERY );
1651cdf0e10cSrcweir 		if( xContainer.is() && xChild.is() )
1652cdf0e10cSrcweir 			xContainer->appendChild( xChild );
1653cdf0e10cSrcweir 	}
1654cdf0e10cSrcweir 	catch( Exception& e )
1655cdf0e10cSrcweir 	{
1656cdf0e10cSrcweir 		(void)e;
1657cdf0e10cSrcweir 		DBG_ERROR("sd::CustomAnimationEffect::setAudio(), exception caught!" );
1658cdf0e10cSrcweir 	}
1659cdf0e10cSrcweir }
1660cdf0e10cSrcweir 
1661cdf0e10cSrcweir // --------------------------------------------------------------------
1662cdf0e10cSrcweir 
1663cdf0e10cSrcweir void CustomAnimationEffect::setStopAudio()
1664cdf0e10cSrcweir {
1665cdf0e10cSrcweir 	if( mnCommand != EffectCommands::STOPAUDIO ) try
1666cdf0e10cSrcweir 	{
1667cdf0e10cSrcweir 		if( mxAudio.is() )
1668cdf0e10cSrcweir 			removeAudio();
1669cdf0e10cSrcweir 
1670cdf0e10cSrcweir 		Reference< XMultiServiceFactory > xMsf( ::comphelper::getProcessServiceFactory() );
1671cdf0e10cSrcweir 		Reference< XCommand > xCommand( xMsf->createInstance( OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.animations.Command") ) ), UNO_QUERY_THROW );
1672cdf0e10cSrcweir 
1673cdf0e10cSrcweir 		xCommand->setCommand( EffectCommands::STOPAUDIO );
1674cdf0e10cSrcweir 
1675cdf0e10cSrcweir 		Reference< XTimeContainer > xContainer( mxNode, UNO_QUERY_THROW );
1676cdf0e10cSrcweir 		Reference< XAnimationNode > xChild( xCommand, UNO_QUERY_THROW );
1677cdf0e10cSrcweir 		xContainer->appendChild( xChild );
1678cdf0e10cSrcweir 
1679cdf0e10cSrcweir 		mnCommand = EffectCommands::STOPAUDIO;
1680cdf0e10cSrcweir 	}
1681cdf0e10cSrcweir 	catch( Exception& e )
1682cdf0e10cSrcweir 	{
1683cdf0e10cSrcweir 		(void)e;
1684cdf0e10cSrcweir 		DBG_ERROR("sd::CustomAnimationEffect::setStopAudio(), exception caught!" );
1685cdf0e10cSrcweir 	}
1686cdf0e10cSrcweir }
1687cdf0e10cSrcweir 
1688cdf0e10cSrcweir // --------------------------------------------------------------------
1689cdf0e10cSrcweir 
1690cdf0e10cSrcweir bool CustomAnimationEffect::getStopAudio() const
1691cdf0e10cSrcweir {
1692cdf0e10cSrcweir 	return mnCommand == EffectCommands::STOPAUDIO;
1693cdf0e10cSrcweir }
1694cdf0e10cSrcweir 
1695cdf0e10cSrcweir // --------------------------------------------------------------------
1696cdf0e10cSrcweir 
1697cdf0e10cSrcweir SdrPathObj* CustomAnimationEffect::createSdrPathObjFromPath()
1698cdf0e10cSrcweir {
1699cdf0e10cSrcweir 	SdrPathObj * pPathObj = new SdrPathObj( OBJ_PATHLINE );
1700cdf0e10cSrcweir 	updateSdrPathObjFromPath( *pPathObj );
1701cdf0e10cSrcweir 	return pPathObj;
1702cdf0e10cSrcweir }
1703cdf0e10cSrcweir 
1704cdf0e10cSrcweir // --------------------------------------------------------------------
1705cdf0e10cSrcweir 
1706cdf0e10cSrcweir void CustomAnimationEffect::updateSdrPathObjFromPath( SdrPathObj& rPathObj )
1707cdf0e10cSrcweir {
1708cdf0e10cSrcweir 	::basegfx::B2DPolyPolygon xPolyPoly;
1709*1f882ec4SArmin Le Grand 	if( ::basegfx::tools::importFromSvgD( xPolyPoly, getPath(), true, 0 ) )
1710cdf0e10cSrcweir 	{
1711cdf0e10cSrcweir 		SdrObject* pObj = GetSdrObjectFromXShape( getTargetShape() );
1712cdf0e10cSrcweir 		if( pObj )
1713cdf0e10cSrcweir 		{
1714cdf0e10cSrcweir 			SdrPage* pPage = pObj->GetPage();
1715cdf0e10cSrcweir 			if( pPage )
1716cdf0e10cSrcweir 			{
1717cdf0e10cSrcweir 				const Size aPageSize( pPage->GetSize() );
1718cdf0e10cSrcweir                 xPolyPoly.transform(basegfx::tools::createScaleB2DHomMatrix((double)aPageSize.Width(), (double)aPageSize.Height()));
1719cdf0e10cSrcweir 			}
1720cdf0e10cSrcweir 
1721cdf0e10cSrcweir 			const Rectangle aBoundRect( pObj->GetCurrentBoundRect() );
1722cdf0e10cSrcweir 			const Point aCenter( aBoundRect.Center() );
1723cdf0e10cSrcweir             xPolyPoly.transform(basegfx::tools::createTranslateB2DHomMatrix(aCenter.X(), aCenter.Y()));
1724cdf0e10cSrcweir 		}
1725cdf0e10cSrcweir 	}
1726cdf0e10cSrcweir 
1727cdf0e10cSrcweir 	rPathObj.SetPathPoly( xPolyPoly );
1728cdf0e10cSrcweir }
1729cdf0e10cSrcweir 
1730cdf0e10cSrcweir // --------------------------------------------------------------------
1731cdf0e10cSrcweir 
1732cdf0e10cSrcweir void CustomAnimationEffect::updatePathFromSdrPathObj( const SdrPathObj& rPathObj )
1733cdf0e10cSrcweir {
1734cdf0e10cSrcweir 	::basegfx::B2DPolyPolygon xPolyPoly( rPathObj.GetPathPoly() );
1735cdf0e10cSrcweir 
1736cdf0e10cSrcweir 	SdrObject* pObj = GetSdrObjectFromXShape( getTargetShape() );
1737cdf0e10cSrcweir 	if( pObj )
1738cdf0e10cSrcweir 	{
1739cdf0e10cSrcweir 		Rectangle aBoundRect(0,0,0,0);
1740cdf0e10cSrcweir 
1741cdf0e10cSrcweir     	const drawinglayer::primitive2d::Primitive2DSequence xPrimitives(pObj->GetViewContact().getViewIndependentPrimitive2DSequence());
1742cdf0e10cSrcweir 	    const drawinglayer::geometry::ViewInformation2D aViewInformation2D;
1743cdf0e10cSrcweir    		const basegfx::B2DRange aRange(drawinglayer::primitive2d::getB2DRangeFromPrimitive2DSequence(xPrimitives, aViewInformation2D));
1744cdf0e10cSrcweir 
1745cdf0e10cSrcweir 		if(!aRange.isEmpty())
1746cdf0e10cSrcweir 		{
1747cdf0e10cSrcweir 			aBoundRect = Rectangle(
1748cdf0e10cSrcweir 					(sal_Int32)floor(aRange.getMinX()), (sal_Int32)floor(aRange.getMinY()),
1749cdf0e10cSrcweir 					(sal_Int32)ceil(aRange.getMaxX()), (sal_Int32)ceil(aRange.getMaxY()));
1750cdf0e10cSrcweir 		}
1751cdf0e10cSrcweir 
1752cdf0e10cSrcweir 		const Point aCenter( aBoundRect.Center() );
1753cdf0e10cSrcweir 
1754cdf0e10cSrcweir         xPolyPoly.transform(basegfx::tools::createTranslateB2DHomMatrix(-aCenter.X(), -aCenter.Y()));
1755cdf0e10cSrcweir 
1756cdf0e10cSrcweir 		SdrPage* pPage = pObj->GetPage();
1757cdf0e10cSrcweir 		if( pPage )
1758cdf0e10cSrcweir 		{
1759cdf0e10cSrcweir 			const Size aPageSize( pPage->GetSize() );
1760cdf0e10cSrcweir             xPolyPoly.transform(basegfx::tools::createScaleB2DHomMatrix(
1761cdf0e10cSrcweir                 1.0 / (double)aPageSize.Width(), 1.0 / (double)aPageSize.Height()));
1762cdf0e10cSrcweir 		}
1763cdf0e10cSrcweir 	}
1764cdf0e10cSrcweir 
1765*1f882ec4SArmin Le Grand 	setPath( ::basegfx::tools::exportToSvgD( xPolyPoly, true, true, true) );
1766cdf0e10cSrcweir }
1767cdf0e10cSrcweir 
1768cdf0e10cSrcweir // ====================================================================
1769cdf0e10cSrcweir 
1770cdf0e10cSrcweir EffectSequenceHelper::EffectSequenceHelper()
1771cdf0e10cSrcweir : mnSequenceType( EffectNodeType::DEFAULT )
1772cdf0e10cSrcweir {
1773cdf0e10cSrcweir }
1774cdf0e10cSrcweir 
1775cdf0e10cSrcweir // --------------------------------------------------------------------
1776cdf0e10cSrcweir 
1777cdf0e10cSrcweir EffectSequenceHelper::EffectSequenceHelper( const ::com::sun::star::uno::Reference< ::com::sun::star::animations::XTimeContainer >& xSequenceRoot )
1778cdf0e10cSrcweir : mxSequenceRoot( xSequenceRoot ), mnSequenceType( EffectNodeType::DEFAULT )
1779cdf0e10cSrcweir {
1780cdf0e10cSrcweir 	Reference< XAnimationNode > xNode( mxSequenceRoot, UNO_QUERY_THROW );
1781cdf0e10cSrcweir 	create( xNode );
1782cdf0e10cSrcweir }
1783cdf0e10cSrcweir 
1784cdf0e10cSrcweir // --------------------------------------------------------------------
1785cdf0e10cSrcweir 
1786cdf0e10cSrcweir EffectSequenceHelper::~EffectSequenceHelper()
1787cdf0e10cSrcweir {
1788cdf0e10cSrcweir 	reset();
1789cdf0e10cSrcweir }
1790cdf0e10cSrcweir 
1791cdf0e10cSrcweir // --------------------------------------------------------------------
1792cdf0e10cSrcweir 
1793cdf0e10cSrcweir void EffectSequenceHelper::reset()
1794cdf0e10cSrcweir {
1795cdf0e10cSrcweir 	EffectSequence::iterator aIter( maEffects.begin() );
1796cdf0e10cSrcweir 	EffectSequence::iterator aEnd( maEffects.end() );
1797cdf0e10cSrcweir 	if( aIter != aEnd )
1798cdf0e10cSrcweir 	{
1799cdf0e10cSrcweir 		CustomAnimationEffectPtr pEffect = (*aIter++);
1800cdf0e10cSrcweir 		pEffect->setEffectSequence(0);
1801cdf0e10cSrcweir 	}
1802cdf0e10cSrcweir 	maEffects.clear();
1803cdf0e10cSrcweir }
1804cdf0e10cSrcweir 
1805cdf0e10cSrcweir Reference< XAnimationNode > EffectSequenceHelper::getRootNode()
1806cdf0e10cSrcweir {
1807cdf0e10cSrcweir 	Reference< XAnimationNode > xRoot( mxSequenceRoot, UNO_QUERY );
1808cdf0e10cSrcweir 	return xRoot;
1809cdf0e10cSrcweir }
1810cdf0e10cSrcweir 
1811cdf0e10cSrcweir // --------------------------------------------------------------------
1812cdf0e10cSrcweir 
1813cdf0e10cSrcweir void EffectSequenceHelper::append( const CustomAnimationEffectPtr& pEffect )
1814cdf0e10cSrcweir {
1815cdf0e10cSrcweir 	pEffect->setEffectSequence( this );
1816cdf0e10cSrcweir 	maEffects.push_back(pEffect);
1817cdf0e10cSrcweir 	rebuild();
1818cdf0e10cSrcweir }
1819cdf0e10cSrcweir 
1820cdf0e10cSrcweir // --------------------------------------------------------------------
1821cdf0e10cSrcweir 
1822cdf0e10cSrcweir CustomAnimationEffectPtr EffectSequenceHelper::append( const CustomAnimationPresetPtr& pPreset, const Any& rTarget, double fDuration /* = -1.0 */ )
1823cdf0e10cSrcweir {
1824cdf0e10cSrcweir 	CustomAnimationEffectPtr pEffect;
1825cdf0e10cSrcweir 
1826cdf0e10cSrcweir 	if( pPreset.get() )
1827cdf0e10cSrcweir 	{
1828cdf0e10cSrcweir 		OUString strEmpty;
1829cdf0e10cSrcweir 		Reference< XAnimationNode > xNode( pPreset->create( strEmpty ) );
1830cdf0e10cSrcweir 		if( xNode.is() )
1831cdf0e10cSrcweir 		{
1832cdf0e10cSrcweir 			// first, filter all only ui relevant user data
1833cdf0e10cSrcweir 			std::vector< NamedValue > aNewUserData;
1834cdf0e10cSrcweir 			Sequence< NamedValue > aUserData( xNode->getUserData() );
1835cdf0e10cSrcweir 			sal_Int32 nLength = aUserData.getLength();
1836cdf0e10cSrcweir 			const NamedValue* p = aUserData.getConstArray();
1837cdf0e10cSrcweir 			bool bFilter = false;
1838cdf0e10cSrcweir 
1839cdf0e10cSrcweir 			while( nLength-- )
1840cdf0e10cSrcweir 			{
1841cdf0e10cSrcweir 				if( !p->Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "text-only" ) ) &&
1842cdf0e10cSrcweir 					!p->Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "preset-property" ) ) )
1843cdf0e10cSrcweir 				{
1844cdf0e10cSrcweir 					aNewUserData.push_back( *p );
1845cdf0e10cSrcweir 					bFilter = true;
1846cdf0e10cSrcweir 				}
1847cdf0e10cSrcweir 				p++;
1848cdf0e10cSrcweir 			}
1849cdf0e10cSrcweir 
1850cdf0e10cSrcweir 			if( bFilter )
1851cdf0e10cSrcweir 			{
1852cdf0e10cSrcweir 				aUserData = ::comphelper::containerToSequence< NamedValue, std::vector< NamedValue > >( aNewUserData );
1853cdf0e10cSrcweir 				xNode->setUserData( aUserData );
1854cdf0e10cSrcweir 			}
1855cdf0e10cSrcweir 
1856cdf0e10cSrcweir 			// check target, maybe we need to force it to text
1857cdf0e10cSrcweir 			Any aTarget( rTarget );
1858cdf0e10cSrcweir 			sal_Int16 nSubItem = ShapeAnimationSubType::AS_WHOLE;
1859cdf0e10cSrcweir 
1860cdf0e10cSrcweir 			if(	aTarget.getValueType() == ::getCppuType((const ParagraphTarget*)0) )
1861cdf0e10cSrcweir 			{
1862cdf0e10cSrcweir 				nSubItem = ShapeAnimationSubType::ONLY_TEXT;
1863cdf0e10cSrcweir 			}
1864cdf0e10cSrcweir 			else if( pPreset->isTextOnly() )
1865cdf0e10cSrcweir 			{
1866cdf0e10cSrcweir 				Reference< XShape > xShape;
1867cdf0e10cSrcweir 				aTarget >>= xShape;
1868cdf0e10cSrcweir 				if( xShape.is() )
1869cdf0e10cSrcweir 				{
1870cdf0e10cSrcweir 					// thats bad, we target a shape here but the effect is only for text
1871cdf0e10cSrcweir 					// so change subitem
1872cdf0e10cSrcweir 					nSubItem = ShapeAnimationSubType::ONLY_TEXT;
1873cdf0e10cSrcweir 				}
1874cdf0e10cSrcweir 			}
1875cdf0e10cSrcweir 
1876cdf0e10cSrcweir 			// now create effect from preset
1877cdf0e10cSrcweir 			pEffect.reset( new CustomAnimationEffect( xNode ) );
1878cdf0e10cSrcweir 			pEffect->setEffectSequence( this );
1879cdf0e10cSrcweir 			pEffect->setTarget( aTarget );
1880cdf0e10cSrcweir 			pEffect->setTargetSubItem( nSubItem );
1881cdf0e10cSrcweir 			if( fDuration != -1.0 )
1882cdf0e10cSrcweir 				pEffect->setDuration( fDuration );
1883cdf0e10cSrcweir 
1884cdf0e10cSrcweir 			maEffects.push_back(pEffect);
1885cdf0e10cSrcweir 
1886cdf0e10cSrcweir 			rebuild();
1887cdf0e10cSrcweir 		}
1888cdf0e10cSrcweir 	}
1889cdf0e10cSrcweir 
1890cdf0e10cSrcweir 	DBG_ASSERT( pEffect.get(), "sd::EffectSequenceHelper::append(), failed!" );
1891cdf0e10cSrcweir 	return pEffect;
1892cdf0e10cSrcweir }
1893cdf0e10cSrcweir 
1894cdf0e10cSrcweir // --------------------------------------------------------------------
1895cdf0e10cSrcweir 
1896cdf0e10cSrcweir CustomAnimationEffectPtr EffectSequenceHelper::append( const SdrPathObj& rPathObj, const Any& rTarget, double fDuration /* = -1.0 */ )
1897cdf0e10cSrcweir {
1898cdf0e10cSrcweir 	CustomAnimationEffectPtr pEffect;
1899cdf0e10cSrcweir 
1900cdf0e10cSrcweir 	if( fDuration <= 0.0 )
1901cdf0e10cSrcweir 		fDuration = 2.0;
1902cdf0e10cSrcweir 
1903cdf0e10cSrcweir 	try
1904cdf0e10cSrcweir 	{
1905cdf0e10cSrcweir 		Reference< XTimeContainer > xEffectContainer( createParallelTimeContainer() );
1906cdf0e10cSrcweir 		const OUString aServiceName( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.animations.AnimateMotion" ) );
1907cdf0e10cSrcweir 		Reference< XAnimationNode > xAnimateMotion( ::comphelper::getProcessServiceFactory()->createInstance(aServiceName), UNO_QUERY_THROW );
1908cdf0e10cSrcweir 
1909cdf0e10cSrcweir 		xAnimateMotion->setDuration( Any( fDuration ) );
1910cdf0e10cSrcweir 		xAnimateMotion->setFill( AnimationFill::HOLD );
1911cdf0e10cSrcweir 		xEffectContainer->appendChild( xAnimateMotion );
1912cdf0e10cSrcweir 
1913cdf0e10cSrcweir 		sal_Int16 nSubItem = ShapeAnimationSubType::AS_WHOLE;
1914cdf0e10cSrcweir 
1915cdf0e10cSrcweir 		if(	rTarget.getValueType() == ::getCppuType((const ParagraphTarget*)0) )
1916cdf0e10cSrcweir 			nSubItem = ShapeAnimationSubType::ONLY_TEXT;
1917cdf0e10cSrcweir 
1918cdf0e10cSrcweir 		Reference< XAnimationNode > xEffectNode( xEffectContainer, UNO_QUERY_THROW );
1919cdf0e10cSrcweir 		pEffect.reset( new CustomAnimationEffect( xEffectNode ) );
1920cdf0e10cSrcweir 		pEffect->setEffectSequence( this );
1921cdf0e10cSrcweir 		pEffect->setTarget( rTarget );
1922cdf0e10cSrcweir 		pEffect->setTargetSubItem( nSubItem );
1923cdf0e10cSrcweir 		pEffect->setNodeType( ::com::sun::star::presentation::EffectNodeType::ON_CLICK );
1924cdf0e10cSrcweir 		pEffect->setPresetClass( ::com::sun::star::presentation::EffectPresetClass::MOTIONPATH );
1925cdf0e10cSrcweir 		pEffect->setAcceleration( 0.5 );
1926cdf0e10cSrcweir 		pEffect->setDecelerate( 0.5 );
1927cdf0e10cSrcweir 		pEffect->setFill( AnimationFill::HOLD );
1928cdf0e10cSrcweir 		pEffect->setBegin( 0.0 );
1929cdf0e10cSrcweir 		pEffect->updatePathFromSdrPathObj( rPathObj );
1930cdf0e10cSrcweir 		if( fDuration != -1.0 )
1931cdf0e10cSrcweir 			pEffect->setDuration( fDuration );
1932cdf0e10cSrcweir 
1933cdf0e10cSrcweir 		maEffects.push_back(pEffect);
1934cdf0e10cSrcweir 
1935cdf0e10cSrcweir 		rebuild();
1936cdf0e10cSrcweir 	}
1937cdf0e10cSrcweir 	catch( Exception& )
1938cdf0e10cSrcweir 	{
1939cdf0e10cSrcweir 		DBG_ERROR( "sd::EffectSequenceHelper::append(), exception cought!" );
1940cdf0e10cSrcweir 	}
1941cdf0e10cSrcweir 
1942cdf0e10cSrcweir 	return pEffect;
1943cdf0e10cSrcweir }
1944cdf0e10cSrcweir 
1945cdf0e10cSrcweir // --------------------------------------------------------------------
1946cdf0e10cSrcweir 
1947cdf0e10cSrcweir void EffectSequenceHelper::replace( const CustomAnimationEffectPtr& pEffect, const CustomAnimationPresetPtr& pPreset, const OUString& rPresetSubType, double fDuration /* = -1.0 */ )
1948cdf0e10cSrcweir {
1949cdf0e10cSrcweir 	if( pEffect.get() && pPreset.get() ) try
1950cdf0e10cSrcweir 	{
1951cdf0e10cSrcweir 		Reference< XAnimationNode > xNewNode( pPreset->create( rPresetSubType ) );
1952cdf0e10cSrcweir 		if( xNewNode.is() )
1953cdf0e10cSrcweir 		{
1954cdf0e10cSrcweir 			pEffect->replaceNode( xNewNode );
1955cdf0e10cSrcweir 			if( fDuration != -1.0 )
1956cdf0e10cSrcweir 				pEffect->setDuration( fDuration );
1957cdf0e10cSrcweir 		}
1958cdf0e10cSrcweir 
1959cdf0e10cSrcweir 		rebuild();
1960cdf0e10cSrcweir 	}
1961cdf0e10cSrcweir 	catch( Exception& e )
1962cdf0e10cSrcweir 	{
1963cdf0e10cSrcweir 		(void)e;
1964cdf0e10cSrcweir 		DBG_ERROR( "sd::EffectSequenceHelper::replace(), exception cought!" );
1965cdf0e10cSrcweir 	}
1966cdf0e10cSrcweir }
1967cdf0e10cSrcweir 
1968cdf0e10cSrcweir // --------------------------------------------------------------------
1969cdf0e10cSrcweir 
1970cdf0e10cSrcweir void EffectSequenceHelper::replace( const CustomAnimationEffectPtr& pEffect, const CustomAnimationPresetPtr& pPreset, double fDuration /* = -1.0 */ )
1971cdf0e10cSrcweir {
1972cdf0e10cSrcweir 	OUString strEmpty;
1973cdf0e10cSrcweir 	replace( pEffect, pPreset, strEmpty, fDuration );
1974cdf0e10cSrcweir }
1975cdf0e10cSrcweir 
1976cdf0e10cSrcweir // --------------------------------------------------------------------
1977cdf0e10cSrcweir 
1978cdf0e10cSrcweir void EffectSequenceHelper::remove( const CustomAnimationEffectPtr& pEffect )
1979cdf0e10cSrcweir {
1980cdf0e10cSrcweir 	if( pEffect.get() )
1981cdf0e10cSrcweir 	{
1982cdf0e10cSrcweir 		pEffect->setEffectSequence( 0 );
1983cdf0e10cSrcweir 		maEffects.remove( pEffect );
1984cdf0e10cSrcweir 	}
1985cdf0e10cSrcweir 
1986cdf0e10cSrcweir 	rebuild();
1987cdf0e10cSrcweir }
1988cdf0e10cSrcweir 
1989cdf0e10cSrcweir // --------------------------------------------------------------------
1990cdf0e10cSrcweir 
1991cdf0e10cSrcweir void EffectSequenceHelper::rebuild()
1992cdf0e10cSrcweir {
1993cdf0e10cSrcweir 	implRebuild();
1994cdf0e10cSrcweir }
1995cdf0e10cSrcweir 
1996cdf0e10cSrcweir // --------------------------------------------------------------------
1997cdf0e10cSrcweir 
1998cdf0e10cSrcweir void EffectSequenceHelper::implRebuild()
1999cdf0e10cSrcweir {
2000cdf0e10cSrcweir 	try
2001cdf0e10cSrcweir 	{
2002cdf0e10cSrcweir 		// first we delete all time containers on the first two levels
2003cdf0e10cSrcweir 		Reference< XEnumerationAccess > xEnumerationAccess( mxSequenceRoot, UNO_QUERY_THROW );
2004cdf0e10cSrcweir 		Reference< XEnumeration > xEnumeration( xEnumerationAccess->createEnumeration(), UNO_QUERY_THROW );
2005cdf0e10cSrcweir 		while( xEnumeration->hasMoreElements() )
2006cdf0e10cSrcweir 		{
2007cdf0e10cSrcweir 			Reference< XAnimationNode > xChildNode( xEnumeration->nextElement(), UNO_QUERY_THROW );
2008cdf0e10cSrcweir 			Reference< XTimeContainer > xChildContainer( xChildNode, UNO_QUERY_THROW );
2009cdf0e10cSrcweir 
2010cdf0e10cSrcweir 			Reference< XEnumerationAccess > xChildEnumerationAccess( xChildNode, UNO_QUERY_THROW );
2011cdf0e10cSrcweir 			Reference< XEnumeration > xChildEnumeration( xChildEnumerationAccess->createEnumeration(), UNO_QUERY_THROW );
2012cdf0e10cSrcweir 			while( xChildEnumeration->hasMoreElements() )
2013cdf0e10cSrcweir 			{
2014cdf0e10cSrcweir 				Reference< XAnimationNode > xNode( xChildEnumeration->nextElement(), UNO_QUERY_THROW );
2015cdf0e10cSrcweir 				xChildContainer->removeChild( xNode );
2016cdf0e10cSrcweir 			}
2017cdf0e10cSrcweir 
2018cdf0e10cSrcweir 			mxSequenceRoot->removeChild( xChildNode );
2019cdf0e10cSrcweir 		}
2020cdf0e10cSrcweir 
2021cdf0e10cSrcweir 		// second, rebuild main sequence
2022cdf0e10cSrcweir 		EffectSequence::iterator aIter( maEffects.begin() );
2023cdf0e10cSrcweir 		EffectSequence::iterator aEnd( maEffects.end() );
2024cdf0e10cSrcweir 		if( aIter != aEnd )
2025cdf0e10cSrcweir 		{
2026cdf0e10cSrcweir 			AfterEffectNodeList aAfterEffects;
2027cdf0e10cSrcweir 
2028cdf0e10cSrcweir 			CustomAnimationEffectPtr pEffect = (*aIter++);
2029cdf0e10cSrcweir 
2030cdf0e10cSrcweir 			bool bFirst = true;
2031cdf0e10cSrcweir 			do
2032cdf0e10cSrcweir 			{
2033cdf0e10cSrcweir 				// create a par container for the next click node and all following with and after effects
2034cdf0e10cSrcweir 				Reference< XTimeContainer > xOnClickContainer( createParallelTimeContainer() );
2035cdf0e10cSrcweir 
2036cdf0e10cSrcweir 				Event aEvent;
2037cdf0e10cSrcweir 				if( mxEventSource.is() )
2038cdf0e10cSrcweir                 {
2039cdf0e10cSrcweir 					aEvent.Source <<= mxEventSource;
2040cdf0e10cSrcweir                     aEvent.Trigger = EventTrigger::ON_CLICK;
2041cdf0e10cSrcweir                 }
2042cdf0e10cSrcweir                 else
2043cdf0e10cSrcweir                 {
2044cdf0e10cSrcweir                     aEvent.Trigger = EventTrigger::ON_NEXT;
2045cdf0e10cSrcweir                 }
2046cdf0e10cSrcweir                 aEvent.Repeat = 0;
2047cdf0e10cSrcweir 
2048cdf0e10cSrcweir 				Any aBegin( makeAny( aEvent ) );
2049cdf0e10cSrcweir 				if( bFirst )
2050cdf0e10cSrcweir 				{
2051cdf0e10cSrcweir 					// if the first node is not a click action, this click container
2052cdf0e10cSrcweir 					// must not have INDEFINITE begin but start at 0s
2053cdf0e10cSrcweir 					bFirst = false;
2054cdf0e10cSrcweir 					if( pEffect->getNodeType() != EffectNodeType::ON_CLICK )
2055cdf0e10cSrcweir 						aBegin <<= (double)0.0;
2056cdf0e10cSrcweir 				}
2057cdf0e10cSrcweir 
2058cdf0e10cSrcweir 				xOnClickContainer->setBegin( aBegin );
2059cdf0e10cSrcweir 
2060cdf0e10cSrcweir 				Reference< XAnimationNode > xOnClickContainerNode( xOnClickContainer, UNO_QUERY_THROW );
2061cdf0e10cSrcweir 				mxSequenceRoot->appendChild( xOnClickContainerNode );
2062cdf0e10cSrcweir 
2063cdf0e10cSrcweir 				double fBegin = 0.0;
2064cdf0e10cSrcweir 
2065cdf0e10cSrcweir 				do
2066cdf0e10cSrcweir 				{
2067cdf0e10cSrcweir 					// create a par container for the current click or after effect node and all following with effects
2068cdf0e10cSrcweir 					Reference< XTimeContainer > xWithContainer( createParallelTimeContainer() );
2069cdf0e10cSrcweir 					Reference< XAnimationNode > xWithContainerNode( xWithContainer, UNO_QUERY_THROW );
2070cdf0e10cSrcweir 					xWithContainer->setBegin( makeAny( fBegin ) );
2071cdf0e10cSrcweir 					xOnClickContainer->appendChild( xWithContainerNode );
2072cdf0e10cSrcweir 
2073cdf0e10cSrcweir 					double fDuration = 0.0;
2074cdf0e10cSrcweir 					do
2075cdf0e10cSrcweir 					{
2076cdf0e10cSrcweir 						Reference< XAnimationNode > xEffectNode( pEffect->getNode() );
2077cdf0e10cSrcweir 						xWithContainer->appendChild( xEffectNode );
2078cdf0e10cSrcweir 
2079cdf0e10cSrcweir 						if( pEffect->hasAfterEffect() )
2080cdf0e10cSrcweir 						{
2081cdf0e10cSrcweir 							Reference< XAnimationNode > xAfterEffect( pEffect->createAfterEffectNode() );
2082cdf0e10cSrcweir 							AfterEffectNode a( xAfterEffect, xEffectNode, pEffect->IsAfterEffectOnNext() );
2083cdf0e10cSrcweir 							aAfterEffects.push_back( a );
2084cdf0e10cSrcweir 						}
2085cdf0e10cSrcweir 
2086cdf0e10cSrcweir 						double fTemp = pEffect->getBegin() + pEffect->getAbsoluteDuration();
2087cdf0e10cSrcweir 						if( fTemp > fDuration )
2088cdf0e10cSrcweir 							fDuration = fTemp;
2089cdf0e10cSrcweir 
2090cdf0e10cSrcweir 						if( aIter != aEnd )
2091cdf0e10cSrcweir 							pEffect = (*aIter++);
2092cdf0e10cSrcweir 						else
2093cdf0e10cSrcweir 							pEffect.reset();
2094cdf0e10cSrcweir 					}
2095cdf0e10cSrcweir 					while( pEffect.get() && (pEffect->getNodeType() == EffectNodeType::WITH_PREVIOUS) );
2096cdf0e10cSrcweir 
2097cdf0e10cSrcweir 					fBegin += fDuration;
2098cdf0e10cSrcweir 				}
2099cdf0e10cSrcweir 				while( pEffect.get() && (pEffect->getNodeType() != EffectNodeType::ON_CLICK) );
2100cdf0e10cSrcweir 			}
2101cdf0e10cSrcweir 			while( pEffect.get() );
2102cdf0e10cSrcweir 
2103cdf0e10cSrcweir 			// process after effect nodes
2104cdf0e10cSrcweir 			std::for_each( aAfterEffects.begin(), aAfterEffects.end(), stl_process_after_effect_node_func );
2105cdf0e10cSrcweir 
2106cdf0e10cSrcweir 			updateTextGroups();
2107cdf0e10cSrcweir 
2108cdf0e10cSrcweir             // reset duration, might have been altered (see below)
2109cdf0e10cSrcweir             mxSequenceRoot->setDuration( Any() );
2110cdf0e10cSrcweir 		}
2111cdf0e10cSrcweir         else
2112cdf0e10cSrcweir         {
2113cdf0e10cSrcweir             // empty sequence, set duration to 0.0 explicitely
2114cdf0e10cSrcweir             // (otherwise, this sequence will never end)
2115cdf0e10cSrcweir             mxSequenceRoot->setDuration( makeAny((double)0.0) );
2116cdf0e10cSrcweir         }
2117cdf0e10cSrcweir 	}
2118cdf0e10cSrcweir 	catch( Exception& e )
2119cdf0e10cSrcweir 	{
2120cdf0e10cSrcweir 		(void)e;
2121cdf0e10cSrcweir 		DBG_ERROR( "sd::EffectSequenceHelper::rebuild(), exception cought!" );
2122cdf0e10cSrcweir 	}
2123cdf0e10cSrcweir }
2124cdf0e10cSrcweir 
2125cdf0e10cSrcweir // --------------------------------------------------------------------
2126cdf0e10cSrcweir 
2127cdf0e10cSrcweir Reference< XTimeContainer > EffectSequenceHelper::createParallelTimeContainer() const
2128cdf0e10cSrcweir {
2129cdf0e10cSrcweir 	const OUString aServiceName( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.animations.ParallelTimeContainer" ) );
2130cdf0e10cSrcweir 	return Reference< XTimeContainer >( ::comphelper::getProcessServiceFactory()->createInstance(aServiceName), UNO_QUERY );
2131cdf0e10cSrcweir }
2132cdf0e10cSrcweir 
2133cdf0e10cSrcweir // --------------------------------------------------------------------
2134cdf0e10cSrcweir 
2135cdf0e10cSrcweir stl_CustomAnimationEffect_search_node_predict::stl_CustomAnimationEffect_search_node_predict( const ::com::sun::star::uno::Reference< ::com::sun::star::animations::XAnimationNode >& xSearchNode )
2136cdf0e10cSrcweir : mxSearchNode( xSearchNode )
2137cdf0e10cSrcweir {
2138cdf0e10cSrcweir }
2139cdf0e10cSrcweir 
2140cdf0e10cSrcweir // --------------------------------------------------------------------
2141cdf0e10cSrcweir 
2142cdf0e10cSrcweir bool stl_CustomAnimationEffect_search_node_predict::operator()( CustomAnimationEffectPtr pEffect ) const
2143cdf0e10cSrcweir {
2144cdf0e10cSrcweir 	return pEffect->getNode() == mxSearchNode;
2145cdf0e10cSrcweir }
2146cdf0e10cSrcweir 
2147cdf0e10cSrcweir // --------------------------------------------------------------------
2148cdf0e10cSrcweir 
2149cdf0e10cSrcweir static bool implFindNextContainer( Reference< XTimeContainer >& xParent, Reference< XTimeContainer >& xCurrent, Reference< XTimeContainer >& xNext )
2150cdf0e10cSrcweir  throw(Exception)
2151cdf0e10cSrcweir {
2152cdf0e10cSrcweir 	Reference< XEnumerationAccess > xEnumerationAccess( xParent, UNO_QUERY_THROW );
2153cdf0e10cSrcweir 	Reference< XEnumeration > xEnumeration( xEnumerationAccess->createEnumeration() );
2154cdf0e10cSrcweir 	if( xEnumeration.is() )
2155cdf0e10cSrcweir 	{
2156cdf0e10cSrcweir 		Reference< XInterface > x;
2157cdf0e10cSrcweir 		while( xEnumeration->hasMoreElements() && !xNext.is() )
2158cdf0e10cSrcweir 		{
2159cdf0e10cSrcweir 			if( (xEnumeration->nextElement() >>= x) && (x == xCurrent) )
2160cdf0e10cSrcweir 			{
2161cdf0e10cSrcweir 				if( xEnumeration->hasMoreElements() )
2162cdf0e10cSrcweir 					xEnumeration->nextElement() >>= xNext;
2163cdf0e10cSrcweir 			}
2164cdf0e10cSrcweir 		}
2165cdf0e10cSrcweir 	}
2166cdf0e10cSrcweir 	return xNext.is();
2167cdf0e10cSrcweir }
2168cdf0e10cSrcweir 
2169cdf0e10cSrcweir // --------------------------------------------------------------------
2170cdf0e10cSrcweir 
2171cdf0e10cSrcweir void stl_process_after_effect_node_func(AfterEffectNode& rNode)
2172cdf0e10cSrcweir {
2173cdf0e10cSrcweir 	try
2174cdf0e10cSrcweir 	{
2175cdf0e10cSrcweir 		if( rNode.mxNode.is() && rNode.mxMaster.is() )
2176cdf0e10cSrcweir 		{
2177cdf0e10cSrcweir 			// set master node
2178cdf0e10cSrcweir 			Reference< XAnimationNode > xMasterNode( rNode.mxMaster, UNO_QUERY_THROW );
2179cdf0e10cSrcweir 			Sequence< NamedValue > aUserData( rNode.mxNode->getUserData() );
2180cdf0e10cSrcweir 			sal_Int32 nSize = aUserData.getLength();
2181cdf0e10cSrcweir 			aUserData.realloc(nSize+1);
2182cdf0e10cSrcweir 			aUserData[nSize].Name = OUString( RTL_CONSTASCII_USTRINGPARAM( "master-element" ) );
2183cdf0e10cSrcweir 			aUserData[nSize].Value <<= xMasterNode;
2184cdf0e10cSrcweir 			rNode.mxNode->setUserData( aUserData );
2185cdf0e10cSrcweir 
2186cdf0e10cSrcweir 			// insert after effect node into timeline
2187cdf0e10cSrcweir 			Reference< XTimeContainer > xContainer( rNode.mxMaster->getParent(), UNO_QUERY_THROW );
2188cdf0e10cSrcweir 
2189cdf0e10cSrcweir 			if( !rNode.mbOnNextEffect ) // sameClick
2190cdf0e10cSrcweir 			{
2191cdf0e10cSrcweir 				// insert the aftereffect after its effect is animated
2192cdf0e10cSrcweir 				xContainer->insertAfter( rNode.mxNode, rNode.mxMaster );
2193cdf0e10cSrcweir 			}
2194cdf0e10cSrcweir 			else // nextClick
2195cdf0e10cSrcweir 			{
2196cdf0e10cSrcweir 				Reference< XMultiServiceFactory > xMsf( ::comphelper::getProcessServiceFactory() );
2197cdf0e10cSrcweir 				// insert the aftereffect in the next group
2198cdf0e10cSrcweir 
2199cdf0e10cSrcweir 				Reference< XTimeContainer > xClickContainer( xContainer->getParent(), UNO_QUERY_THROW );
2200cdf0e10cSrcweir 				Reference< XTimeContainer > xSequenceContainer( xClickContainer->getParent(), UNO_QUERY_THROW );
2201cdf0e10cSrcweir 
2202cdf0e10cSrcweir 				Reference< XTimeContainer > xNextContainer;
2203cdf0e10cSrcweir 
2204cdf0e10cSrcweir 				// first try if we have an after effect container
2205cdf0e10cSrcweir 				if( !implFindNextContainer( xClickContainer, xContainer, xNextContainer ) )
2206cdf0e10cSrcweir 				{
2207cdf0e10cSrcweir 					Reference< XTimeContainer > xNextClickContainer;
2208cdf0e10cSrcweir 					// if not, try to find the next click effect container
2209cdf0e10cSrcweir 					if( implFindNextContainer( xSequenceContainer, xClickContainer, xNextClickContainer ) )
2210cdf0e10cSrcweir 					{
2211cdf0e10cSrcweir 						Reference< XEnumerationAccess > xEnumerationAccess( xNextClickContainer, UNO_QUERY_THROW );
2212cdf0e10cSrcweir 						Reference< XEnumeration > xEnumeration( xEnumerationAccess->createEnumeration(), UNO_QUERY_THROW );
2213cdf0e10cSrcweir 						if( xEnumeration->hasMoreElements() )
2214cdf0e10cSrcweir 						{
2215cdf0e10cSrcweir 							// the next container is the first child container
2216cdf0e10cSrcweir 							xEnumeration->nextElement() >>= xNextContainer;
2217cdf0e10cSrcweir 						}
2218cdf0e10cSrcweir 						else
2219cdf0e10cSrcweir 						{
2220cdf0e10cSrcweir 							// this does not yet have a child container, create one
2221cdf0e10cSrcweir 							const OUString aServiceName( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.animations.ParallelTimeContainer") );
2222cdf0e10cSrcweir 							xNextContainer = Reference< XTimeContainer >::query( xMsf->createInstance(aServiceName) );
2223cdf0e10cSrcweir 
2224cdf0e10cSrcweir 							if( xNextContainer.is() )
2225cdf0e10cSrcweir 							{
2226cdf0e10cSrcweir 								Reference< XAnimationNode > xNode( xNextContainer, UNO_QUERY_THROW );
2227cdf0e10cSrcweir 								xNode->setBegin( makeAny( (double)0.0 ) );
2228cdf0e10cSrcweir //								xNode->setFill( AnimationFill::HOLD );
2229cdf0e10cSrcweir 								xNextClickContainer->appendChild( xNode );
2230cdf0e10cSrcweir 							}
2231cdf0e10cSrcweir 						}
2232cdf0e10cSrcweir 						DBG_ASSERT( xNextContainer.is(), "ppt::stl_process_after_effect_node_func::operator(), could not find/create container!" );
2233cdf0e10cSrcweir 					}
2234cdf0e10cSrcweir 				}
2235cdf0e10cSrcweir 
2236cdf0e10cSrcweir 				// if we don't have a next container, we add one to the sequence container
2237cdf0e10cSrcweir 				if( !xNextContainer.is() )
2238cdf0e10cSrcweir 				{
2239cdf0e10cSrcweir 					const OUString aServiceName( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.animations.ParallelTimeContainer") );
2240cdf0e10cSrcweir 					Reference< XTimeContainer > xNewClickContainer( xMsf->createInstance(aServiceName), UNO_QUERY_THROW );
2241cdf0e10cSrcweir 
2242cdf0e10cSrcweir 					Reference< XAnimationNode > xNewClickNode( xNewClickContainer, UNO_QUERY_THROW );
2243cdf0e10cSrcweir 
2244cdf0e10cSrcweir                     Event aEvent;
2245cdf0e10cSrcweir                     aEvent.Trigger = EventTrigger::ON_NEXT;
2246cdf0e10cSrcweir                     aEvent.Repeat = 0;
2247cdf0e10cSrcweir 					xNewClickNode->setBegin( makeAny( aEvent ) );
2248cdf0e10cSrcweir 
2249cdf0e10cSrcweir 					Reference< XAnimationNode > xRefNode( xClickContainer, UNO_QUERY_THROW );
2250cdf0e10cSrcweir 					xSequenceContainer->insertAfter( xNewClickNode, xRefNode );
2251cdf0e10cSrcweir 
2252cdf0e10cSrcweir 					xNextContainer = Reference< XTimeContainer >::query( xMsf->createInstance(aServiceName) );
2253cdf0e10cSrcweir 
2254cdf0e10cSrcweir 					DBG_ASSERT( xNextContainer.is(), "ppt::stl_process_after_effect_node_func::operator(), could not create container!" );
2255cdf0e10cSrcweir 					if( xNextContainer.is() )
2256cdf0e10cSrcweir 					{
2257cdf0e10cSrcweir 						Reference< XAnimationNode > xNode( xNextContainer, UNO_QUERY_THROW );
2258cdf0e10cSrcweir 						xNode->setBegin( makeAny( (double)0.0 ) );
2259cdf0e10cSrcweir //						xNode->setFill( AnimationFill::HOLD );
2260cdf0e10cSrcweir 						xNewClickContainer->appendChild( xNode );
2261cdf0e10cSrcweir 					}
2262cdf0e10cSrcweir 				}
2263cdf0e10cSrcweir 
2264cdf0e10cSrcweir 				if( xNextContainer.is() )
2265cdf0e10cSrcweir 				{
2266cdf0e10cSrcweir 					// find begin time of first element
2267cdf0e10cSrcweir 					Reference< XEnumerationAccess > xEnumerationAccess( xNextContainer, UNO_QUERY_THROW );
2268cdf0e10cSrcweir 					Reference< XEnumeration > xEnumeration( xEnumerationAccess->createEnumeration(), UNO_QUERY_THROW );
2269cdf0e10cSrcweir 					if( xEnumeration->hasMoreElements() )
2270cdf0e10cSrcweir 					{
2271cdf0e10cSrcweir 						Reference< XAnimationNode > xChild;
2272cdf0e10cSrcweir 						// the next container is the first child container
2273cdf0e10cSrcweir 						xEnumeration->nextElement() >>= xChild;
2274cdf0e10cSrcweir 						if( xChild.is() )
2275cdf0e10cSrcweir 						{
2276cdf0e10cSrcweir 							Any aBegin( xChild->getBegin() );
2277cdf0e10cSrcweir 							double fBegin = 0.0;
2278cdf0e10cSrcweir 							if( (aBegin >>= fBegin) && (fBegin >= 0.0))
2279cdf0e10cSrcweir 								rNode.mxNode->setBegin( aBegin );
2280cdf0e10cSrcweir 						}
2281cdf0e10cSrcweir 					}
2282cdf0e10cSrcweir 
2283cdf0e10cSrcweir 					xNextContainer->appendChild( rNode.mxNode );
2284cdf0e10cSrcweir 				}
2285cdf0e10cSrcweir 			}
2286cdf0e10cSrcweir 		}
2287cdf0e10cSrcweir 	}
2288cdf0e10cSrcweir 	catch( Exception& e )
2289cdf0e10cSrcweir 	{
2290cdf0e10cSrcweir 		(void)e;
2291cdf0e10cSrcweir 		DBG_ERROR( "ppt::stl_process_after_effect_node_func::operator(), exception cought!" );
2292cdf0e10cSrcweir 	}
2293cdf0e10cSrcweir }
2294cdf0e10cSrcweir 
2295cdf0e10cSrcweir // --------------------------------------------------------------------
2296cdf0e10cSrcweir 
2297cdf0e10cSrcweir EffectSequence::iterator EffectSequenceHelper::find( const CustomAnimationEffectPtr& pEffect )
2298cdf0e10cSrcweir {
2299cdf0e10cSrcweir 	return std::find( maEffects.begin(), maEffects.end(), pEffect );
2300cdf0e10cSrcweir }
2301cdf0e10cSrcweir 
2302cdf0e10cSrcweir // --------------------------------------------------------------------
2303cdf0e10cSrcweir 
2304cdf0e10cSrcweir CustomAnimationEffectPtr EffectSequenceHelper::findEffect( const ::com::sun::star::uno::Reference< ::com::sun::star::animations::XAnimationNode >& xNode ) const
2305cdf0e10cSrcweir {
2306cdf0e10cSrcweir 	CustomAnimationEffectPtr pEffect;
2307cdf0e10cSrcweir 
2308cdf0e10cSrcweir 	EffectSequence::const_iterator aIter( maEffects.begin() );
2309cdf0e10cSrcweir 	for( ; aIter != maEffects.end(); aIter++ )
2310cdf0e10cSrcweir 	{
2311cdf0e10cSrcweir 		if( (*aIter)->getNode() == xNode )
2312cdf0e10cSrcweir 		{
2313cdf0e10cSrcweir 			pEffect = (*aIter);
2314cdf0e10cSrcweir 			break;
2315cdf0e10cSrcweir 		}
2316cdf0e10cSrcweir 	}
2317cdf0e10cSrcweir 
2318cdf0e10cSrcweir 	return pEffect;
2319cdf0e10cSrcweir }
2320cdf0e10cSrcweir 
2321cdf0e10cSrcweir // --------------------------------------------------------------------
2322cdf0e10cSrcweir 
2323cdf0e10cSrcweir sal_Int32 EffectSequenceHelper::getOffsetFromEffect( const CustomAnimationEffectPtr& xEffect ) const
2324cdf0e10cSrcweir {
2325cdf0e10cSrcweir 	sal_Int32 nOffset = 0;
2326cdf0e10cSrcweir 
2327cdf0e10cSrcweir 	EffectSequence::const_iterator aIter( maEffects.begin() );
2328cdf0e10cSrcweir 	for( ; aIter != maEffects.end(); aIter++, nOffset++ )
2329cdf0e10cSrcweir 	{
2330cdf0e10cSrcweir 		if( (*aIter) == xEffect )
2331cdf0e10cSrcweir 			return nOffset;
2332cdf0e10cSrcweir 	}
2333cdf0e10cSrcweir 
2334cdf0e10cSrcweir 	return -1;
2335cdf0e10cSrcweir }
2336cdf0e10cSrcweir 
2337cdf0e10cSrcweir // --------------------------------------------------------------------
2338cdf0e10cSrcweir 
2339cdf0e10cSrcweir CustomAnimationEffectPtr EffectSequenceHelper::getEffectFromOffset( sal_Int32 nOffset ) const
2340cdf0e10cSrcweir {
2341cdf0e10cSrcweir 	EffectSequence::const_iterator aIter( maEffects.begin() );
2342cdf0e10cSrcweir 	while( nOffset-- && aIter != maEffects.end() )
2343cdf0e10cSrcweir 		aIter++;
2344cdf0e10cSrcweir 
2345cdf0e10cSrcweir 	CustomAnimationEffectPtr pEffect;
2346cdf0e10cSrcweir 	if( aIter != maEffects.end() )
2347cdf0e10cSrcweir 		pEffect = (*aIter);
2348cdf0e10cSrcweir 
2349cdf0e10cSrcweir 	return pEffect;
2350cdf0e10cSrcweir }
2351cdf0e10cSrcweir 
2352cdf0e10cSrcweir // --------------------------------------------------------------------
2353cdf0e10cSrcweir 
2354cdf0e10cSrcweir bool EffectSequenceHelper::disposeShape( const Reference< XShape >& xShape )
2355cdf0e10cSrcweir {
2356cdf0e10cSrcweir 	bool bChanges = false;
2357cdf0e10cSrcweir 
2358cdf0e10cSrcweir 	EffectSequence::iterator aIter( maEffects.begin() );
2359cdf0e10cSrcweir 	while( aIter != maEffects.end() )
2360cdf0e10cSrcweir 	{
2361cdf0e10cSrcweir 		if( (*aIter)->getTargetShape() == xShape )
2362cdf0e10cSrcweir 		{
2363cdf0e10cSrcweir 			(*aIter)->setEffectSequence( 0 );
2364cdf0e10cSrcweir 			bChanges = true;
2365cdf0e10cSrcweir 			aIter = maEffects.erase( aIter );
2366cdf0e10cSrcweir 		}
2367cdf0e10cSrcweir 		else
2368cdf0e10cSrcweir 		{
2369cdf0e10cSrcweir 			aIter++;
2370cdf0e10cSrcweir 		}
2371cdf0e10cSrcweir 	}
2372cdf0e10cSrcweir 
2373cdf0e10cSrcweir 	return bChanges;
2374cdf0e10cSrcweir }
2375cdf0e10cSrcweir 
2376cdf0e10cSrcweir // --------------------------------------------------------------------
2377cdf0e10cSrcweir 
2378cdf0e10cSrcweir bool EffectSequenceHelper::hasEffect( const com::sun::star::uno::Reference< com::sun::star::drawing::XShape >& xShape )
2379cdf0e10cSrcweir {
2380cdf0e10cSrcweir 	EffectSequence::iterator aIter( maEffects.begin() );
2381cdf0e10cSrcweir 	while( aIter != maEffects.end() )
2382cdf0e10cSrcweir 	{
2383cdf0e10cSrcweir 		if( (*aIter)->getTargetShape() == xShape )
2384cdf0e10cSrcweir 			return true;
2385cdf0e10cSrcweir 		aIter++;
2386cdf0e10cSrcweir 	}
2387cdf0e10cSrcweir 
2388cdf0e10cSrcweir 	return false;
2389cdf0e10cSrcweir }
2390cdf0e10cSrcweir 
2391cdf0e10cSrcweir // --------------------------------------------------------------------
2392cdf0e10cSrcweir 
2393cdf0e10cSrcweir void EffectSequenceHelper::insertTextRange( const com::sun::star::uno::Any& aTarget )
2394cdf0e10cSrcweir {
2395cdf0e10cSrcweir 	bool bChanges = false;
2396cdf0e10cSrcweir 
2397cdf0e10cSrcweir 	ParagraphTarget aParaTarget;
2398cdf0e10cSrcweir 	if( !(aTarget >>= aParaTarget ) )
2399cdf0e10cSrcweir 		return;
2400cdf0e10cSrcweir 
2401cdf0e10cSrcweir 	EffectSequence::iterator aIter( maEffects.begin() );
2402cdf0e10cSrcweir 	while( aIter != maEffects.end() )
2403cdf0e10cSrcweir 	{
2404cdf0e10cSrcweir 		if( (*aIter)->getTargetShape() == aParaTarget.Shape )
2405cdf0e10cSrcweir 			bChanges |= (*aIter)->checkForText();
2406cdf0e10cSrcweir 		aIter++;
2407cdf0e10cSrcweir 	}
2408cdf0e10cSrcweir 
2409cdf0e10cSrcweir 	if( bChanges )
2410cdf0e10cSrcweir 		rebuild();
2411cdf0e10cSrcweir }
2412cdf0e10cSrcweir 
2413cdf0e10cSrcweir // --------------------------------------------------------------------
2414cdf0e10cSrcweir 
2415cdf0e10cSrcweir void EffectSequenceHelper::disposeTextRange( const com::sun::star::uno::Any& aTarget )
2416cdf0e10cSrcweir {
2417cdf0e10cSrcweir 	ParagraphTarget aParaTarget;
2418cdf0e10cSrcweir 	if( !(aTarget >>= aParaTarget ) )
2419cdf0e10cSrcweir 		return;
2420cdf0e10cSrcweir 
2421cdf0e10cSrcweir 	bool bChanges = false;
2422cdf0e10cSrcweir 	bool bErased = false;
2423cdf0e10cSrcweir 
2424cdf0e10cSrcweir 	EffectSequence::iterator aIter( maEffects.begin() );
2425cdf0e10cSrcweir 	while( aIter != maEffects.end() )
2426cdf0e10cSrcweir 	{
2427cdf0e10cSrcweir 		Any aIterTarget( (*aIter)->getTarget() );
2428cdf0e10cSrcweir 		if( aIterTarget.getValueType() == ::getCppuType((const ParagraphTarget*)0) )
2429cdf0e10cSrcweir 		{
2430cdf0e10cSrcweir 			ParagraphTarget aIterParaTarget;
2431cdf0e10cSrcweir 			if( (aIterTarget >>= aIterParaTarget) && (aIterParaTarget.Shape == aParaTarget.Shape) )
2432cdf0e10cSrcweir 			{
2433cdf0e10cSrcweir 				if( aIterParaTarget.Paragraph == aParaTarget.Paragraph )
2434cdf0e10cSrcweir 				{
2435cdf0e10cSrcweir 					// delete this effect if it targets the disposed paragraph directly
2436cdf0e10cSrcweir 					(*aIter)->setEffectSequence( 0 );
2437cdf0e10cSrcweir 					aIter = maEffects.erase( aIter );
2438cdf0e10cSrcweir 					bChanges = true;
2439cdf0e10cSrcweir 					bErased = true;
2440cdf0e10cSrcweir 				}
2441cdf0e10cSrcweir 				else
2442cdf0e10cSrcweir 				{
2443cdf0e10cSrcweir 					if( aIterParaTarget.Paragraph > aParaTarget.Paragraph )
2444cdf0e10cSrcweir 					{
2445cdf0e10cSrcweir 						// shift all paragraphs after disposed paragraph
2446cdf0e10cSrcweir 						aIterParaTarget.Paragraph--;
2447cdf0e10cSrcweir 						(*aIter)->setTarget( makeAny( aIterParaTarget ) );
2448cdf0e10cSrcweir 					}
2449cdf0e10cSrcweir 				}
2450cdf0e10cSrcweir 			}
2451cdf0e10cSrcweir 		}
2452cdf0e10cSrcweir 		else if( (*aIter)->getTargetShape() == aParaTarget.Shape )
2453cdf0e10cSrcweir 		{
2454cdf0e10cSrcweir 			bChanges |= (*aIter)->checkForText();
2455cdf0e10cSrcweir 		}
2456cdf0e10cSrcweir 
2457cdf0e10cSrcweir 		if( bErased )
2458cdf0e10cSrcweir 			bErased = false;
2459cdf0e10cSrcweir 		else
2460cdf0e10cSrcweir 			aIter++;
2461cdf0e10cSrcweir 	}
2462cdf0e10cSrcweir 
2463cdf0e10cSrcweir 	if( bChanges )
2464cdf0e10cSrcweir 		rebuild();
2465cdf0e10cSrcweir }
2466cdf0e10cSrcweir 
2467cdf0e10cSrcweir // --------------------------------------------------------------------
2468cdf0e10cSrcweir 
2469cdf0e10cSrcweir CustomAnimationTextGroup::CustomAnimationTextGroup( const Reference< XShape >& rTarget, sal_Int32 nGroupId )
2470cdf0e10cSrcweir :	maTarget( rTarget ),
2471cdf0e10cSrcweir 	mnGroupId( nGroupId )
2472cdf0e10cSrcweir {
2473cdf0e10cSrcweir 	reset();
2474cdf0e10cSrcweir }
2475cdf0e10cSrcweir 
2476cdf0e10cSrcweir // --------------------------------------------------------------------
2477cdf0e10cSrcweir 
2478cdf0e10cSrcweir void CustomAnimationTextGroup::reset()
2479cdf0e10cSrcweir {
2480cdf0e10cSrcweir 	mnTextGrouping = -1;
2481cdf0e10cSrcweir 	mbAnimateForm = false;
2482cdf0e10cSrcweir 	mbTextReverse = false;
2483cdf0e10cSrcweir 	mfGroupingAuto = -1.0;
2484cdf0e10cSrcweir 	mnLastPara = -1; // used to check for TextReverse
2485cdf0e10cSrcweir 
2486cdf0e10cSrcweir 	int i = 5;
2487cdf0e10cSrcweir 	while( i-- ) mnDepthFlags[i] = 0;
2488cdf0e10cSrcweir 
2489cdf0e10cSrcweir 	maEffects.clear();
2490cdf0e10cSrcweir }
2491cdf0e10cSrcweir 
2492cdf0e10cSrcweir // --------------------------------------------------------------------
2493cdf0e10cSrcweir 
2494cdf0e10cSrcweir void CustomAnimationTextGroup::addEffect( CustomAnimationEffectPtr& pEffect )
2495cdf0e10cSrcweir {
2496cdf0e10cSrcweir 	maEffects.push_back( pEffect );
2497cdf0e10cSrcweir 
2498cdf0e10cSrcweir 	Any aTarget( pEffect->getTarget() );
2499cdf0e10cSrcweir 	if( aTarget.getValueType() == ::getCppuType((const ParagraphTarget*)0) )
2500cdf0e10cSrcweir 	{
2501cdf0e10cSrcweir 		// now look at the paragraph
2502cdf0e10cSrcweir 		ParagraphTarget aParaTarget;
2503cdf0e10cSrcweir 		aTarget >>= aParaTarget;
2504cdf0e10cSrcweir 
2505cdf0e10cSrcweir 		if( mnLastPara != -1 )
2506cdf0e10cSrcweir 			mbTextReverse = mnLastPara > aParaTarget.Paragraph;
2507cdf0e10cSrcweir 
2508cdf0e10cSrcweir 		mnLastPara = aParaTarget.Paragraph;
2509cdf0e10cSrcweir 
2510cdf0e10cSrcweir 		const sal_Int32 nParaDepth = pEffect->getParaDepth();
2511cdf0e10cSrcweir 
2512cdf0e10cSrcweir 		// only look at the first 5 levels
2513cdf0e10cSrcweir 		if( nParaDepth < 5 )
2514cdf0e10cSrcweir 		{
2515cdf0e10cSrcweir 			// our first paragraph with this level?
2516cdf0e10cSrcweir 			if( mnDepthFlags[nParaDepth] == 0 )
2517cdf0e10cSrcweir 			{
2518cdf0e10cSrcweir 				// so set it to the first found
2519cdf0e10cSrcweir 				mnDepthFlags[nParaDepth] = (sal_Int8)pEffect->getNodeType();
2520cdf0e10cSrcweir 			}
2521cdf0e10cSrcweir 			else if( mnDepthFlags[nParaDepth] != pEffect->getNodeType() )
2522cdf0e10cSrcweir 			{
2523cdf0e10cSrcweir 				mnDepthFlags[nParaDepth] = -1;
2524cdf0e10cSrcweir 			}
2525cdf0e10cSrcweir 
2526cdf0e10cSrcweir 			if( pEffect->getNodeType() == EffectNodeType::AFTER_PREVIOUS )
2527cdf0e10cSrcweir 				mfGroupingAuto = pEffect->getBegin();
2528cdf0e10cSrcweir 
2529cdf0e10cSrcweir 			mnTextGrouping = 0;
2530cdf0e10cSrcweir 			while( (mnTextGrouping < 5) && (mnDepthFlags[mnTextGrouping] > 0) )
2531cdf0e10cSrcweir 				mnTextGrouping++;
2532cdf0e10cSrcweir 		}
2533cdf0e10cSrcweir 	}
2534cdf0e10cSrcweir 	else
2535cdf0e10cSrcweir 	{
2536cdf0e10cSrcweir 		// if we have an effect with the shape as a target, we animate the background
2537cdf0e10cSrcweir 		mbAnimateForm = pEffect->getTargetSubItem() != ShapeAnimationSubType::ONLY_TEXT;
2538cdf0e10cSrcweir 	}
2539cdf0e10cSrcweir }
2540cdf0e10cSrcweir 
2541cdf0e10cSrcweir // --------------------------------------------------------------------
2542cdf0e10cSrcweir 
2543cdf0e10cSrcweir class TextGroupMapImpl : public std::map< sal_Int32, CustomAnimationTextGroup* >
2544cdf0e10cSrcweir {
2545cdf0e10cSrcweir public:
2546cdf0e10cSrcweir 	CustomAnimationTextGroup* findGroup( sal_Int32 nGroupId );
2547cdf0e10cSrcweir };
2548cdf0e10cSrcweir 
2549cdf0e10cSrcweir // --------------------------------------------------------------------
2550cdf0e10cSrcweir 
2551cdf0e10cSrcweir CustomAnimationTextGroupPtr EffectSequenceHelper::findGroup( sal_Int32 nGroupId )
2552cdf0e10cSrcweir {
2553cdf0e10cSrcweir 	CustomAnimationTextGroupPtr aPtr;
2554cdf0e10cSrcweir 
2555cdf0e10cSrcweir 	CustomAnimationTextGroupMap::iterator aIter( maGroupMap.find( nGroupId ) );
2556cdf0e10cSrcweir 	if( aIter != maGroupMap.end() )
2557cdf0e10cSrcweir 		aPtr = (*aIter).second;
2558cdf0e10cSrcweir 
2559cdf0e10cSrcweir 	return aPtr;
2560cdf0e10cSrcweir }
2561cdf0e10cSrcweir 
2562cdf0e10cSrcweir // --------------------------------------------------------------------
2563cdf0e10cSrcweir 
2564cdf0e10cSrcweir void EffectSequenceHelper::updateTextGroups()
2565cdf0e10cSrcweir {
2566cdf0e10cSrcweir 	maGroupMap.clear();
2567cdf0e10cSrcweir 
2568cdf0e10cSrcweir 	// first create all the groups
2569cdf0e10cSrcweir 	EffectSequence::iterator aIter( maEffects.begin() );
2570cdf0e10cSrcweir 	const EffectSequence::iterator aEnd( maEffects.end() );
2571cdf0e10cSrcweir 	while( aIter != aEnd )
2572cdf0e10cSrcweir 	{
2573cdf0e10cSrcweir 		CustomAnimationEffectPtr pEffect( (*aIter++) );
2574cdf0e10cSrcweir 
2575cdf0e10cSrcweir 		const sal_Int32 nGroupId = pEffect->getGroupId();
2576cdf0e10cSrcweir 
2577cdf0e10cSrcweir 		if( nGroupId == -1 )
2578cdf0e10cSrcweir 			continue; // trivial case, no group
2579cdf0e10cSrcweir 
2580cdf0e10cSrcweir 		CustomAnimationTextGroupPtr pGroup = findGroup( nGroupId );
2581cdf0e10cSrcweir 		if( !pGroup.get() )
2582cdf0e10cSrcweir 		{
2583cdf0e10cSrcweir 			pGroup.reset( new CustomAnimationTextGroup( pEffect->getTargetShape(), nGroupId ) );
2584cdf0e10cSrcweir 			maGroupMap[nGroupId] = pGroup;
2585cdf0e10cSrcweir 		}
2586cdf0e10cSrcweir 
2587cdf0e10cSrcweir 		pGroup->addEffect( pEffect );
2588cdf0e10cSrcweir 	}
2589cdf0e10cSrcweir }
2590cdf0e10cSrcweir 
2591cdf0e10cSrcweir // --------------------------------------------------------------------
2592cdf0e10cSrcweir 
2593cdf0e10cSrcweir CustomAnimationTextGroupPtr	EffectSequenceHelper::createTextGroup( CustomAnimationEffectPtr pEffect, sal_Int32 nTextGrouping, double fTextGroupingAuto, sal_Bool bAnimateForm, sal_Bool bTextReverse )
2594cdf0e10cSrcweir {
2595cdf0e10cSrcweir 	// first finde a free group-id
2596cdf0e10cSrcweir 	sal_Int32 nGroupId = 0;
2597cdf0e10cSrcweir 
2598cdf0e10cSrcweir 	CustomAnimationTextGroupMap::iterator aIter( maGroupMap.begin() );
2599cdf0e10cSrcweir 	const CustomAnimationTextGroupMap::iterator aEnd( maGroupMap.end() );
2600cdf0e10cSrcweir 	while( aIter != aEnd )
2601cdf0e10cSrcweir 	{
2602cdf0e10cSrcweir 		if( (*aIter).first == nGroupId )
2603cdf0e10cSrcweir 		{
2604cdf0e10cSrcweir 			nGroupId++;
2605cdf0e10cSrcweir 			aIter = maGroupMap.begin();
2606cdf0e10cSrcweir 		}
2607cdf0e10cSrcweir 		else
2608cdf0e10cSrcweir 		{
2609cdf0e10cSrcweir 			aIter++;
2610cdf0e10cSrcweir 		}
2611cdf0e10cSrcweir 	}
2612cdf0e10cSrcweir 
2613cdf0e10cSrcweir 	Reference< XShape > xTarget( pEffect->getTargetShape() );
2614cdf0e10cSrcweir 
2615cdf0e10cSrcweir 	CustomAnimationTextGroupPtr	pTextGroup( new CustomAnimationTextGroup( xTarget, nGroupId ) );
2616cdf0e10cSrcweir 	maGroupMap[nGroupId] = pTextGroup;
2617cdf0e10cSrcweir 
2618cdf0e10cSrcweir 	bool bUsed = false;
2619cdf0e10cSrcweir 
2620cdf0e10cSrcweir 	// do we need to target the shape?
2621cdf0e10cSrcweir 	if( (nTextGrouping == 0) || bAnimateForm )
2622cdf0e10cSrcweir 	{
2623cdf0e10cSrcweir 		sal_Int16 nSubItem;
2624cdf0e10cSrcweir 		if( nTextGrouping == 0)
2625cdf0e10cSrcweir 			nSubItem = bAnimateForm ? ShapeAnimationSubType::AS_WHOLE : ShapeAnimationSubType::ONLY_TEXT;
2626cdf0e10cSrcweir 		else
2627cdf0e10cSrcweir 			nSubItem = ShapeAnimationSubType::ONLY_BACKGROUND;
2628cdf0e10cSrcweir 
2629cdf0e10cSrcweir 		pEffect->setTarget( makeAny( xTarget ) );
2630cdf0e10cSrcweir 		pEffect->setTargetSubItem( nSubItem );
2631cdf0e10cSrcweir 		pEffect->setEffectSequence( this );
2632cdf0e10cSrcweir 		pEffect->setGroupId( nGroupId );
2633cdf0e10cSrcweir 
2634cdf0e10cSrcweir 		pTextGroup->addEffect( pEffect );
2635cdf0e10cSrcweir 		bUsed = true;
2636cdf0e10cSrcweir 	}
2637cdf0e10cSrcweir 
2638cdf0e10cSrcweir 	pTextGroup->mnTextGrouping = nTextGrouping;
2639cdf0e10cSrcweir 	pTextGroup->mfGroupingAuto = fTextGroupingAuto;
2640cdf0e10cSrcweir 	pTextGroup->mbTextReverse = bTextReverse;
2641cdf0e10cSrcweir 
2642cdf0e10cSrcweir 	// now add an effect for each paragraph
2643cdf0e10cSrcweir 	createTextGroupParagraphEffects( pTextGroup, pEffect, bUsed );
2644cdf0e10cSrcweir 
2645cdf0e10cSrcweir 	notify_listeners();
2646cdf0e10cSrcweir 
2647cdf0e10cSrcweir 	return pTextGroup;
2648cdf0e10cSrcweir }
2649cdf0e10cSrcweir 
2650cdf0e10cSrcweir // --------------------------------------------------------------------
2651cdf0e10cSrcweir 
2652cdf0e10cSrcweir void EffectSequenceHelper::createTextGroupParagraphEffects( CustomAnimationTextGroupPtr pTextGroup, CustomAnimationEffectPtr pEffect, bool bUsed )
2653cdf0e10cSrcweir {
2654cdf0e10cSrcweir 	Reference< XShape > xTarget( pTextGroup->maTarget );
2655cdf0e10cSrcweir 
2656cdf0e10cSrcweir 	sal_Int32 nTextGrouping = pTextGroup->mnTextGrouping;
2657cdf0e10cSrcweir 	double fTextGroupingAuto = pTextGroup->mfGroupingAuto;
2658cdf0e10cSrcweir 	sal_Bool bTextReverse = pTextGroup->mbTextReverse;
2659cdf0e10cSrcweir 
2660cdf0e10cSrcweir 	// now add an effect for each paragraph
2661cdf0e10cSrcweir 	if( nTextGrouping >= 0 ) try
2662cdf0e10cSrcweir 	{
2663cdf0e10cSrcweir 		EffectSequence::iterator aInsertIter( find( pEffect ) );
2664cdf0e10cSrcweir 
2665cdf0e10cSrcweir 		const OUString strNumberingLevel( RTL_CONSTASCII_USTRINGPARAM("NumberingLevel") );
2666cdf0e10cSrcweir 		Reference< XEnumerationAccess > xText( xTarget, UNO_QUERY_THROW );
2667cdf0e10cSrcweir 		Reference< XEnumeration > xEnumeration( xText->createEnumeration(), UNO_QUERY_THROW );
2668cdf0e10cSrcweir 
2669cdf0e10cSrcweir 		std::list< sal_Int16 > aParaList;
2670cdf0e10cSrcweir 		sal_Int16 nPara;
2671cdf0e10cSrcweir 
2672cdf0e10cSrcweir 		// fill the list with all valid paragraphs
2673cdf0e10cSrcweir 		for( nPara = 0; xEnumeration->hasMoreElements(); nPara++ )
2674cdf0e10cSrcweir 		{
2675cdf0e10cSrcweir 			Reference< XTextRange > xRange( xEnumeration->nextElement(), UNO_QUERY );
2676cdf0e10cSrcweir 			if( xRange.is() && xRange->getString().getLength() )
2677cdf0e10cSrcweir 			{
2678cdf0e10cSrcweir 				if( bTextReverse ) // sort them
2679cdf0e10cSrcweir 					aParaList.push_front( nPara );
2680cdf0e10cSrcweir 				else
2681cdf0e10cSrcweir 					aParaList.push_back( nPara );
2682cdf0e10cSrcweir 			}
2683cdf0e10cSrcweir 		}
2684cdf0e10cSrcweir 
2685cdf0e10cSrcweir 		ParagraphTarget aTarget;
2686cdf0e10cSrcweir 		aTarget.Shape = xTarget;
2687cdf0e10cSrcweir 
2688cdf0e10cSrcweir 		std::list< sal_Int16 >::iterator aIter( aParaList.begin() );
2689cdf0e10cSrcweir 		std::list< sal_Int16 >::iterator aEnd( aParaList.end() );
2690cdf0e10cSrcweir 		while( aIter != aEnd )
2691cdf0e10cSrcweir 		{
2692cdf0e10cSrcweir 			aTarget.Paragraph = (*aIter++);
2693cdf0e10cSrcweir 
2694cdf0e10cSrcweir 			CustomAnimationEffectPtr pNewEffect;
2695cdf0e10cSrcweir 			if( bUsed )
2696cdf0e10cSrcweir 			{
2697cdf0e10cSrcweir 				// clone a new effect from first effect
2698cdf0e10cSrcweir 				pNewEffect = pEffect->clone();
2699cdf0e10cSrcweir 				++aInsertIter;
2700cdf0e10cSrcweir 				aInsertIter = maEffects.insert( aInsertIter, pNewEffect );
2701cdf0e10cSrcweir 			}
2702cdf0e10cSrcweir 			else
2703cdf0e10cSrcweir 			{
2704cdf0e10cSrcweir 				// reuse first effect if its not yet used
2705cdf0e10cSrcweir 				pNewEffect = pEffect;
2706cdf0e10cSrcweir 				bUsed = true;
2707cdf0e10cSrcweir 				aInsertIter = find( pNewEffect );
2708cdf0e10cSrcweir 			}
2709cdf0e10cSrcweir 
2710cdf0e10cSrcweir 			// set target and group-id
2711cdf0e10cSrcweir 			pNewEffect->setTarget( makeAny( aTarget ) );
2712cdf0e10cSrcweir 			pNewEffect->setTargetSubItem( ShapeAnimationSubType::ONLY_TEXT );
2713cdf0e10cSrcweir 			pNewEffect->setGroupId( pTextGroup->mnGroupId );
2714cdf0e10cSrcweir 			pNewEffect->setEffectSequence( this );
2715cdf0e10cSrcweir 
2716cdf0e10cSrcweir 			// set correct node type
2717cdf0e10cSrcweir 			if( pNewEffect->getParaDepth() < nTextGrouping )
2718cdf0e10cSrcweir 			{
2719cdf0e10cSrcweir 				if( fTextGroupingAuto == -1.0 )
2720cdf0e10cSrcweir 				{
2721cdf0e10cSrcweir 					pNewEffect->setNodeType( EffectNodeType::ON_CLICK );
2722cdf0e10cSrcweir 					pNewEffect->setBegin( 0.0 );
2723cdf0e10cSrcweir 				}
2724cdf0e10cSrcweir 				else
2725cdf0e10cSrcweir 				{
2726cdf0e10cSrcweir 					pNewEffect->setNodeType( EffectNodeType::AFTER_PREVIOUS );
2727cdf0e10cSrcweir 					pNewEffect->setBegin( fTextGroupingAuto );
2728cdf0e10cSrcweir 				}
2729cdf0e10cSrcweir 			}
2730cdf0e10cSrcweir 			else
2731cdf0e10cSrcweir 			{
2732cdf0e10cSrcweir 				pNewEffect->setNodeType( EffectNodeType::WITH_PREVIOUS );
2733cdf0e10cSrcweir 				pNewEffect->setBegin( 0.0 );
2734cdf0e10cSrcweir 			}
2735cdf0e10cSrcweir 
2736cdf0e10cSrcweir 			pTextGroup->addEffect( pNewEffect );
2737cdf0e10cSrcweir 		}
2738cdf0e10cSrcweir 		notify_listeners();
2739cdf0e10cSrcweir 	}
2740cdf0e10cSrcweir 	catch( Exception& e )
2741cdf0e10cSrcweir 	{
2742cdf0e10cSrcweir 		(void)e;
2743cdf0e10cSrcweir 		DBG_ERROR("sd::EffectSequenceHelper::createTextGroup(), exception cought!" );
2744cdf0e10cSrcweir 	}
2745cdf0e10cSrcweir }
2746cdf0e10cSrcweir 
2747cdf0e10cSrcweir // --------------------------------------------------------------------
2748cdf0e10cSrcweir 
2749cdf0e10cSrcweir void EffectSequenceHelper::setTextGrouping( CustomAnimationTextGroupPtr pTextGroup, sal_Int32 nTextGrouping )
2750cdf0e10cSrcweir {
2751cdf0e10cSrcweir 	if( pTextGroup->mnTextGrouping == nTextGrouping )
2752cdf0e10cSrcweir 	{
2753cdf0e10cSrcweir 		// first case, trivial case, do nothing
2754cdf0e10cSrcweir 	}
2755cdf0e10cSrcweir 	else if( (pTextGroup->mnTextGrouping == -1) && (nTextGrouping >= 0) )
2756cdf0e10cSrcweir 	{
2757cdf0e10cSrcweir 		// second case, we need to add new effects for each paragraph
2758cdf0e10cSrcweir 
2759cdf0e10cSrcweir 		CustomAnimationEffectPtr pEffect( pTextGroup->maEffects.front() );
2760cdf0e10cSrcweir 
2761cdf0e10cSrcweir 		pTextGroup->mnTextGrouping = nTextGrouping;
2762cdf0e10cSrcweir 		createTextGroupParagraphEffects( pTextGroup, pEffect, true );
2763cdf0e10cSrcweir 		notify_listeners();
2764cdf0e10cSrcweir 	}
2765cdf0e10cSrcweir 	else if( (pTextGroup->mnTextGrouping >= 0) && (nTextGrouping == -1 ) )
2766cdf0e10cSrcweir 	{
2767cdf0e10cSrcweir 		// third case, we need to remove effects for each paragraph
2768cdf0e10cSrcweir 
2769cdf0e10cSrcweir 		EffectSequence aEffects( pTextGroup->maEffects );
2770cdf0e10cSrcweir 		pTextGroup->reset();
2771cdf0e10cSrcweir 
2772cdf0e10cSrcweir 		EffectSequence::iterator aIter( aEffects.begin() );
2773cdf0e10cSrcweir 		const EffectSequence::iterator aEnd( aEffects.end() );
2774cdf0e10cSrcweir 		while( aIter != aEnd )
2775cdf0e10cSrcweir 		{
2776cdf0e10cSrcweir 			CustomAnimationEffectPtr pEffect( (*aIter++) );
2777cdf0e10cSrcweir 
2778cdf0e10cSrcweir 			if( pEffect->getTarget().getValueType() == ::getCppuType((const ParagraphTarget*)0) )
2779cdf0e10cSrcweir 				remove( pEffect );
2780cdf0e10cSrcweir 			else
2781cdf0e10cSrcweir 				pTextGroup->addEffect( pEffect );
2782cdf0e10cSrcweir 		}
2783cdf0e10cSrcweir 		notify_listeners();
2784cdf0e10cSrcweir 	}
2785cdf0e10cSrcweir 	else
2786cdf0e10cSrcweir 	{
2787cdf0e10cSrcweir 		// fourth case, we need to change the node types for the text nodes
2788cdf0e10cSrcweir 		double fTextGroupingAuto = pTextGroup->mfGroupingAuto;
2789cdf0e10cSrcweir 
2790cdf0e10cSrcweir 		EffectSequence aEffects( pTextGroup->maEffects );
2791cdf0e10cSrcweir 		pTextGroup->reset();
2792cdf0e10cSrcweir 
2793cdf0e10cSrcweir 		EffectSequence::iterator aIter( aEffects.begin() );
2794cdf0e10cSrcweir 		const EffectSequence::iterator aEnd( aEffects.end() );
2795cdf0e10cSrcweir 		while( aIter != aEnd )
2796cdf0e10cSrcweir 		{
2797cdf0e10cSrcweir 			CustomAnimationEffectPtr pEffect( (*aIter++) );
2798cdf0e10cSrcweir 
2799cdf0e10cSrcweir 			if( pEffect->getTarget().getValueType() == ::getCppuType((const ParagraphTarget*)0) )
2800cdf0e10cSrcweir 			{
2801cdf0e10cSrcweir 				// set correct node type
2802cdf0e10cSrcweir 				if( pEffect->getParaDepth() < nTextGrouping )
2803cdf0e10cSrcweir 				{
2804cdf0e10cSrcweir 					if( fTextGroupingAuto == -1.0 )
2805cdf0e10cSrcweir 					{
2806cdf0e10cSrcweir 						pEffect->setNodeType( EffectNodeType::ON_CLICK );
2807cdf0e10cSrcweir 						pEffect->setBegin( 0.0 );
2808cdf0e10cSrcweir 					}
2809cdf0e10cSrcweir 					else
2810cdf0e10cSrcweir 					{
2811cdf0e10cSrcweir 						pEffect->setNodeType( EffectNodeType::AFTER_PREVIOUS );
2812cdf0e10cSrcweir 						pEffect->setBegin( fTextGroupingAuto );
2813cdf0e10cSrcweir 					}
2814cdf0e10cSrcweir 				}
2815cdf0e10cSrcweir 				else
2816cdf0e10cSrcweir 				{
2817cdf0e10cSrcweir 					pEffect->setNodeType( EffectNodeType::WITH_PREVIOUS );
2818cdf0e10cSrcweir 					pEffect->setBegin( 0.0 );
2819cdf0e10cSrcweir 				}
2820cdf0e10cSrcweir 			}
2821cdf0e10cSrcweir 
2822cdf0e10cSrcweir 			pTextGroup->addEffect( pEffect );
2823cdf0e10cSrcweir 
2824cdf0e10cSrcweir 		}
2825cdf0e10cSrcweir 		notify_listeners();
2826cdf0e10cSrcweir 	}
2827cdf0e10cSrcweir }
2828cdf0e10cSrcweir 
2829cdf0e10cSrcweir // --------------------------------------------------------------------
2830cdf0e10cSrcweir 
2831cdf0e10cSrcweir void EffectSequenceHelper::setAnimateForm( CustomAnimationTextGroupPtr pTextGroup, sal_Bool bAnimateForm )
2832cdf0e10cSrcweir {
2833cdf0e10cSrcweir 	if( pTextGroup->mbAnimateForm == bAnimateForm )
2834cdf0e10cSrcweir 	{
2835cdf0e10cSrcweir 		// trivial case, do nothing
2836cdf0e10cSrcweir 	}
2837cdf0e10cSrcweir 	else
2838cdf0e10cSrcweir 	{
2839cdf0e10cSrcweir 		EffectSequence aEffects( pTextGroup->maEffects );
2840cdf0e10cSrcweir 		pTextGroup->reset();
2841cdf0e10cSrcweir 
2842cdf0e10cSrcweir 		EffectSequence::iterator aIter( aEffects.begin() );
2843cdf0e10cSrcweir 		const EffectSequence::iterator aEnd( aEffects.end() );
2844cdf0e10cSrcweir 
2845cdf0e10cSrcweir 		// first insert if we have to
2846cdf0e10cSrcweir 		if( bAnimateForm )
2847cdf0e10cSrcweir 		{
2848cdf0e10cSrcweir 			EffectSequence::iterator aInsertIter( find( (*aIter) ) );
2849cdf0e10cSrcweir 
2850cdf0e10cSrcweir 			CustomAnimationEffectPtr pEffect;
2851cdf0e10cSrcweir 			if( (aEffects.size() == 1) && ((*aIter)->getTarget().getValueType() != ::getCppuType((const ParagraphTarget*)0) ) )
2852cdf0e10cSrcweir 			{
2853cdf0e10cSrcweir 				// special case, only one effect and that targets whole text,
2854cdf0e10cSrcweir 				// convert this to target whole shape
2855cdf0e10cSrcweir 				pEffect = (*aIter++);
2856cdf0e10cSrcweir 				pEffect->setTargetSubItem( ShapeAnimationSubType::AS_WHOLE );
2857cdf0e10cSrcweir 			}
2858cdf0e10cSrcweir 			else
2859cdf0e10cSrcweir 			{
2860cdf0e10cSrcweir 				pEffect = (*aIter)->clone();
2861cdf0e10cSrcweir 				pEffect->setTarget( makeAny( (*aIter)->getTargetShape() ) );
2862cdf0e10cSrcweir 				pEffect->setTargetSubItem( ShapeAnimationSubType::ONLY_BACKGROUND );
2863cdf0e10cSrcweir 				maEffects.insert( aInsertIter, pEffect );
2864cdf0e10cSrcweir 			}
2865cdf0e10cSrcweir 
2866cdf0e10cSrcweir 			pTextGroup->addEffect( pEffect );
2867cdf0e10cSrcweir 		}
2868cdf0e10cSrcweir 
2869cdf0e10cSrcweir 		if( !bAnimateForm && (aEffects.size() == 1) )
2870cdf0e10cSrcweir 		{
2871cdf0e10cSrcweir 			CustomAnimationEffectPtr pEffect( (*aIter) );
2872cdf0e10cSrcweir 			pEffect->setTarget( makeAny( (*aIter)->getTargetShape() ) );
2873cdf0e10cSrcweir 			pEffect->setTargetSubItem( ShapeAnimationSubType::ONLY_TEXT );
2874cdf0e10cSrcweir 			pTextGroup->addEffect( pEffect );
2875cdf0e10cSrcweir 		}
2876cdf0e10cSrcweir 		else
2877cdf0e10cSrcweir 		{
2878cdf0e10cSrcweir 			// readd the rest to the group again
2879cdf0e10cSrcweir 			while( aIter != aEnd )
2880cdf0e10cSrcweir 			{
2881cdf0e10cSrcweir 				CustomAnimationEffectPtr pEffect( (*aIter++) );
2882cdf0e10cSrcweir 
2883cdf0e10cSrcweir 				if( pEffect->getTarget().getValueType() == ::getCppuType((const ParagraphTarget*)0) )
2884cdf0e10cSrcweir 				{
2885cdf0e10cSrcweir 					pTextGroup->addEffect( pEffect );
2886cdf0e10cSrcweir 				}
2887cdf0e10cSrcweir 				else
2888cdf0e10cSrcweir 				{
2889cdf0e10cSrcweir 					DBG_ASSERT( !bAnimateForm, "sd::EffectSequenceHelper::setAnimateForm(), something is wrong here!" );
2890cdf0e10cSrcweir 					remove( pEffect );
2891cdf0e10cSrcweir 				}
2892cdf0e10cSrcweir 			}
2893cdf0e10cSrcweir 		}
2894cdf0e10cSrcweir 		notify_listeners();
2895cdf0e10cSrcweir 	}
2896cdf0e10cSrcweir }
2897cdf0e10cSrcweir 
2898cdf0e10cSrcweir // --------------------------------------------------------------------
2899cdf0e10cSrcweir 
2900cdf0e10cSrcweir void EffectSequenceHelper::setTextGroupingAuto( CustomAnimationTextGroupPtr pTextGroup, double fTextGroupingAuto )
2901cdf0e10cSrcweir {
2902cdf0e10cSrcweir 	sal_Int32 nTextGrouping = pTextGroup->mnTextGrouping;
2903cdf0e10cSrcweir 
2904cdf0e10cSrcweir 	EffectSequence aEffects( pTextGroup->maEffects );
2905cdf0e10cSrcweir 	pTextGroup->reset();
2906cdf0e10cSrcweir 
2907cdf0e10cSrcweir 	EffectSequence::iterator aIter( aEffects.begin() );
2908cdf0e10cSrcweir 	const EffectSequence::iterator aEnd( aEffects.end() );
2909cdf0e10cSrcweir 	while( aIter != aEnd )
2910cdf0e10cSrcweir 	{
2911cdf0e10cSrcweir 		CustomAnimationEffectPtr pEffect( (*aIter++) );
2912cdf0e10cSrcweir 
2913cdf0e10cSrcweir 		if( pEffect->getTarget().getValueType() == ::getCppuType((const ParagraphTarget*)0) )
2914cdf0e10cSrcweir 		{
2915cdf0e10cSrcweir 			// set correct node type
2916cdf0e10cSrcweir 			if( pEffect->getParaDepth() < nTextGrouping )
2917cdf0e10cSrcweir 			{
2918cdf0e10cSrcweir 				if( fTextGroupingAuto == -1.0 )
2919cdf0e10cSrcweir 				{
2920cdf0e10cSrcweir 					pEffect->setNodeType( EffectNodeType::ON_CLICK );
2921cdf0e10cSrcweir 					pEffect->setBegin( 0.0 );
2922cdf0e10cSrcweir 				}
2923cdf0e10cSrcweir 				else
2924cdf0e10cSrcweir 				{
2925cdf0e10cSrcweir 					pEffect->setNodeType( EffectNodeType::AFTER_PREVIOUS );
2926cdf0e10cSrcweir 					pEffect->setBegin( fTextGroupingAuto );
2927cdf0e10cSrcweir 				}
2928cdf0e10cSrcweir 			}
2929cdf0e10cSrcweir 			else
2930cdf0e10cSrcweir 			{
2931cdf0e10cSrcweir 				pEffect->setNodeType( EffectNodeType::WITH_PREVIOUS );
2932cdf0e10cSrcweir 				pEffect->setBegin( 0.0 );
2933cdf0e10cSrcweir 			}
2934cdf0e10cSrcweir 		}
2935cdf0e10cSrcweir 
2936cdf0e10cSrcweir 		pTextGroup->addEffect( pEffect );
2937cdf0e10cSrcweir 
2938cdf0e10cSrcweir 	}
2939cdf0e10cSrcweir 	notify_listeners();
2940cdf0e10cSrcweir }
2941cdf0e10cSrcweir 
2942cdf0e10cSrcweir // --------------------------------------------------------------------
2943cdf0e10cSrcweir 
2944cdf0e10cSrcweir struct ImplStlTextGroupSortHelper
2945cdf0e10cSrcweir {
2946cdf0e10cSrcweir 	ImplStlTextGroupSortHelper( bool bReverse ) : mbReverse( bReverse ) {};
2947cdf0e10cSrcweir 	bool operator()( const CustomAnimationEffectPtr& p1, const CustomAnimationEffectPtr& p2 );
2948cdf0e10cSrcweir 	bool mbReverse;
2949cdf0e10cSrcweir 	sal_Int32 getTargetParagraph( const CustomAnimationEffectPtr& p1 );
2950cdf0e10cSrcweir };
2951cdf0e10cSrcweir 
2952cdf0e10cSrcweir // --------------------------------------------------------------------
2953cdf0e10cSrcweir 
2954cdf0e10cSrcweir sal_Int32 ImplStlTextGroupSortHelper::getTargetParagraph( const CustomAnimationEffectPtr& p1 )
2955cdf0e10cSrcweir {
2956cdf0e10cSrcweir 	const Any aTarget(p1->getTarget());
2957cdf0e10cSrcweir 	if( aTarget.hasValue() && aTarget.getValueType() == ::getCppuType((const ParagraphTarget*)0) )
2958cdf0e10cSrcweir 	{
2959cdf0e10cSrcweir 		ParagraphTarget aParaTarget;
2960cdf0e10cSrcweir 		aTarget >>= aParaTarget;
2961cdf0e10cSrcweir 		return aParaTarget.Paragraph;
2962cdf0e10cSrcweir 	}
2963cdf0e10cSrcweir 	else
2964cdf0e10cSrcweir 	{
2965cdf0e10cSrcweir 		return mbReverse ? 0x7fffffff : -1;
2966cdf0e10cSrcweir 	}
2967cdf0e10cSrcweir }
2968cdf0e10cSrcweir 
2969cdf0e10cSrcweir // --------------------------------------------------------------------
2970cdf0e10cSrcweir 
2971cdf0e10cSrcweir bool ImplStlTextGroupSortHelper::operator()( const CustomAnimationEffectPtr& p1, const CustomAnimationEffectPtr& p2 )
2972cdf0e10cSrcweir {
2973cdf0e10cSrcweir 	if( mbReverse )
2974cdf0e10cSrcweir 	{
2975cdf0e10cSrcweir 		return getTargetParagraph( p2 ) < getTargetParagraph( p1 );
2976cdf0e10cSrcweir 	}
2977cdf0e10cSrcweir 	else
2978cdf0e10cSrcweir 	{
2979cdf0e10cSrcweir 		return getTargetParagraph( p1 ) < getTargetParagraph( p2 );
2980cdf0e10cSrcweir 	}
2981cdf0e10cSrcweir }
2982cdf0e10cSrcweir 
2983cdf0e10cSrcweir // --------------------------------------------------------------------
2984cdf0e10cSrcweir 
2985cdf0e10cSrcweir void EffectSequenceHelper::setTextReverse( CustomAnimationTextGroupPtr pTextGroup, sal_Bool bTextReverse )
2986cdf0e10cSrcweir {
2987cdf0e10cSrcweir 	if( pTextGroup->mbTextReverse == bTextReverse )
2988cdf0e10cSrcweir 	{
2989cdf0e10cSrcweir 		// do nothing
2990cdf0e10cSrcweir 	}
2991cdf0e10cSrcweir 	else
2992cdf0e10cSrcweir 	{
2993cdf0e10cSrcweir 		std::vector< CustomAnimationEffectPtr > aSortedVector(pTextGroup->maEffects.size());
2994cdf0e10cSrcweir 		std::copy( pTextGroup->maEffects.begin(), pTextGroup->maEffects.end(), aSortedVector.begin() );
2995cdf0e10cSrcweir 		ImplStlTextGroupSortHelper aSortHelper( bTextReverse );
2996cdf0e10cSrcweir 		std::sort( aSortedVector.begin(), aSortedVector.end(), aSortHelper );
2997cdf0e10cSrcweir 
2998cdf0e10cSrcweir 		pTextGroup->reset();
2999cdf0e10cSrcweir 
3000cdf0e10cSrcweir 		std::vector< CustomAnimationEffectPtr >::iterator aIter( aSortedVector.begin() );
3001cdf0e10cSrcweir 		const std::vector< CustomAnimationEffectPtr >::iterator aEnd( aSortedVector.end() );
3002cdf0e10cSrcweir 
3003cdf0e10cSrcweir 		if( aIter != aEnd )
3004cdf0e10cSrcweir 		{
3005cdf0e10cSrcweir 			pTextGroup->addEffect( (*aIter ) );
3006cdf0e10cSrcweir 			EffectSequence::iterator aInsertIter( find( (*aIter++) ) );
3007cdf0e10cSrcweir 			while( aIter != aEnd )
3008cdf0e10cSrcweir 			{
3009cdf0e10cSrcweir 				CustomAnimationEffectPtr pEffect( (*aIter++) );
3010cdf0e10cSrcweir 				maEffects.erase( find( pEffect ) );
3011cdf0e10cSrcweir 				aInsertIter = maEffects.insert( ++aInsertIter, pEffect );
3012cdf0e10cSrcweir 				pTextGroup->addEffect( pEffect );
3013cdf0e10cSrcweir 			}
3014cdf0e10cSrcweir 		}
3015cdf0e10cSrcweir 		notify_listeners();
3016cdf0e10cSrcweir 	}
3017cdf0e10cSrcweir }
3018cdf0e10cSrcweir 
3019cdf0e10cSrcweir // --------------------------------------------------------------------
3020cdf0e10cSrcweir 
3021cdf0e10cSrcweir void EffectSequenceHelper::addListener( ISequenceListener* pListener )
3022cdf0e10cSrcweir {
3023cdf0e10cSrcweir 	if( std::find( maListeners.begin(), maListeners.end(), pListener ) == maListeners.end() )
3024cdf0e10cSrcweir 		maListeners.push_back( pListener );
3025cdf0e10cSrcweir }
3026cdf0e10cSrcweir 
3027cdf0e10cSrcweir // --------------------------------------------------------------------
3028cdf0e10cSrcweir 
3029cdf0e10cSrcweir void EffectSequenceHelper::removeListener( ISequenceListener* pListener )
3030cdf0e10cSrcweir {
3031cdf0e10cSrcweir 	maListeners.remove( pListener );
3032cdf0e10cSrcweir }
3033cdf0e10cSrcweir 
3034cdf0e10cSrcweir // --------------------------------------------------------------------
3035cdf0e10cSrcweir 
3036cdf0e10cSrcweir struct stl_notify_listeners_func : public std::unary_function<ISequenceListener*, void>
3037cdf0e10cSrcweir {
3038cdf0e10cSrcweir 	stl_notify_listeners_func() {}
3039cdf0e10cSrcweir 	void operator()(ISequenceListener* pListener) { pListener->notify_change(); }
3040cdf0e10cSrcweir };
3041cdf0e10cSrcweir 
3042cdf0e10cSrcweir // --------------------------------------------------------------------
3043cdf0e10cSrcweir 
3044cdf0e10cSrcweir void EffectSequenceHelper::notify_listeners()
3045cdf0e10cSrcweir {
3046cdf0e10cSrcweir 	stl_notify_listeners_func aFunc;
3047cdf0e10cSrcweir 	std::for_each( maListeners.begin(), maListeners.end(), aFunc );
3048cdf0e10cSrcweir }
3049cdf0e10cSrcweir 
3050cdf0e10cSrcweir // --------------------------------------------------------------------
3051cdf0e10cSrcweir 
3052cdf0e10cSrcweir void EffectSequenceHelper::create( const ::com::sun::star::uno::Reference< ::com::sun::star::animations::XAnimationNode >& xNode )
3053cdf0e10cSrcweir {
3054cdf0e10cSrcweir 	DBG_ASSERT( xNode.is(), "sd::EffectSequenceHelper::create(), illegal argument" );
3055cdf0e10cSrcweir 
3056cdf0e10cSrcweir 	if( xNode.is() ) try
3057cdf0e10cSrcweir 	{
3058cdf0e10cSrcweir 		Reference< XEnumerationAccess > xEnumerationAccess( xNode, UNO_QUERY_THROW );
3059cdf0e10cSrcweir 		Reference< XEnumeration > xEnumeration( xEnumerationAccess->createEnumeration(), UNO_QUERY_THROW );
3060cdf0e10cSrcweir 		while( xEnumeration->hasMoreElements() )
3061cdf0e10cSrcweir 		{
3062cdf0e10cSrcweir 			Reference< XAnimationNode > xChildNode( xEnumeration->nextElement(), UNO_QUERY_THROW );
3063cdf0e10cSrcweir 			createEffectsequence( xChildNode );
3064cdf0e10cSrcweir 		}
3065cdf0e10cSrcweir 	}
3066cdf0e10cSrcweir 	catch( Exception& )
3067cdf0e10cSrcweir 	{
3068cdf0e10cSrcweir 		DBG_ERROR( "sd::EffectSequenceHelper::create(), exception cought!" );
3069cdf0e10cSrcweir 	}
3070cdf0e10cSrcweir }
3071cdf0e10cSrcweir 
3072cdf0e10cSrcweir // --------------------------------------------------------------------
3073cdf0e10cSrcweir 
3074cdf0e10cSrcweir void EffectSequenceHelper::createEffectsequence( const Reference< XAnimationNode >& xNode )
3075cdf0e10cSrcweir {
3076cdf0e10cSrcweir 	DBG_ASSERT( xNode.is(), "sd::EffectSequenceHelper::createEffectsequence(), illegal argument" );
3077cdf0e10cSrcweir 
3078cdf0e10cSrcweir 	if( xNode.is() ) try
3079cdf0e10cSrcweir 	{
3080cdf0e10cSrcweir 		Reference< XEnumerationAccess > xEnumerationAccess( xNode, UNO_QUERY_THROW );
3081cdf0e10cSrcweir 		Reference< XEnumeration > xEnumeration( xEnumerationAccess->createEnumeration(), UNO_QUERY_THROW );
3082cdf0e10cSrcweir 		while( xEnumeration->hasMoreElements() )
3083cdf0e10cSrcweir 		{
3084cdf0e10cSrcweir 			Reference< XAnimationNode > xChildNode( xEnumeration->nextElement(), UNO_QUERY_THROW );
3085cdf0e10cSrcweir 
3086cdf0e10cSrcweir 			createEffects( xChildNode );
3087cdf0e10cSrcweir 		}
3088cdf0e10cSrcweir 	}
3089cdf0e10cSrcweir 	catch( Exception& )
3090cdf0e10cSrcweir 	{
3091cdf0e10cSrcweir 		DBG_ERROR( "sd::EffectSequenceHelper::createEffectsequence(), exception cought!" );
3092cdf0e10cSrcweir 	}
3093cdf0e10cSrcweir }
3094cdf0e10cSrcweir 
3095cdf0e10cSrcweir // --------------------------------------------------------------------
3096cdf0e10cSrcweir 
3097cdf0e10cSrcweir void EffectSequenceHelper::createEffects( const Reference< XAnimationNode >& xNode )
3098cdf0e10cSrcweir {
3099cdf0e10cSrcweir 	DBG_ASSERT( xNode.is(), "sd::EffectSequenceHelper::createEffects(), illegal argument" );
3100cdf0e10cSrcweir 
3101cdf0e10cSrcweir 	if( xNode.is() ) try
3102cdf0e10cSrcweir 	{
3103cdf0e10cSrcweir 		Reference< XEnumerationAccess > xEnumerationAccess( xNode, UNO_QUERY_THROW );
3104cdf0e10cSrcweir 		Reference< XEnumeration > xEnumeration( xEnumerationAccess->createEnumeration(), UNO_QUERY_THROW );
3105cdf0e10cSrcweir 		while( xEnumeration->hasMoreElements() )
3106cdf0e10cSrcweir 		{
3107cdf0e10cSrcweir 			Reference< XAnimationNode > xChildNode( xEnumeration->nextElement(), UNO_QUERY_THROW );
3108cdf0e10cSrcweir 
3109cdf0e10cSrcweir 			switch( xChildNode->getType() )
3110cdf0e10cSrcweir 			{
3111cdf0e10cSrcweir 			// found an effect
3112cdf0e10cSrcweir 			case AnimationNodeType::PAR:
3113cdf0e10cSrcweir 			case AnimationNodeType::ITERATE:
3114cdf0e10cSrcweir 				{
3115cdf0e10cSrcweir 					CustomAnimationEffectPtr pEffect( new CustomAnimationEffect( xChildNode ) );
3116cdf0e10cSrcweir 
3117cdf0e10cSrcweir 					if( pEffect->mnNodeType != -1 )
3118cdf0e10cSrcweir 					{
3119cdf0e10cSrcweir 						pEffect->setEffectSequence( this );
3120cdf0e10cSrcweir 						maEffects.push_back(pEffect);
3121cdf0e10cSrcweir 					}
3122cdf0e10cSrcweir 				}
3123cdf0e10cSrcweir 				break;
3124cdf0e10cSrcweir 
3125cdf0e10cSrcweir 			// found an after effect
3126cdf0e10cSrcweir 			case AnimationNodeType::SET:
3127cdf0e10cSrcweir 			case AnimationNodeType::ANIMATECOLOR:
3128cdf0e10cSrcweir 				{
3129cdf0e10cSrcweir 					processAfterEffect( xChildNode );
3130cdf0e10cSrcweir 				}
3131cdf0e10cSrcweir 				break;
3132cdf0e10cSrcweir 			}
3133cdf0e10cSrcweir 		}
3134cdf0e10cSrcweir 	}
3135cdf0e10cSrcweir 	catch( Exception& e )
3136cdf0e10cSrcweir 	{
3137cdf0e10cSrcweir 		(void)e;
3138cdf0e10cSrcweir 		DBG_ERROR( "sd::EffectSequenceHelper::createEffects(), exception cought!" );
3139cdf0e10cSrcweir 	}
3140cdf0e10cSrcweir }
3141cdf0e10cSrcweir 
3142cdf0e10cSrcweir // --------------------------------------------------------------------
3143cdf0e10cSrcweir 
3144cdf0e10cSrcweir void EffectSequenceHelper::processAfterEffect( const Reference< XAnimationNode >& xNode )
3145cdf0e10cSrcweir {
3146cdf0e10cSrcweir 	try
3147cdf0e10cSrcweir 	{
3148cdf0e10cSrcweir 		Reference< XAnimationNode > xMaster;
3149cdf0e10cSrcweir 
3150cdf0e10cSrcweir 		Sequence< NamedValue > aUserData( xNode->getUserData() );
3151cdf0e10cSrcweir 		sal_Int32 nLength = aUserData.getLength();
3152cdf0e10cSrcweir 		const NamedValue* p = aUserData.getConstArray();
3153cdf0e10cSrcweir 
3154cdf0e10cSrcweir 		while( nLength-- )
3155cdf0e10cSrcweir 		{
3156cdf0e10cSrcweir 			if( p->Name.equalsAscii( "master-element" ) )
3157cdf0e10cSrcweir 			{
3158cdf0e10cSrcweir 				p->Value >>= xMaster;
3159cdf0e10cSrcweir 				break;
3160cdf0e10cSrcweir 			}
3161cdf0e10cSrcweir 			p++;
3162cdf0e10cSrcweir 		}
3163cdf0e10cSrcweir 
3164cdf0e10cSrcweir 		// only process if this is a valid after effect
3165cdf0e10cSrcweir 		if( xMaster.is() )
3166cdf0e10cSrcweir 		{
3167cdf0e10cSrcweir 			CustomAnimationEffectPtr pMasterEffect;
3168cdf0e10cSrcweir 
3169cdf0e10cSrcweir 			// find the master effect
3170cdf0e10cSrcweir 			stl_CustomAnimationEffect_search_node_predict aSearchPredict( xMaster );
3171cdf0e10cSrcweir 			EffectSequence::iterator aIter( std::find_if( maEffects.begin(), maEffects.end(), aSearchPredict ) );
3172cdf0e10cSrcweir 			if( aIter != maEffects.end() )
3173cdf0e10cSrcweir 				pMasterEffect = (*aIter );
3174cdf0e10cSrcweir 
3175cdf0e10cSrcweir 			if( pMasterEffect.get() )
3176cdf0e10cSrcweir 			{
3177cdf0e10cSrcweir 				pMasterEffect->setHasAfterEffect( true );
3178cdf0e10cSrcweir 
3179cdf0e10cSrcweir 				// find out what kind of after effect this is
3180cdf0e10cSrcweir 				if( xNode->getType() == AnimationNodeType::ANIMATECOLOR )
3181cdf0e10cSrcweir 				{
3182cdf0e10cSrcweir 					// its a dim
3183cdf0e10cSrcweir 					Reference< XAnimate > xAnimate( xNode, UNO_QUERY_THROW );
3184cdf0e10cSrcweir 					pMasterEffect->setDimColor( xAnimate->getTo() );
3185cdf0e10cSrcweir 					pMasterEffect->setAfterEffectOnNext( true );
3186cdf0e10cSrcweir 				}
3187cdf0e10cSrcweir 				else
3188cdf0e10cSrcweir 				{
3189cdf0e10cSrcweir 					// its a hide
3190cdf0e10cSrcweir 					Reference< XChild > xNodeChild( xNode, UNO_QUERY_THROW );
3191cdf0e10cSrcweir 					Reference< XChild > xMasterChild( xMaster, UNO_QUERY_THROW );
3192cdf0e10cSrcweir 					pMasterEffect->setAfterEffectOnNext( xNodeChild->getParent() != xMasterChild->getParent() );
3193cdf0e10cSrcweir 				}
3194cdf0e10cSrcweir 			}
3195cdf0e10cSrcweir 		}
3196cdf0e10cSrcweir 	}
3197cdf0e10cSrcweir 	catch( Exception& e )
3198cdf0e10cSrcweir 	{
3199cdf0e10cSrcweir 		(void)e;
3200cdf0e10cSrcweir 		DBG_ERROR( "sd::EffectSequenceHelper::processAfterEffect(), exception cought!" );
3201cdf0e10cSrcweir 	}
3202cdf0e10cSrcweir }
3203cdf0e10cSrcweir 
3204cdf0e10cSrcweir /*
3205cdf0e10cSrcweir double EffectSequenceHelper::calculateIterateNodeDuration(
3206cdf0e10cSrcweir {
3207cdf0e10cSrcweir     Reference< i18n::XBreakIterator > xBI( ImplGetBreakIterator() );
3208cdf0e10cSrcweir 
3209cdf0e10cSrcweir     sal_Int32 nDone;
3210cdf0e10cSrcweir     sal_Int32 nNextCellBreak( xBI->nextCharacters(rTxt, nIdx, rLocale, i18n::CharacterIteratorMode::SKIPCELL, 0, nDone) );
3211cdf0e10cSrcweir     i18n::Boundary nNextWordBoundary( xBI->getWordBoundary(rTxt, nIdx, rLocale, i18n::WordType::ANY_WORD, sal_True) );
3212cdf0e10cSrcweir     sal_Int32 nNextSentenceBreak( xBI->endOfSentence(rTxt, nIdx, rLocale) );
3213cdf0e10cSrcweir 
3214cdf0e10cSrcweir     const sal_Int32 nEndPos( nIdx + nLen );
3215cdf0e10cSrcweir     sal_Int32 i, currOffset(0);
3216cdf0e10cSrcweir     for( i=nIdx; i<nEndPos; ++i )
3217cdf0e10cSrcweir     {
3218cdf0e10cSrcweir         // TODO: Check whether position update is valid for CTL/BiDi
3219cdf0e10cSrcweir         rOutDev.DrawText( rPos + Point(currOffset,0), rTxt, i, 1 );
3220cdf0e10cSrcweir         currOffset = *pDXArray++;
3221cdf0e10cSrcweir 
3222cdf0e10cSrcweir         // issue the comments at the respective break positions
3223cdf0e10cSrcweir         if( i == nNextCellBreak )
3224cdf0e10cSrcweir         {
3225cdf0e10cSrcweir             rMtf.AddAction( new MetaCommentAction( "XTEXT_EOC" ) );
3226cdf0e10cSrcweir             nNextCellBreak = xBI->nextCharacters(rTxt, i, rLocale, i18n::CharacterIteratorMode::SKIPCELL, 1, nDone);
3227cdf0e10cSrcweir         }
3228cdf0e10cSrcweir         if( i == nNextWordBoundary.endPos )
3229cdf0e10cSrcweir         {
3230cdf0e10cSrcweir             rMtf.AddAction( new MetaCommentAction( "XTEXT_EOW" ) );
3231cdf0e10cSrcweir             nNextWordBoundary = xBI->getWordBoundary(rTxt, i+1, rLocale, i18n::WordType::ANY_WORD, sal_True);
3232cdf0e10cSrcweir         }
3233cdf0e10cSrcweir         if( i == nNextSentenceBreak )
3234cdf0e10cSrcweir         {
3235cdf0e10cSrcweir             rMtf.AddAction( new MetaCommentAction( "XTEXT_EOS" ) );
3236cdf0e10cSrcweir             nNextSentenceBreak = xBI->endOfSentence(rTxt, i+1, rLocale);
3237cdf0e10cSrcweir         }
3238cdf0e10cSrcweir     }
3239cdf0e10cSrcweir }
3240cdf0e10cSrcweir 
3241cdf0e10cSrcweir */
3242cdf0e10cSrcweir // ====================================================================
3243cdf0e10cSrcweir 
3244cdf0e10cSrcweir class AnimationChangeListener : public cppu::WeakImplHelper1< XChangesListener >
3245cdf0e10cSrcweir {
3246cdf0e10cSrcweir public:
3247cdf0e10cSrcweir 	AnimationChangeListener( MainSequence* pMainSequence ) : mpMainSequence( pMainSequence ) {}
3248cdf0e10cSrcweir 
3249cdf0e10cSrcweir     virtual void SAL_CALL changesOccurred( const ::com::sun::star::util::ChangesEvent& Event ) throw (RuntimeException);
3250cdf0e10cSrcweir     virtual void SAL_CALL disposing( const ::com::sun::star::lang::EventObject& Source ) throw (RuntimeException);
3251cdf0e10cSrcweir private:
3252cdf0e10cSrcweir 	MainSequence* mpMainSequence;
3253cdf0e10cSrcweir };
3254cdf0e10cSrcweir 
3255cdf0e10cSrcweir void SAL_CALL AnimationChangeListener::changesOccurred( const ::com::sun::star::util::ChangesEvent& ) throw (RuntimeException)
3256cdf0e10cSrcweir {
3257cdf0e10cSrcweir 	if( mpMainSequence )
3258cdf0e10cSrcweir 		mpMainSequence->startRecreateTimer();
3259cdf0e10cSrcweir }
3260cdf0e10cSrcweir 
3261cdf0e10cSrcweir void SAL_CALL AnimationChangeListener::disposing( const ::com::sun::star::lang::EventObject& ) throw (RuntimeException)
3262cdf0e10cSrcweir {
3263cdf0e10cSrcweir }
3264cdf0e10cSrcweir 
3265cdf0e10cSrcweir // ====================================================================
3266cdf0e10cSrcweir 
3267cdf0e10cSrcweir MainSequence::MainSequence()
3268cdf0e10cSrcweir : mxTimingRootNode( ::comphelper::getProcessServiceFactory()->createInstance(OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.animations.SequenceTimeContainer"))), UNO_QUERY )
3269cdf0e10cSrcweir , mbRebuilding( false )
3270cdf0e10cSrcweir , mnRebuildLockGuard( 0 )
3271cdf0e10cSrcweir , mbPendingRebuildRequest( false )
3272cdf0e10cSrcweir {
3273cdf0e10cSrcweir 	if( mxTimingRootNode.is() )
3274cdf0e10cSrcweir 	{
3275cdf0e10cSrcweir 		Sequence< ::com::sun::star::beans::NamedValue > aUserData( 1 );
3276cdf0e10cSrcweir 		aUserData[0].Name = OUString( RTL_CONSTASCII_USTRINGPARAM( "node-type" ) );
3277cdf0e10cSrcweir 		aUserData[0].Value <<= ::com::sun::star::presentation::EffectNodeType::MAIN_SEQUENCE;
3278cdf0e10cSrcweir 		mxTimingRootNode->setUserData( aUserData );
3279cdf0e10cSrcweir 	}
3280cdf0e10cSrcweir 	init();
3281cdf0e10cSrcweir }
3282cdf0e10cSrcweir 
3283cdf0e10cSrcweir // --------------------------------------------------------------------
3284cdf0e10cSrcweir 
3285cdf0e10cSrcweir MainSequence::MainSequence( const ::com::sun::star::uno::Reference< ::com::sun::star::animations::XAnimationNode >& xNode )
3286cdf0e10cSrcweir : mxTimingRootNode( xNode, UNO_QUERY )
3287cdf0e10cSrcweir , mbRebuilding( false )
3288cdf0e10cSrcweir , mnRebuildLockGuard( 0 )
3289cdf0e10cSrcweir , mbPendingRebuildRequest( false )
3290cdf0e10cSrcweir , mbIgnoreChanges( 0 )
3291cdf0e10cSrcweir {
3292cdf0e10cSrcweir 	init();
3293cdf0e10cSrcweir }
3294cdf0e10cSrcweir 
3295cdf0e10cSrcweir // --------------------------------------------------------------------
3296cdf0e10cSrcweir 
3297cdf0e10cSrcweir MainSequence::~MainSequence()
3298cdf0e10cSrcweir {
3299cdf0e10cSrcweir 	reset();
3300cdf0e10cSrcweir }
3301cdf0e10cSrcweir 
3302cdf0e10cSrcweir // --------------------------------------------------------------------
3303cdf0e10cSrcweir 
3304cdf0e10cSrcweir void MainSequence::init()
3305cdf0e10cSrcweir {
3306cdf0e10cSrcweir 	mnSequenceType = EffectNodeType::MAIN_SEQUENCE;
3307cdf0e10cSrcweir 
3308cdf0e10cSrcweir 	maTimer.SetTimeoutHdl( LINK(this, MainSequence, onTimerHdl) );
3309cdf0e10cSrcweir 	maTimer.SetTimeout(500);
3310cdf0e10cSrcweir 
3311cdf0e10cSrcweir 	mxChangesListener.set( new AnimationChangeListener( this ) );
3312cdf0e10cSrcweir 
3313cdf0e10cSrcweir 	createMainSequence();
3314cdf0e10cSrcweir }
3315cdf0e10cSrcweir 
3316cdf0e10cSrcweir // --------------------------------------------------------------------
3317cdf0e10cSrcweir 
3318cdf0e10cSrcweir void MainSequence::reset( const ::com::sun::star::uno::Reference< ::com::sun::star::animations::XAnimationNode >& xTimingRootNode )
3319cdf0e10cSrcweir {
3320cdf0e10cSrcweir 	reset();
3321cdf0e10cSrcweir 
3322cdf0e10cSrcweir 	mxTimingRootNode.set( xTimingRootNode, UNO_QUERY );
3323cdf0e10cSrcweir 
3324cdf0e10cSrcweir 	createMainSequence();
3325cdf0e10cSrcweir }
3326cdf0e10cSrcweir 
3327cdf0e10cSrcweir // --------------------------------------------------------------------
3328cdf0e10cSrcweir 
3329cdf0e10cSrcweir Reference< ::com::sun::star::animations::XAnimationNode > MainSequence::getRootNode()
3330cdf0e10cSrcweir {
3331cdf0e10cSrcweir 	DBG_ASSERT( mnRebuildLockGuard == 0, "MainSequence::getRootNode(), rebuild is locked, ist this really what you want?" );
3332cdf0e10cSrcweir 
3333cdf0e10cSrcweir 	if( maTimer.IsActive() && mbTimerMode )
3334cdf0e10cSrcweir 	{
3335cdf0e10cSrcweir 		// force a rebuild NOW if one is pending
3336cdf0e10cSrcweir 		maTimer.Stop();
3337cdf0e10cSrcweir 		implRebuild();
3338cdf0e10cSrcweir 	}
3339cdf0e10cSrcweir 
3340cdf0e10cSrcweir 	return EffectSequenceHelper::getRootNode();
3341cdf0e10cSrcweir }
3342cdf0e10cSrcweir 
3343cdf0e10cSrcweir // --------------------------------------------------------------------
3344cdf0e10cSrcweir 
3345cdf0e10cSrcweir void MainSequence::createMainSequence()
3346cdf0e10cSrcweir {
3347cdf0e10cSrcweir 	if( mxTimingRootNode.is() ) try
3348cdf0e10cSrcweir 	{
3349cdf0e10cSrcweir 		Reference< XEnumerationAccess > xEnumerationAccess( mxTimingRootNode, UNO_QUERY_THROW );
3350cdf0e10cSrcweir 		Reference< XEnumeration > xEnumeration( xEnumerationAccess->createEnumeration(), UNO_QUERY_THROW );
3351cdf0e10cSrcweir 		while( xEnumeration->hasMoreElements() )
3352cdf0e10cSrcweir 		{
3353cdf0e10cSrcweir 			Reference< XAnimationNode > xChildNode( xEnumeration->nextElement(), UNO_QUERY_THROW );
3354cdf0e10cSrcweir 			sal_Int32 nNodeType = CustomAnimationEffect::get_node_type( xChildNode );
3355cdf0e10cSrcweir 			if( nNodeType == EffectNodeType::MAIN_SEQUENCE )
3356cdf0e10cSrcweir 			{
3357cdf0e10cSrcweir 				mxSequenceRoot.set( xChildNode, UNO_QUERY );
3358cdf0e10cSrcweir 				EffectSequenceHelper::create( xChildNode );
3359cdf0e10cSrcweir 			}
3360cdf0e10cSrcweir 			else if( nNodeType == EffectNodeType::INTERACTIVE_SEQUENCE )
3361cdf0e10cSrcweir 			{
3362cdf0e10cSrcweir 				Reference< XTimeContainer > xInteractiveRoot( xChildNode, UNO_QUERY_THROW );
3363cdf0e10cSrcweir 				InteractiveSequencePtr pIS( new InteractiveSequence( xInteractiveRoot, this ) );
3364cdf0e10cSrcweir 				pIS->addListener( this );
3365cdf0e10cSrcweir 				maInteractiveSequenceList.push_back( pIS );
3366cdf0e10cSrcweir 			}
3367cdf0e10cSrcweir 		}
3368cdf0e10cSrcweir 
3369cdf0e10cSrcweir 		// see if we have a mainsequence at all. if not, create one...
3370cdf0e10cSrcweir 		if( !mxSequenceRoot.is() )
3371cdf0e10cSrcweir 		{
3372cdf0e10cSrcweir 			mxSequenceRoot = Reference< XTimeContainer >::query(::comphelper::getProcessServiceFactory()->createInstance(OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.animations.SequenceTimeContainer"))));
3373cdf0e10cSrcweir 			if( mxSequenceRoot.is() )
3374cdf0e10cSrcweir 			{
3375cdf0e10cSrcweir 				uno::Sequence< ::com::sun::star::beans::NamedValue > aUserData( 1 );
3376cdf0e10cSrcweir 				aUserData[0].Name = OUString( RTL_CONSTASCII_USTRINGPARAM( "node-type" ) );
3377cdf0e10cSrcweir 				aUserData[0].Value <<= ::com::sun::star::presentation::EffectNodeType::MAIN_SEQUENCE;
3378cdf0e10cSrcweir 				mxSequenceRoot->setUserData( aUserData );
3379cdf0e10cSrcweir 
3380cdf0e10cSrcweir                 // empty sequence until now, set duration to 0.0
3381cdf0e10cSrcweir                 // explicitely (otherwise, this sequence will never
3382cdf0e10cSrcweir                 // end)
3383cdf0e10cSrcweir                 mxSequenceRoot->setDuration( makeAny((double)0.0) );
3384cdf0e10cSrcweir 
3385cdf0e10cSrcweir 				Reference< XAnimationNode > xMainSequenceNode( mxSequenceRoot, UNO_QUERY_THROW );
3386cdf0e10cSrcweir 				mxTimingRootNode->appendChild( xMainSequenceNode );
3387cdf0e10cSrcweir 			}
3388cdf0e10cSrcweir 		}
3389cdf0e10cSrcweir 
3390cdf0e10cSrcweir 		updateTextGroups();
3391cdf0e10cSrcweir 
3392cdf0e10cSrcweir 		notify_listeners();
3393cdf0e10cSrcweir 
3394cdf0e10cSrcweir 		Reference< XChangesNotifier > xNotifier( mxTimingRootNode, UNO_QUERY );
3395cdf0e10cSrcweir 		if( xNotifier.is() )
3396cdf0e10cSrcweir 			xNotifier->addChangesListener( mxChangesListener );
3397cdf0e10cSrcweir 	}
3398cdf0e10cSrcweir 	catch( Exception& e )
3399cdf0e10cSrcweir 	{
3400cdf0e10cSrcweir 		(void)e;
3401cdf0e10cSrcweir 		DBG_ERROR( "sd::MainSequence::create(), exception cought!" );
3402cdf0e10cSrcweir 		return;
3403cdf0e10cSrcweir 	}
3404cdf0e10cSrcweir 
3405cdf0e10cSrcweir 	DBG_ASSERT( mxSequenceRoot.is(), "sd::MainSequence::create(), found no main sequence!" );
3406cdf0e10cSrcweir }
3407cdf0e10cSrcweir 
3408cdf0e10cSrcweir // --------------------------------------------------------------------
3409cdf0e10cSrcweir 
3410cdf0e10cSrcweir void MainSequence::reset()
3411cdf0e10cSrcweir {
3412cdf0e10cSrcweir 	EffectSequenceHelper::reset();
3413cdf0e10cSrcweir 
3414cdf0e10cSrcweir 	InteractiveSequenceList::iterator aIter;
3415cdf0e10cSrcweir 	for( aIter = maInteractiveSequenceList.begin(); aIter != maInteractiveSequenceList.end(); aIter++ )
3416cdf0e10cSrcweir 		(*aIter)->reset();
3417cdf0e10cSrcweir 	maInteractiveSequenceList.clear();
3418cdf0e10cSrcweir 
3419cdf0e10cSrcweir 	try
3420cdf0e10cSrcweir 	{
3421cdf0e10cSrcweir 		Reference< XChangesNotifier > xNotifier( mxTimingRootNode, UNO_QUERY );
3422cdf0e10cSrcweir 		if( xNotifier.is() )
3423cdf0e10cSrcweir 			xNotifier->removeChangesListener( mxChangesListener );
3424cdf0e10cSrcweir 	}
3425cdf0e10cSrcweir 	catch( Exception& )
3426cdf0e10cSrcweir 	{
3427cdf0e10cSrcweir 		// ...
3428cdf0e10cSrcweir 	}
3429cdf0e10cSrcweir }
3430cdf0e10cSrcweir 
3431cdf0e10cSrcweir // --------------------------------------------------------------------
3432cdf0e10cSrcweir 
3433cdf0e10cSrcweir InteractiveSequencePtr MainSequence::createInteractiveSequence( const ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape >& xShape )
3434cdf0e10cSrcweir {
3435cdf0e10cSrcweir 	InteractiveSequencePtr pIS;
3436cdf0e10cSrcweir 
3437cdf0e10cSrcweir 	// create a new interactive sequence container
3438cdf0e10cSrcweir 	Reference< XTimeContainer > xISRoot( ::comphelper::getProcessServiceFactory()->createInstance(OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.animations.SequenceTimeContainer"))), UNO_QUERY );
3439cdf0e10cSrcweir 	DBG_ASSERT( xISRoot.is(), "sd::MainSequence::createInteractiveSequence(), could not create \"com.sun.star.animations.SequenceTimeContainer\"!");
3440cdf0e10cSrcweir 	if( xISRoot.is() )
3441cdf0e10cSrcweir 	{
3442cdf0e10cSrcweir 		uno::Sequence< ::com::sun::star::beans::NamedValue > aUserData( 1 );
3443cdf0e10cSrcweir 		aUserData[0].Name = OUString( RTL_CONSTASCII_USTRINGPARAM( "node-type" ) );
3444cdf0e10cSrcweir 		aUserData[0].Value <<= ::com::sun::star::presentation::EffectNodeType::INTERACTIVE_SEQUENCE ;
3445cdf0e10cSrcweir 		xISRoot->setUserData( aUserData );
3446cdf0e10cSrcweir 
3447cdf0e10cSrcweir 		Reference< XChild > xChild( mxSequenceRoot, UNO_QUERY_THROW );
3448cdf0e10cSrcweir 		Reference< XAnimationNode > xISNode( xISRoot, UNO_QUERY_THROW );
3449cdf0e10cSrcweir 		Reference< XTimeContainer > xParent( xChild->getParent(), UNO_QUERY_THROW );
3450cdf0e10cSrcweir 		xParent->appendChild( xISNode );
3451cdf0e10cSrcweir 	}
3452cdf0e10cSrcweir 	pIS.reset( new InteractiveSequence( xISRoot, this) );
3453cdf0e10cSrcweir     pIS->setTriggerShape( xShape );
3454cdf0e10cSrcweir 	pIS->addListener( this );
3455cdf0e10cSrcweir 	maInteractiveSequenceList.push_back( pIS );
3456cdf0e10cSrcweir 	return pIS;
3457cdf0e10cSrcweir }
3458cdf0e10cSrcweir 
3459cdf0e10cSrcweir // --------------------------------------------------------------------
3460cdf0e10cSrcweir 
3461cdf0e10cSrcweir CustomAnimationEffectPtr MainSequence::findEffect( const ::com::sun::star::uno::Reference< ::com::sun::star::animations::XAnimationNode >& xNode ) const
3462cdf0e10cSrcweir {
3463cdf0e10cSrcweir 	CustomAnimationEffectPtr pEffect = EffectSequenceHelper::findEffect( xNode );
3464cdf0e10cSrcweir 
3465cdf0e10cSrcweir 	if( pEffect.get() == 0 )
3466cdf0e10cSrcweir 	{
3467cdf0e10cSrcweir 		InteractiveSequenceList::const_iterator aIter;
3468cdf0e10cSrcweir 		for( aIter = maInteractiveSequenceList.begin(); (aIter != maInteractiveSequenceList.end()) && (pEffect.get() == 0); aIter++ )
3469cdf0e10cSrcweir 		{
3470cdf0e10cSrcweir 			pEffect = (*aIter)->findEffect( xNode );
3471cdf0e10cSrcweir 		}
3472cdf0e10cSrcweir 	}
3473cdf0e10cSrcweir 	return pEffect;
3474cdf0e10cSrcweir }
3475cdf0e10cSrcweir 
3476cdf0e10cSrcweir // --------------------------------------------------------------------
3477cdf0e10cSrcweir 
3478cdf0e10cSrcweir sal_Int32 MainSequence::getOffsetFromEffect( const CustomAnimationEffectPtr& pEffect ) const
3479cdf0e10cSrcweir {
3480cdf0e10cSrcweir 	sal_Int32 nOffset = EffectSequenceHelper::getOffsetFromEffect( pEffect );
3481cdf0e10cSrcweir 
3482cdf0e10cSrcweir 	if( nOffset != -1 )
3483cdf0e10cSrcweir 		return nOffset;
3484cdf0e10cSrcweir 
3485cdf0e10cSrcweir 	nOffset = EffectSequenceHelper::getCount();
3486cdf0e10cSrcweir 
3487cdf0e10cSrcweir 	InteractiveSequenceList::const_iterator aIter;
3488cdf0e10cSrcweir 	for( aIter = maInteractiveSequenceList.begin(); aIter != maInteractiveSequenceList.end(); aIter++ )
3489cdf0e10cSrcweir 	{
3490cdf0e10cSrcweir 		sal_Int32 nTemp = (*aIter)->getOffsetFromEffect( pEffect );
3491cdf0e10cSrcweir 		if( nTemp != -1 )
3492cdf0e10cSrcweir 			return nOffset + nTemp;
3493cdf0e10cSrcweir 
3494cdf0e10cSrcweir 		nOffset += (*aIter)->getCount();
3495cdf0e10cSrcweir 	}
3496cdf0e10cSrcweir 
3497cdf0e10cSrcweir 	return -1;
3498cdf0e10cSrcweir }
3499cdf0e10cSrcweir 
3500cdf0e10cSrcweir // --------------------------------------------------------------------
3501cdf0e10cSrcweir 
3502cdf0e10cSrcweir CustomAnimationEffectPtr MainSequence::getEffectFromOffset( sal_Int32 nOffset ) const
3503cdf0e10cSrcweir {
3504cdf0e10cSrcweir 	if( nOffset >= 0 )
3505cdf0e10cSrcweir 	{
3506cdf0e10cSrcweir 		if( nOffset < getCount() )
3507cdf0e10cSrcweir 			return EffectSequenceHelper::getEffectFromOffset( nOffset );
3508cdf0e10cSrcweir 
3509cdf0e10cSrcweir 		nOffset -= getCount();
3510cdf0e10cSrcweir 
3511cdf0e10cSrcweir 		InteractiveSequenceList::const_iterator aIter( maInteractiveSequenceList.begin() );
3512cdf0e10cSrcweir 
3513cdf0e10cSrcweir 		while( (aIter != maInteractiveSequenceList.end()) && (nOffset > (*aIter)->getCount()) )
3514cdf0e10cSrcweir 			nOffset -= (*aIter++)->getCount();
3515cdf0e10cSrcweir 
3516cdf0e10cSrcweir 		if( (aIter != maInteractiveSequenceList.end()) && (nOffset >= 0) )
3517cdf0e10cSrcweir 			return (*aIter)->getEffectFromOffset( nOffset );
3518cdf0e10cSrcweir 	}
3519cdf0e10cSrcweir 
3520cdf0e10cSrcweir 	CustomAnimationEffectPtr pEffect;
3521cdf0e10cSrcweir 	return pEffect;
3522cdf0e10cSrcweir }
3523cdf0e10cSrcweir 
3524cdf0e10cSrcweir // --------------------------------------------------------------------
3525cdf0e10cSrcweir 
3526cdf0e10cSrcweir bool MainSequence::disposeShape( const Reference< XShape >& xShape )
3527cdf0e10cSrcweir {
3528cdf0e10cSrcweir 	bool bChanges = EffectSequenceHelper::disposeShape( xShape );
3529cdf0e10cSrcweir 
3530cdf0e10cSrcweir 	InteractiveSequenceList::iterator aIter;
3531cdf0e10cSrcweir 	for( aIter = maInteractiveSequenceList.begin(); aIter != maInteractiveSequenceList.end();  )
3532cdf0e10cSrcweir 	{
3533cdf0e10cSrcweir 			bChanges |= (*aIter++)->disposeShape( xShape );
3534cdf0e10cSrcweir 	}
3535cdf0e10cSrcweir 
3536cdf0e10cSrcweir 	if( bChanges )
3537cdf0e10cSrcweir 		startRebuildTimer();
3538cdf0e10cSrcweir 
3539cdf0e10cSrcweir 	return bChanges;
3540cdf0e10cSrcweir }
3541cdf0e10cSrcweir 
3542cdf0e10cSrcweir // --------------------------------------------------------------------
3543cdf0e10cSrcweir 
3544cdf0e10cSrcweir bool MainSequence::hasEffect( const com::sun::star::uno::Reference< com::sun::star::drawing::XShape >& xShape )
3545cdf0e10cSrcweir {
3546cdf0e10cSrcweir 	if( EffectSequenceHelper::hasEffect( xShape ) )
3547cdf0e10cSrcweir 		return true;
3548cdf0e10cSrcweir 
3549cdf0e10cSrcweir 	InteractiveSequenceList::iterator aIter;
3550cdf0e10cSrcweir 	for( aIter = maInteractiveSequenceList.begin(); aIter != maInteractiveSequenceList.end();  )
3551cdf0e10cSrcweir 	{
3552cdf0e10cSrcweir 		if( (*aIter)->getTriggerShape() == xShape )
3553cdf0e10cSrcweir 			return true;
3554cdf0e10cSrcweir 
3555cdf0e10cSrcweir 		if( (*aIter++)->hasEffect( xShape ) )
3556cdf0e10cSrcweir 			return true;
3557cdf0e10cSrcweir 	}
3558cdf0e10cSrcweir 
3559cdf0e10cSrcweir 	return false;
3560cdf0e10cSrcweir }
3561cdf0e10cSrcweir 
3562cdf0e10cSrcweir // --------------------------------------------------------------------
3563cdf0e10cSrcweir 
3564cdf0e10cSrcweir void MainSequence::insertTextRange( const com::sun::star::uno::Any& aTarget )
3565cdf0e10cSrcweir {
3566cdf0e10cSrcweir 	EffectSequenceHelper::insertTextRange( aTarget );
3567cdf0e10cSrcweir 
3568cdf0e10cSrcweir 	InteractiveSequenceList::iterator aIter;
3569cdf0e10cSrcweir 	for( aIter = maInteractiveSequenceList.begin(); aIter != maInteractiveSequenceList.end(); aIter++ )
3570cdf0e10cSrcweir 	{
3571cdf0e10cSrcweir 		(*aIter)->insertTextRange( aTarget );
3572cdf0e10cSrcweir 	}
3573cdf0e10cSrcweir }
3574cdf0e10cSrcweir // --------------------------------------------------------------------
3575cdf0e10cSrcweir 
3576cdf0e10cSrcweir void MainSequence::disposeTextRange( const com::sun::star::uno::Any& aTarget )
3577cdf0e10cSrcweir {
3578cdf0e10cSrcweir 	EffectSequenceHelper::disposeTextRange( aTarget );
3579cdf0e10cSrcweir 
3580cdf0e10cSrcweir 	InteractiveSequenceList::iterator aIter;
3581cdf0e10cSrcweir 	for( aIter = maInteractiveSequenceList.begin(); aIter != maInteractiveSequenceList.end(); aIter++ )
3582cdf0e10cSrcweir 	{
3583cdf0e10cSrcweir 		(*aIter)->disposeTextRange( aTarget );
3584cdf0e10cSrcweir 	}
3585cdf0e10cSrcweir }
3586cdf0e10cSrcweir 
3587cdf0e10cSrcweir // --------------------------------------------------------------------
3588cdf0e10cSrcweir 
3589cdf0e10cSrcweir /** callback from the sd::View when an object just left text edit mode */
3590cdf0e10cSrcweir void MainSequence::onTextChanged( const Reference< XShape >& xShape )
3591cdf0e10cSrcweir {
3592cdf0e10cSrcweir 	EffectSequenceHelper::onTextChanged( xShape );
3593cdf0e10cSrcweir 
3594cdf0e10cSrcweir 	InteractiveSequenceList::iterator aIter;
3595cdf0e10cSrcweir 	for( aIter = maInteractiveSequenceList.begin(); aIter != maInteractiveSequenceList.end(); aIter++ )
3596cdf0e10cSrcweir 	{
3597cdf0e10cSrcweir 		(*aIter)->onTextChanged( xShape );
3598cdf0e10cSrcweir 	}
3599cdf0e10cSrcweir }
3600cdf0e10cSrcweir 
3601cdf0e10cSrcweir // --------------------------------------------------------------------
3602cdf0e10cSrcweir 
3603cdf0e10cSrcweir void EffectSequenceHelper::onTextChanged( const Reference< XShape >& xShape )
3604cdf0e10cSrcweir {
3605cdf0e10cSrcweir 	bool bChanges = false;
3606cdf0e10cSrcweir 
3607cdf0e10cSrcweir 	EffectSequence::iterator aIter;
3608cdf0e10cSrcweir 	for( aIter = maEffects.begin(); aIter != maEffects.end(); aIter++ )
3609cdf0e10cSrcweir 	{
3610cdf0e10cSrcweir 		if( (*aIter)->getTargetShape() == xShape )
3611cdf0e10cSrcweir 			bChanges |= (*aIter)->checkForText();
3612cdf0e10cSrcweir 	}
3613cdf0e10cSrcweir 
3614cdf0e10cSrcweir 	if( bChanges )
3615cdf0e10cSrcweir 		EffectSequenceHelper::implRebuild();
3616cdf0e10cSrcweir }
3617cdf0e10cSrcweir 
3618cdf0e10cSrcweir // --------------------------------------------------------------------
3619cdf0e10cSrcweir 
3620cdf0e10cSrcweir void MainSequence::rebuild()
3621cdf0e10cSrcweir {
3622cdf0e10cSrcweir 	startRebuildTimer();
3623cdf0e10cSrcweir }
3624cdf0e10cSrcweir 
3625cdf0e10cSrcweir // --------------------------------------------------------------------
3626cdf0e10cSrcweir 
3627cdf0e10cSrcweir void MainSequence::lockRebuilds()
3628cdf0e10cSrcweir {
3629cdf0e10cSrcweir 	mnRebuildLockGuard++;
3630cdf0e10cSrcweir }
3631cdf0e10cSrcweir 
3632cdf0e10cSrcweir // --------------------------------------------------------------------
3633cdf0e10cSrcweir 
3634cdf0e10cSrcweir void MainSequence::unlockRebuilds()
3635cdf0e10cSrcweir {
3636cdf0e10cSrcweir 	DBG_ASSERT( mnRebuildLockGuard, "sd::MainSequence::unlockRebuilds(), no corresponding lockRebuilds() call!" );
3637cdf0e10cSrcweir 	if( mnRebuildLockGuard )
3638cdf0e10cSrcweir 		mnRebuildLockGuard--;
3639cdf0e10cSrcweir 
3640cdf0e10cSrcweir 	if( (mnRebuildLockGuard == 0) && mbPendingRebuildRequest )
3641cdf0e10cSrcweir 	{
3642cdf0e10cSrcweir 		mbPendingRebuildRequest = false;
3643cdf0e10cSrcweir 		startRebuildTimer();
3644cdf0e10cSrcweir 	}
3645cdf0e10cSrcweir }
3646cdf0e10cSrcweir 
3647cdf0e10cSrcweir // --------------------------------------------------------------------
3648cdf0e10cSrcweir 
3649cdf0e10cSrcweir void MainSequence::implRebuild()
3650cdf0e10cSrcweir {
3651cdf0e10cSrcweir 	if( mnRebuildLockGuard )
3652cdf0e10cSrcweir 	{
3653cdf0e10cSrcweir 		mbPendingRebuildRequest = true;
3654cdf0e10cSrcweir 		return;
3655cdf0e10cSrcweir 	}
3656cdf0e10cSrcweir 
3657cdf0e10cSrcweir 	mbRebuilding = true;
3658cdf0e10cSrcweir 
3659cdf0e10cSrcweir 	EffectSequenceHelper::implRebuild();
3660cdf0e10cSrcweir 
3661cdf0e10cSrcweir 	InteractiveSequenceList::iterator aIter( maInteractiveSequenceList.begin() );
3662cdf0e10cSrcweir 	const InteractiveSequenceList::iterator aEnd( maInteractiveSequenceList.end() );
3663cdf0e10cSrcweir 	while( aIter != aEnd )
3664cdf0e10cSrcweir 	{
3665cdf0e10cSrcweir 		InteractiveSequencePtr pIS( (*aIter) );
3666cdf0e10cSrcweir 		if( pIS->maEffects.empty() )
3667cdf0e10cSrcweir 		{
3668cdf0e10cSrcweir 			// remove empty interactive sequences
3669cdf0e10cSrcweir 			aIter = maInteractiveSequenceList.erase( aIter );
3670cdf0e10cSrcweir 
3671cdf0e10cSrcweir 			Reference< XChild > xChild( mxSequenceRoot, UNO_QUERY_THROW );
3672cdf0e10cSrcweir 			Reference< XTimeContainer > xParent( xChild->getParent(), UNO_QUERY_THROW );
3673cdf0e10cSrcweir 			Reference< XAnimationNode > xISNode( pIS->mxSequenceRoot, UNO_QUERY_THROW );
3674cdf0e10cSrcweir 			xParent->removeChild( xISNode );
3675cdf0e10cSrcweir 		}
3676cdf0e10cSrcweir 		else
3677cdf0e10cSrcweir 		{
3678cdf0e10cSrcweir 			pIS->implRebuild();
3679cdf0e10cSrcweir 			aIter++;
3680cdf0e10cSrcweir 		}
3681cdf0e10cSrcweir 	}
3682cdf0e10cSrcweir 
3683cdf0e10cSrcweir 	notify_listeners();
3684cdf0e10cSrcweir 	mbRebuilding = false;
3685cdf0e10cSrcweir }
3686cdf0e10cSrcweir 
3687cdf0e10cSrcweir // --------------------------------------------------------------------
3688cdf0e10cSrcweir 
3689cdf0e10cSrcweir void MainSequence::notify_change()
3690cdf0e10cSrcweir {
3691cdf0e10cSrcweir 	notify_listeners();
3692cdf0e10cSrcweir }
3693cdf0e10cSrcweir 
3694cdf0e10cSrcweir // --------------------------------------------------------------------
3695cdf0e10cSrcweir 
3696cdf0e10cSrcweir bool MainSequence::setTrigger( const CustomAnimationEffectPtr& pEffect, const ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape >& xTriggerShape )
3697cdf0e10cSrcweir {
3698cdf0e10cSrcweir 	EffectSequenceHelper* pOldSequence = pEffect->getEffectSequence();
3699cdf0e10cSrcweir 
3700cdf0e10cSrcweir 	EffectSequenceHelper* pNewSequence = 0;
3701cdf0e10cSrcweir 	if( xTriggerShape.is() )
3702cdf0e10cSrcweir 	{
3703cdf0e10cSrcweir 		InteractiveSequenceList::iterator aIter( maInteractiveSequenceList.begin() );
3704cdf0e10cSrcweir 		const InteractiveSequenceList::iterator aEnd( maInteractiveSequenceList.end() );
3705cdf0e10cSrcweir 		while( aIter != aEnd )
3706cdf0e10cSrcweir 		{
3707cdf0e10cSrcweir 			InteractiveSequencePtr pIS( (*aIter++) );
3708cdf0e10cSrcweir 			if( pIS->getTriggerShape() == xTriggerShape )
3709cdf0e10cSrcweir 			{
3710cdf0e10cSrcweir 				pNewSequence = pIS.get();
3711cdf0e10cSrcweir 				break;
3712cdf0e10cSrcweir 			}
3713cdf0e10cSrcweir 		}
3714cdf0e10cSrcweir 
3715cdf0e10cSrcweir 		if( !pNewSequence )
3716cdf0e10cSrcweir 			pNewSequence = createInteractiveSequence( xTriggerShape ).get();
3717cdf0e10cSrcweir 	}
3718cdf0e10cSrcweir 	else
3719cdf0e10cSrcweir 	{
3720cdf0e10cSrcweir 		pNewSequence = this;
3721cdf0e10cSrcweir 	}
3722cdf0e10cSrcweir 
3723cdf0e10cSrcweir 	if( pOldSequence != pNewSequence )
3724cdf0e10cSrcweir 	{
3725cdf0e10cSrcweir 		if( pOldSequence )
3726cdf0e10cSrcweir 			pOldSequence->maEffects.remove( pEffect );
3727cdf0e10cSrcweir 		if( pNewSequence )
3728cdf0e10cSrcweir 			pNewSequence->maEffects.push_back( pEffect );
3729cdf0e10cSrcweir 		pEffect->setEffectSequence( pNewSequence );
3730cdf0e10cSrcweir 		return true;
3731cdf0e10cSrcweir 	}
3732cdf0e10cSrcweir 	else
3733cdf0e10cSrcweir 	{
3734cdf0e10cSrcweir 		return false;
3735cdf0e10cSrcweir 	}
3736cdf0e10cSrcweir 
3737cdf0e10cSrcweir }
3738cdf0e10cSrcweir 
3739cdf0e10cSrcweir // --------------------------------------------------------------------
3740cdf0e10cSrcweir 
3741cdf0e10cSrcweir IMPL_LINK( MainSequence, onTimerHdl, Timer *, EMPTYARG )
3742cdf0e10cSrcweir {
3743cdf0e10cSrcweir 	if( mbTimerMode )
3744cdf0e10cSrcweir 	{
3745cdf0e10cSrcweir 		implRebuild();
3746cdf0e10cSrcweir 	}
3747cdf0e10cSrcweir 	else
3748cdf0e10cSrcweir 	{
3749cdf0e10cSrcweir 		reset();
3750cdf0e10cSrcweir 		createMainSequence();
3751cdf0e10cSrcweir 	}
3752cdf0e10cSrcweir 
3753cdf0e10cSrcweir 	return 0;
3754cdf0e10cSrcweir }
3755cdf0e10cSrcweir 
3756cdf0e10cSrcweir // --------------------------------------------------------------------
3757cdf0e10cSrcweir 
3758cdf0e10cSrcweir /** starts a timer that recreates the internal structure from the API core after 1 second */
3759cdf0e10cSrcweir void MainSequence::startRecreateTimer()
3760cdf0e10cSrcweir {
3761cdf0e10cSrcweir 	if( !mbRebuilding && (mbIgnoreChanges == 0) )
3762cdf0e10cSrcweir 	{
3763cdf0e10cSrcweir 		mbTimerMode = false;
3764cdf0e10cSrcweir 		maTimer.Start();
3765cdf0e10cSrcweir 	}
3766cdf0e10cSrcweir }
3767cdf0e10cSrcweir 
3768cdf0e10cSrcweir // --------------------------------------------------------------------
3769cdf0e10cSrcweir 
3770cdf0e10cSrcweir /** starts a timer that rebuilds the API core from the internal structure after 1 second */
3771cdf0e10cSrcweir void MainSequence::startRebuildTimer()
3772cdf0e10cSrcweir {
3773cdf0e10cSrcweir 	mbTimerMode = true;
3774cdf0e10cSrcweir 	maTimer.Start();
3775cdf0e10cSrcweir }
3776cdf0e10cSrcweir 
3777cdf0e10cSrcweir // ====================================================================
3778cdf0e10cSrcweir 
3779cdf0e10cSrcweir InteractiveSequence::InteractiveSequence( const Reference< XTimeContainer >& xSequenceRoot, MainSequence* pMainSequence )
3780cdf0e10cSrcweir : EffectSequenceHelper( xSequenceRoot ), mpMainSequence( pMainSequence )
3781cdf0e10cSrcweir {
3782cdf0e10cSrcweir 	mnSequenceType = EffectNodeType::INTERACTIVE_SEQUENCE;
3783cdf0e10cSrcweir 
3784cdf0e10cSrcweir 	try
3785cdf0e10cSrcweir 	{
3786cdf0e10cSrcweir 		if( mxSequenceRoot.is() )
3787cdf0e10cSrcweir 		{
3788cdf0e10cSrcweir 			Reference< XEnumerationAccess > xEnumerationAccess( mxSequenceRoot, UNO_QUERY_THROW );
3789cdf0e10cSrcweir 			Reference< XEnumeration > xEnumeration( xEnumerationAccess->createEnumeration(), UNO_QUERY_THROW );
3790cdf0e10cSrcweir 			while( !mxEventSource.is() && xEnumeration->hasMoreElements() )
3791cdf0e10cSrcweir 			{
3792cdf0e10cSrcweir 				Reference< XAnimationNode > xChildNode( xEnumeration->nextElement(), UNO_QUERY_THROW );
3793cdf0e10cSrcweir 
3794cdf0e10cSrcweir 				Event aEvent;
3795cdf0e10cSrcweir 				if( (xChildNode->getBegin() >>= aEvent) && (aEvent.Trigger == EventTrigger::ON_CLICK) )
3796cdf0e10cSrcweir 					aEvent.Source >>= mxEventSource;
3797cdf0e10cSrcweir 			}
3798cdf0e10cSrcweir 		}
3799cdf0e10cSrcweir 	}
3800cdf0e10cSrcweir 	catch( Exception& e )
3801cdf0e10cSrcweir 	{
3802cdf0e10cSrcweir 		(void)e;
3803cdf0e10cSrcweir 		DBG_ERROR( "sd::InteractiveSequence::InteractiveSequence(), exception cought!" );
3804cdf0e10cSrcweir 		return;
3805cdf0e10cSrcweir 	}
3806cdf0e10cSrcweir }
3807cdf0e10cSrcweir 
3808cdf0e10cSrcweir // --------------------------------------------------------------------
3809cdf0e10cSrcweir 
3810cdf0e10cSrcweir void InteractiveSequence::rebuild()
3811cdf0e10cSrcweir {
3812cdf0e10cSrcweir 	mpMainSequence->rebuild();
3813cdf0e10cSrcweir }
3814cdf0e10cSrcweir 
3815cdf0e10cSrcweir void InteractiveSequence::implRebuild()
3816cdf0e10cSrcweir {
3817cdf0e10cSrcweir 	EffectSequenceHelper::implRebuild();
3818cdf0e10cSrcweir }
3819cdf0e10cSrcweir 
3820cdf0e10cSrcweir // --------------------------------------------------------------------
3821cdf0e10cSrcweir 
3822cdf0e10cSrcweir MainSequenceRebuildGuard::MainSequenceRebuildGuard( const MainSequencePtr& pMainSequence )
3823cdf0e10cSrcweir : mpMainSequence( pMainSequence )
3824cdf0e10cSrcweir {
3825cdf0e10cSrcweir 	if( mpMainSequence.get() )
3826cdf0e10cSrcweir 		mpMainSequence->lockRebuilds();
3827cdf0e10cSrcweir }
3828cdf0e10cSrcweir 
3829cdf0e10cSrcweir MainSequenceRebuildGuard::~MainSequenceRebuildGuard()
3830cdf0e10cSrcweir {
3831cdf0e10cSrcweir 	if( mpMainSequence.get() )
3832cdf0e10cSrcweir 		mpMainSequence->unlockRebuilds();
3833cdf0e10cSrcweir }
3834cdf0e10cSrcweir 
3835cdf0e10cSrcweir 
3836cdf0e10cSrcweir }
3837