1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: CustomAnimationEffect.cxx,v $
10 * $Revision: 1.17.74.1 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sd.hxx"
33 #include <tools/debug.hxx>
34 #include <com/sun/star/util/XCloneable.hpp>
35 #include <com/sun/star/animations/AnimationFill.hpp>
36 #include <com/sun/star/container/XEnumerationAccess.hpp>
37 #include <com/sun/star/presentation/EffectNodeType.hpp>
38 #include <com/sun/star/presentation/EffectCommands.hpp>
39 #include <com/sun/star/presentation/EffectPresetClass.hpp>
40 #include <com/sun/star/presentation/ParagraphTarget.hpp>
41 #include <com/sun/star/lang/XInitialization.hpp>
42 #include <com/sun/star/presentation/ShapeAnimationSubType.hpp>
43 #include <com/sun/star/animations/AnimationNodeType.hpp>
44 #include <com/sun/star/animations/XCommand.hpp>
45 #include <com/sun/star/animations/AnimationTransformType.hpp>
46 #include <com/sun/star/animations/XIterateContainer.hpp>
47 #include <com/sun/star/animations/XAnimateTransform.hpp>
48 #include <com/sun/star/animations/Event.hpp>
49 #include <com/sun/star/animations/EventTrigger.hpp>
50 #include <com/sun/star/animations/Timing.hpp>
51 #include <com/sun/star/drawing/XDrawPage.hpp>
52 #include <com/sun/star/text/XText.hpp>
53 #include <com/sun/star/animations/XAnimate.hpp>
54 #include <com/sun/star/beans/NamedValue.hpp>
55 #include <com/sun/star/beans/XPropertySet.hpp>
56 #include <com/sun/star/util/XChangesNotifier.hpp>
57 #include <com/sun/star/animations/XAnimateMotion.hpp>
58 #include <comphelper/processfactory.hxx>
59 #include <comphelper/sequence.hxx>
60 #include <com/sun/star/lang/Locale.hpp>
61 #include <com/sun/star/i18n/XBreakIterator.hpp>
62 #include <com/sun/star/i18n/CharacterIteratorMode.hpp>
63 #ifndef _COM_SUN_STAR_TEXT_WORDTYPE_HPP_
64 #include <com/sun/star/i18n/WordType.hpp>
66 #include <com/sun/star/presentation/TextAnimationType.hpp>
68 #include <basegfx/polygon/b2dpolypolygon.hxx>
69 #include <basegfx/polygon/b2dpolypolygontools.hxx>
70 #include <basegfx/matrix/b2dhommatrix.hxx>
71 #include <basegfx/range/b2drange.hxx>
75 #include <cppuhelper/implbase1.hxx>
77 #include <svx/svdopath.hxx>
78 #include <svx/svdpage.hxx>
79 #include <svx/unoapi.hxx>
80 #include "CustomAnimationEffect.hxx"
81 #include <CustomAnimationPreset.hxx>
82 #include "animations.hxx"
84 using namespace ::com::sun::star
;
85 using namespace ::com::sun::star::presentation
;
86 using namespace ::com::sun::star::animations
;
88 using ::rtl::OUString
;
89 using ::com::sun::star::uno::Reference
;
90 using ::com::sun::star::uno::Sequence
;
91 using ::com::sun::star::uno::XInterface
;
92 using ::com::sun::star::uno::UNO_QUERY
;
93 using ::com::sun::star::uno::UNO_QUERY_THROW
;
94 using ::com::sun::star::uno::Any
;
95 using ::com::sun::star::uno::makeAny
;
96 using ::com::sun::star::uno::Exception
;
97 using ::com::sun::star::uno::RuntimeException
;
98 using ::com::sun::star::container::XEnumerationAccess
;
99 using ::com::sun::star::container::XEnumeration
;
100 using ::com::sun::star::beans::NamedValue
;
101 using ::com::sun::star::container::XChild
;
102 using ::com::sun::star::container::XElementAccess
;
103 using ::com::sun::star::drawing::XShape
;
104 using ::com::sun::star::lang::XInitialization
;
105 using ::com::sun::star::drawing::XShapes
;
106 using ::com::sun::star::drawing::XDrawPage
;
107 using ::com::sun::star::text::XText
;
108 using ::com::sun::star::text::XTextRange
;
109 using ::com::sun::star::beans::XPropertySet
;
110 using ::com::sun::star::lang::XMultiServiceFactory
;
111 using ::com::sun::star::util::XCloneable
;
112 using ::com::sun::star::lang::Locale
;
113 using ::com::sun::star::util::XChangesNotifier
;
114 using ::com::sun::star::util::XChangesListener
;
118 class MainSequenceChangeGuard
121 MainSequenceChangeGuard( EffectSequenceHelper
* pSequence
)
123 mpMainSequence
= dynamic_cast< MainSequence
* >( pSequence
);
124 if( mpMainSequence
== 0 )
126 InteractiveSequence
* pI
= dynamic_cast< InteractiveSequence
* >( pSequence
);
128 mpMainSequence
= pI
->mpMainSequence
;
130 DBG_ASSERT( mpMainSequence
, "sd::MainSequenceChangeGuard::MainSequenceChangeGuard(), no main sequence to guard!" );
133 mpMainSequence
->mbIgnoreChanges
++;
136 ~MainSequenceChangeGuard()
139 mpMainSequence
->mbIgnoreChanges
++;
143 MainSequence
* mpMainSequence
;
146 CustomAnimationEffect::CustomAnimationEffect( const ::com::sun::star::uno::Reference
< ::com::sun::star::animations::XAnimationNode
>& xNode
)
151 mfAbsoluteDuration(-1.0),
154 mfIterateInterval(0.0),
156 mbHasText(sal_False
),
157 mfAcceleration( 1.0 ),
159 mbAutoReverse(false),
162 mpEffectSequence( 0 ),
163 mbHasAfterEffect(false),
164 mbAfterEffectOnNextEffect(false)
169 // --------------------------------------------------------------------
171 void CustomAnimationEffect::setNode( const ::com::sun::star::uno::Reference
< ::com::sun::star::animations::XAnimationNode
>& xNode
)
176 Sequence
< NamedValue
> aUserData( mxNode
->getUserData() );
177 sal_Int32 nLength
= aUserData
.getLength();
178 const NamedValue
* p
= aUserData
.getConstArray();
182 if( p
->Name
.equalsAscii( "node-type" ) )
184 p
->Value
>>= mnNodeType
;
186 else if( p
->Name
.equalsAscii( "preset-id" ) )
188 p
->Value
>>= maPresetId
;
190 else if( p
->Name
.equalsAscii( "preset-sub-type" ) )
192 p
->Value
>>= maPresetSubType
;
194 else if( p
->Name
.equalsAscii( "preset-class" ) )
196 p
->Value
>>= mnPresetClass
;
198 else if( p
->Name
.equalsAscii( "preset-property" ) )
200 p
->Value
>>= maProperty
;
202 else if( p
->Name
.equalsAscii( "group-id" ) )
204 p
->Value
>>= mnGroupId
;
210 // get effect start time
211 mxNode
->getBegin() >>= mfBegin
;
213 mfAcceleration
= mxNode
->getAcceleration();
214 mfDecelerate
= mxNode
->getDecelerate();
215 mbAutoReverse
= mxNode
->getAutoReverse();
217 // get iteration data
218 Reference
< XIterateContainer
> xIter( mxNode
, UNO_QUERY
);
221 mfIterateInterval
= xIter
->getIterateInterval();
222 mnIterateType
= xIter
->getIterateType();
223 maTarget
= xIter
->getTarget();
224 mnTargetSubItem
= xIter
->getSubItem();
228 mfIterateInterval
= 0.0f
;
232 // calculate effect duration and get target shape
233 Reference
< XEnumerationAccess
> xEnumerationAccess( mxNode
, UNO_QUERY
);
234 if( xEnumerationAccess
.is() )
236 Reference
< XEnumeration
> xEnumeration( xEnumerationAccess
->createEnumeration(), UNO_QUERY
);
237 if( xEnumeration
.is() )
239 while( xEnumeration
->hasMoreElements() )
241 Reference
< XAnimationNode
> xChildNode( xEnumeration
->nextElement(), UNO_QUERY
);
242 if( !xChildNode
.is() )
245 if( xChildNode
->getType() == AnimationNodeType::AUDIO
)
247 mxAudio
.set( xChildNode
, UNO_QUERY
);
249 else if( xChildNode
->getType() == AnimationNodeType::COMMAND
)
251 Reference
< XCommand
> xCommand( xChildNode
, UNO_QUERY
);
254 mnCommand
= xCommand
->getCommand();
255 if( !maTarget
.hasValue() )
256 maTarget
= xCommand
->getTarget();
262 double fDuration
= 0.0;
263 xChildNode
->getBegin() >>= fBegin
;
264 xChildNode
->getDuration() >>= fDuration
;
267 if( fDuration
> mfDuration
)
268 mfDuration
= fDuration
;
270 // no target shape yet?
271 if( !maTarget
.hasValue() )
274 Reference
< XAnimate
> xAnimate( xChildNode
, UNO_QUERY
);
277 maTarget
= xAnimate
->getTarget();
278 mnTargetSubItem
= xAnimate
->getSubItem();
286 mfAbsoluteDuration
= mfDuration
;
290 // --------------------------------------------------------------------
292 sal_Int32
CustomAnimationEffect::getNumberOfSubitems( const Any
& aTarget
, sal_Int16 nIterateType
)
294 sal_Int32 nSubItems
= 0;
298 // first get target text
299 sal_Int32 nOnlyPara
= -1;
301 Reference
< XText
> xShape
;
305 ParagraphTarget aParaTarget
;
306 if( aTarget
>>= aParaTarget
)
308 xShape
.set( aParaTarget
.Shape
, UNO_QUERY
);
309 nOnlyPara
= aParaTarget
.Paragraph
;
313 // now use the break iterator to iterate over the given text
314 // and count the sub items
318 // TODO/LATER: Optimize this, don't create a break iterator each time
319 Reference
< lang::XMultiServiceFactory
> xMSF( ::comphelper::getProcessServiceFactory() );
320 Reference
< i18n::XBreakIterator
> xBI( xMSF
->createInstance( OUString::createFromAscii( "com.sun.star.i18n.BreakIterator" ) ), UNO_QUERY
);
321 DBG_ASSERT( xBI
.is(), "sd::CustomAnimationEffect::getNumberOfSubitems(), could not create a 'com.sun.star.i18n.BreakIterator'!" );
325 Reference
< XEnumerationAccess
> xEA( xShape
, UNO_QUERY_THROW
);
326 Reference
< XEnumeration
> xEnumeration( xEA
->createEnumeration(), UNO_QUERY_THROW
);
328 const OUString
aStrLocaleName( RTL_CONSTASCII_USTRINGPARAM("CharLocale") );
329 Reference
< XTextRange
> xParagraph
;
332 while( xEnumeration
->hasMoreElements() )
334 xEnumeration
->nextElement() >>= xParagraph
;
336 // skip this if its not the only paragraph we want to count
337 if( (nOnlyPara
!= -1) && (nOnlyPara
!= nPara
) )
340 if( nIterateType
== TextAnimationType::BY_PARAGRAPH
)
346 const OUString
aText( xParagraph
->getString() );
347 Reference
< XPropertySet
> xSet( xParagraph
, UNO_QUERY_THROW
);
348 xSet
->getPropertyValue( aStrLocaleName
) >>= aLocale
;
351 const sal_Int32 nEndPos
= aText
.getLength();
353 if( nIterateType
== TextAnimationType::BY_WORD
)
355 for( nPos
= 0; nPos
< nEndPos
; nPos
++ )
357 nPos
= xBI
->getWordBoundary(aText
, nPos
, aLocale
, i18n::WordType::ANY_WORD
, sal_True
).endPos
;
365 for( nPos
= 0; nPos
< nEndPos
; nPos
++ )
367 nPos
= xBI
->nextCharacters(aText
, nPos
, aLocale
, i18n::CharacterIteratorMode::SKIPCELL
, 0, nDone
);
373 if( nPara
== nOnlyPara
)
381 catch( Exception
& e
)
385 DBG_ERROR( "sd::CustomAnimationEffect::getNumberOfSubitems(), exception cought!" );
391 // --------------------------------------------------------------------
393 CustomAnimationEffect::~CustomAnimationEffect()
397 // --------------------------------------------------------------------
399 CustomAnimationEffectPtr
CustomAnimationEffect::clone() const
401 Reference
< XCloneable
> xCloneable( mxNode
, UNO_QUERY_THROW
);
402 Reference
< XAnimationNode
> xNode( xCloneable
->createClone(), UNO_QUERY_THROW
);
403 CustomAnimationEffectPtr
pEffect( new CustomAnimationEffect( xNode
) );
404 pEffect
->setEffectSequence( getEffectSequence() );
408 // --------------------------------------------------------------------
410 sal_Int32
CustomAnimationEffect::get_node_type( const Reference
< XAnimationNode
>& xNode
)
412 sal_Int16 nNodeType
= -1;
416 Sequence
< NamedValue
> aUserData( xNode
->getUserData() );
417 sal_Int32 nLength
= aUserData
.getLength();
420 const NamedValue
* p
= aUserData
.getConstArray();
423 if( p
->Name
.equalsAscii( "node-type" ) )
425 p
->Value
>>= nNodeType
;
436 // --------------------------------------------------------------------
438 void CustomAnimationEffect::setPresetClass( sal_Int16 nPresetClass
)
440 if( mnPresetClass
!= nPresetClass
)
442 mnPresetClass
= nPresetClass
;
445 // first try to find a "preset-class" entry in the user data
447 Sequence
< NamedValue
> aUserData( mxNode
->getUserData() );
448 sal_Int32 nLength
= aUserData
.getLength();
452 NamedValue
* p
= aUserData
.getArray();
455 if( p
->Name
.equalsAscii( "preset-class" ) )
457 p
->Value
<<= mnPresetClass
;
465 // no "node-type" entry inside user data, so add it
468 nLength
= aUserData
.getLength();
469 aUserData
.realloc( nLength
+ 1);
470 aUserData
[nLength
].Name
= OUString( RTL_CONSTASCII_USTRINGPARAM( "preset-class" ) );
471 aUserData
[nLength
].Value
<<= mnPresetClass
;
474 mxNode
->setUserData( aUserData
);
479 void CustomAnimationEffect::setNodeType( sal_Int16 nNodeType
)
481 if( mnNodeType
!= nNodeType
)
483 mnNodeType
= nNodeType
;
486 // first try to find a "node-type" entry in the user data
488 Sequence
< NamedValue
> aUserData( mxNode
->getUserData() );
489 sal_Int32 nLength
= aUserData
.getLength();
493 NamedValue
* p
= aUserData
.getArray();
496 if( p
->Name
.equalsAscii( "node-type" ) )
498 p
->Value
<<= mnNodeType
;
506 // no "node-type" entry inside user data, so add it
509 nLength
= aUserData
.getLength();
510 aUserData
.realloc( nLength
+ 1);
511 aUserData
[nLength
].Name
= OUString( RTL_CONSTASCII_USTRINGPARAM( "node-type" ) );
512 aUserData
[nLength
].Value
<<= mnNodeType
;
515 mxNode
->setUserData( aUserData
);
520 // --------------------------------------------------------------------
522 void CustomAnimationEffect::setGroupId( sal_Int32 nGroupId
)
524 mnGroupId
= nGroupId
;
527 // first try to find a "group-id" entry in the user data
529 Sequence
< NamedValue
> aUserData( mxNode
->getUserData() );
530 sal_Int32 nLength
= aUserData
.getLength();
534 NamedValue
* p
= aUserData
.getArray();
537 if( p
->Name
.equalsAscii( "group-id" ) )
539 p
->Value
<<= mnGroupId
;
547 // no "node-type" entry inside user data, so add it
550 nLength
= aUserData
.getLength();
551 aUserData
.realloc( nLength
+ 1);
552 aUserData
[nLength
].Name
= OUString( RTL_CONSTASCII_USTRINGPARAM( "group-id" ) );
553 aUserData
[nLength
].Value
<<= mnGroupId
;
556 mxNode
->setUserData( aUserData
);
560 // --------------------------------------------------------------------
562 /** checks if the text for this effect has changed and updates internal flags.
563 returns true if something changed.
565 bool CustomAnimationEffect::checkForText()
567 bool bChange
= false;
569 Reference
< XText
> xText
;
571 if( maTarget
.getValueType() == ::getCppuType((const ParagraphTarget
*)0) )
574 ParagraphTarget aParaTarget
;
575 maTarget
>>= aParaTarget
;
577 xText
= Reference
< XText
>::query( aParaTarget
.Shape
);
582 Reference
< XEnumerationAccess
> xEA( xText
, UNO_QUERY
);
585 Reference
< XEnumeration
> xEnumeration( xEA
->createEnumeration(), UNO_QUERY
);
586 if( xEnumeration
.is() )
588 sal_Bool bHasText
= xEnumeration
->hasMoreElements();
589 bChange
|= bHasText
!= mbHasText
;
590 mbHasText
= bHasText
;
592 sal_Int32 nPara
= aParaTarget
.Paragraph
;
594 while( xEnumeration
->hasMoreElements() && nPara
-- )
595 xEnumeration
->nextElement();
597 if( xEnumeration
->hasMoreElements() )
599 Reference
< XPropertySet
> xParaSet
;
600 xEnumeration
->nextElement() >>= xParaSet
;
603 sal_Int32 nParaDepth
= 0;
604 const OUString
strNumberingLevel( RTL_CONSTASCII_USTRINGPARAM("NumberingLevel") );
605 xParaSet
->getPropertyValue( strNumberingLevel
) >>= nParaDepth
;
606 bChange
|= nParaDepth
!= mnParaDepth
;
607 mnParaDepth
= nParaDepth
;
617 sal_Bool bHasText
= xText
.is() && xText
->getString().getLength();
618 bChange
|= bHasText
!= mbHasText
;
619 mbHasText
= bHasText
;
622 bChange
|= calculateIterateDuration();
626 bool CustomAnimationEffect::calculateIterateDuration()
628 bool bChange
= false;
630 // if we have an iteration, we must also calculate the
631 // 'true' container duration, that is
632 // ( ( is form animated ) ? [contained effects duration] : 0 ) +
633 // ( [number of animated children] - 1 ) * [interval-delay] + [contained effects duration]
634 Reference
< XIterateContainer
> xIter( mxNode
, UNO_QUERY
);
637 double fDuration
= mfDuration
;
638 const double fSubEffectDuration
= mfDuration
;
640 if( mnTargetSubItem
!= ShapeAnimationSubType::ONLY_BACKGROUND
) // does not make sense for iterate container but better check
642 const sal_Int32 nSubItems
= getNumberOfSubitems( maTarget
, mnIterateType
);
645 const double f
= (nSubItems
-1) * mfIterateInterval
;
650 // if we also animate the form first, we have to add the
651 // sub effect duration to the whole effect duration
652 if( mnTargetSubItem
== ShapeAnimationSubType::AS_WHOLE
)
653 fDuration
+= fSubEffectDuration
;
655 bChange
|= fDuration
!= mfAbsoluteDuration
;
656 mfAbsoluteDuration
= fDuration
;
662 // --------------------------------------------------------------------
664 void CustomAnimationEffect::setTarget( const ::com::sun::star::uno::Any
& rTarget
)
670 // first, check special case for random node
671 Reference
< XInitialization
> xInit( mxNode
, UNO_QUERY
);
674 const Sequence
< Any
> aArgs( &maTarget
, 1 );
675 xInit
->initialize( aArgs
);
679 Reference
< XIterateContainer
> xIter( mxNode
, UNO_QUERY
);
682 xIter
->setTarget(maTarget
);
686 Reference
< XEnumerationAccess
> xEnumerationAccess( mxNode
, UNO_QUERY
);
687 if( xEnumerationAccess
.is() )
689 Reference
< XEnumeration
> xEnumeration( xEnumerationAccess
->createEnumeration(), UNO_QUERY
);
690 if( xEnumeration
.is() )
692 while( xEnumeration
->hasMoreElements() )
694 const Any
aElem( xEnumeration
->nextElement() );
695 Reference
< XAnimate
> xAnimate( aElem
, UNO_QUERY
);
697 xAnimate
->setTarget( rTarget
);
700 Reference
< XCommand
> xCommand( aElem
, UNO_QUERY
);
702 xCommand
->setTarget( rTarget
);
713 DBG_ERROR( "sd::CustomAnimationEffect::setTarget(), exception cought!" );
717 // --------------------------------------------------------------------
719 void CustomAnimationEffect::setTargetSubItem( sal_Int16 nSubItem
)
723 mnTargetSubItem
= nSubItem
;
725 Reference
< XIterateContainer
> xIter( mxNode
, UNO_QUERY
);
728 xIter
->setSubItem(mnTargetSubItem
);
732 Reference
< XEnumerationAccess
> xEnumerationAccess( mxNode
, UNO_QUERY
);
733 if( xEnumerationAccess
.is() )
735 Reference
< XEnumeration
> xEnumeration( xEnumerationAccess
->createEnumeration(), UNO_QUERY
);
736 if( xEnumeration
.is() )
738 while( xEnumeration
->hasMoreElements() )
740 Reference
< XAnimate
> xAnimate( xEnumeration
->nextElement(), UNO_QUERY
);
742 xAnimate
->setSubItem( mnTargetSubItem
);
750 DBG_ERROR( "sd::CustomAnimationEffect::setTargetSubItem(), exception cought!" );
754 // --------------------------------------------------------------------
756 void CustomAnimationEffect::setDuration( double fDuration
)
758 if( (mfDuration
!= -1.0) && (mfDuration
!= fDuration
) ) try
760 double fScale
= fDuration
/ mfDuration
;
761 mfDuration
= fDuration
;
762 mfAbsoluteDuration
= mfDuration
;
764 // calculate effect duration and get target shape
765 Reference
< XEnumerationAccess
> xEnumerationAccess( mxNode
, UNO_QUERY
);
766 if( xEnumerationAccess
.is() )
768 Reference
< XEnumeration
> xEnumeration( xEnumerationAccess
->createEnumeration(), UNO_QUERY
);
769 if( xEnumeration
.is() )
771 while( xEnumeration
->hasMoreElements() )
773 Reference
< XAnimationNode
> xChildNode( xEnumeration
->nextElement(), UNO_QUERY
);
774 if( !xChildNode
.is() )
778 double fChildBegin
= 0.0;
779 xChildNode
->getBegin() >>= fChildBegin
;
780 if( fChildBegin
!= 0.0 )
782 fChildBegin
*= fScale
;
783 xChildNode
->setBegin( makeAny( fChildBegin
) );
786 double fChildDuration
= 0.0;
787 xChildNode
->getDuration() >>= fChildDuration
;
788 if( fChildDuration
!= 0.0 )
790 fChildDuration
*= fScale
;
791 xChildNode
->setDuration( makeAny( fChildDuration
) );
796 calculateIterateDuration();
800 DBG_ERROR( "sd::CustomAnimationEffect::setDuration(), exception cought!" );
804 // --------------------------------------------------------------------
806 void CustomAnimationEffect::setBegin( double fBegin
)
808 if( mxNode
.is() ) try
811 mxNode
->setBegin( makeAny( fBegin
) );
815 DBG_ERROR( "sd::CustomAnimationEffect::setBegin(), exception cought!" );
819 // --------------------------------------------------------------------
821 void CustomAnimationEffect::setAcceleration( double fAcceleration
)
823 if( mxNode
.is() ) try
825 mfAcceleration
= fAcceleration
;
826 mxNode
->setAcceleration( fAcceleration
);
830 DBG_ERROR( "sd::CustomAnimationEffect::setAcceleration(), exception cought!" );
833 // --------------------------------------------------------------------
835 void CustomAnimationEffect::setDecelerate( double fDecelerate
)
837 if( mxNode
.is() ) try
839 mfDecelerate
= fDecelerate
;
840 mxNode
->setDecelerate( fDecelerate
);
844 DBG_ERROR( "sd::CustomAnimationEffect::setDecelerate(), exception cought!" );
848 // --------------------------------------------------------------------
850 void CustomAnimationEffect::setAutoReverse( sal_Bool bAutoReverse
)
852 if( mxNode
.is() ) try
854 mbAutoReverse
= bAutoReverse
;
855 mxNode
->setAutoReverse( bAutoReverse
);
859 DBG_ERROR( "sd::CustomAnimationEffect::setAutoReverse(), exception cought!" );
863 // --------------------------------------------------------------------
865 void CustomAnimationEffect::replaceNode( const ::com::sun::star::uno::Reference
< ::com::sun::star::animations::XAnimationNode
>& xNode
)
867 sal_Int16 nNodeType
= mnNodeType
;
868 Any aTarget
= maTarget
;
870 double fBegin
= mfBegin
;
871 double fDuration
= mfDuration
;
872 double fAcceleration
= mfAcceleration
;
873 double fDecelerate
= mfDecelerate
;
874 sal_Bool bAutoReverse
= mbAutoReverse
;
875 Reference
< XAudio
> xAudio( mxAudio
);
876 sal_Int16 nIterateType
= mnIterateType
;
877 double fIterateInterval
= mfIterateInterval
;
878 sal_Int16 nSubItem
= mnTargetSubItem
;
883 setNodeType( nNodeType
);
884 setTarget( aTarget
);
885 setTargetSubItem( nSubItem
);
886 setDuration( fDuration
);
889 setAcceleration( fAcceleration
);
890 setDecelerate( fDecelerate
);
891 setAutoReverse( bAutoReverse
);
893 if( nIterateType
!= mnIterateType
)
894 setIterateType( nIterateType
);
896 if( mnIterateType
&& ( fIterateInterval
!= mfIterateInterval
) )
897 setIterateInterval( fIterateInterval
);
900 // --------------------------------------------------------------------
902 Reference
< XShape
> CustomAnimationEffect::getTargetShape() const
904 Reference
< XShape
> xShape
;
908 ParagraphTarget aParaTarget
;
909 if( maTarget
>>= aParaTarget
)
910 xShape
= aParaTarget
.Shape
;
916 // --------------------------------------------------------------------
918 Any
CustomAnimationEffect::getRepeatCount() const
922 return mxNode
->getRepeatCount();
931 // --------------------------------------------------------------------
933 Any
CustomAnimationEffect::getEnd() const
937 return mxNode
->getEnd();
946 // --------------------------------------------------------------------
948 sal_Int16
CustomAnimationEffect::getFill() const
951 return mxNode
->getFill();
956 // --------------------------------------------------------------------
958 void CustomAnimationEffect::setRepeatCount( const Any
& rRepeatCount
)
961 mxNode
->setRepeatCount( rRepeatCount
);
964 // --------------------------------------------------------------------
966 void CustomAnimationEffect::setEnd( const Any
& rEnd
)
969 mxNode
->setEnd( rEnd
);
972 // --------------------------------------------------------------------
974 void CustomAnimationEffect::setFill( sal_Int16 nFill
)
977 mxNode
->setFill( nFill
);
980 // --------------------------------------------------------------------
982 Reference
< XAnimationNode
> CustomAnimationEffect::createAfterEffectNode() const throw (Exception
)
984 DBG_ASSERT( mbHasAfterEffect
, "sd::CustomAnimationEffect::createAfterEffectNode(), this node has no after effect!" );
986 Reference
< XMultiServiceFactory
> xMsf( ::comphelper::getProcessServiceFactory() );
988 const char* pServiceName
= maDimColor
.hasValue() ?
989 "com.sun.star.animations.AnimateColor" : "com.sun.star.animations.AnimateSet";
991 Reference
< XAnimate
> xAnimate( xMsf
->createInstance(OUString::createFromAscii(pServiceName
) ), UNO_QUERY_THROW
);
994 OUString aAttributeName
;
996 if( maDimColor
.hasValue() )
999 aAttributeName
= OUString( RTL_CONSTASCII_USTRINGPARAM( "DimColor" ) );
1003 aTo
= makeAny( (sal_Bool
)sal_False
);
1004 aAttributeName
= OUString( RTL_CONSTASCII_USTRINGPARAM( "Visibility" ) );
1008 if( !mbAfterEffectOnNextEffect
) // sameClick
1012 aEvent
.Source
<<= getNode();
1013 aEvent
.Trigger
= EventTrigger::END_EVENT
;
1020 aBegin
<<= (double)0.0;
1023 xAnimate
->setBegin( aBegin
);
1024 xAnimate
->setTo( aTo
);
1025 xAnimate
->setAttributeName( aAttributeName
);
1027 xAnimate
->setDuration( makeAny( (double)0.001 ) );
1028 xAnimate
->setFill( AnimationFill::HOLD
);
1029 xAnimate
->setTarget( maTarget
);
1031 return Reference
< XAnimationNode
>( xAnimate
, UNO_QUERY_THROW
);
1034 // --------------------------------------------------------------------
1036 void CustomAnimationEffect::setIterateType( sal_Int16 nIterateType
)
1038 if( mnIterateType
!= nIterateType
) try
1040 // do we need to exchange the container node?
1041 if( (mnIterateType
== 0) || (nIterateType
== 0) )
1043 sal_Int16 nTargetSubItem
= mnTargetSubItem
;
1045 Reference
< XMultiServiceFactory
> xMsf( ::comphelper::getProcessServiceFactory() );
1046 const char * pServiceName
=
1047 nIterateType
? "com.sun.star.animations.IterateContainer" : "com.sun.star.animations.ParallelTimeContainer";
1048 Reference
< XTimeContainer
> xNewContainer(
1049 xMsf
->createInstance( OUString::createFromAscii(pServiceName
) ), UNO_QUERY_THROW
);
1051 Reference
< XTimeContainer
> xOldContainer( mxNode
, UNO_QUERY_THROW
);
1052 Reference
< XEnumerationAccess
> xEnumerationAccess( mxNode
, UNO_QUERY_THROW
);
1053 Reference
< XEnumeration
> xEnumeration( xEnumerationAccess
->createEnumeration(), UNO_QUERY_THROW
);
1054 while( xEnumeration
->hasMoreElements() )
1056 Reference
< XAnimationNode
> xChildNode( xEnumeration
->nextElement(), UNO_QUERY_THROW
);
1057 xOldContainer
->removeChild( xChildNode
);
1058 xNewContainer
->appendChild( xChildNode
);
1061 Reference
< XAnimationNode
> xNewNode( xNewContainer
, UNO_QUERY_THROW
);
1063 xNewNode
->setBegin( mxNode
->getBegin() );
1064 xNewNode
->setDuration( mxNode
->getDuration() );
1065 xNewNode
->setEnd( mxNode
->getEnd() );
1066 xNewNode
->setEndSync( mxNode
->getEndSync() );
1067 xNewNode
->setRepeatCount( mxNode
->getRepeatCount() );
1068 xNewNode
->setFill( mxNode
->getFill() );
1069 xNewNode
->setFillDefault( mxNode
->getFillDefault() );
1070 xNewNode
->setRestart( mxNode
->getRestart() );
1071 xNewNode
->setRestartDefault( mxNode
->getRestartDefault() );
1072 xNewNode
->setAcceleration( mxNode
->getAcceleration() );
1073 xNewNode
->setDecelerate( mxNode
->getDecelerate() );
1074 xNewNode
->setAutoReverse( mxNode
->getAutoReverse() );
1075 xNewNode
->setRepeatDuration( mxNode
->getRepeatDuration() );
1076 xNewNode
->setEndSync( mxNode
->getEndSync() );
1077 xNewNode
->setRepeatCount( mxNode
->getRepeatCount() );
1078 xNewNode
->setUserData( mxNode
->getUserData() );
1085 Reference
< XIterateContainer
> xIter( mxNode
, UNO_QUERY_THROW
);
1086 xIter
->setTarget(maTarget
);
1087 xIter
->setSubItem( nTargetSubItem
);
1094 Reference
< XEnumerationAccess
> xEA( mxNode
, UNO_QUERY_THROW
);
1095 Reference
< XEnumeration
> xE( xEA
->createEnumeration(), UNO_QUERY_THROW
);
1096 while( xE
->hasMoreElements() )
1098 Reference
< XAnimate
> xAnimate( xE
->nextElement(), UNO_QUERY
);
1101 xAnimate
->setTarget( aTarget
);
1102 xAnimate
->setSubItem( nTargetSubItem
);
1107 mnIterateType
= nIterateType
;
1109 // if we have an iteration container, we must set its type
1112 Reference
< XIterateContainer
> xIter( mxNode
, UNO_QUERY_THROW
);
1113 xIter
->setIterateType( nIterateType
);
1118 catch( Exception
& e
)
1121 DBG_ERROR( "sd::CustomAnimationEffect::setIterateType(), Exception cought!" );
1125 // --------------------------------------------------------------------
1127 void CustomAnimationEffect::setIterateInterval( double fIterateInterval
)
1129 if( mfIterateInterval
!= fIterateInterval
)
1131 Reference
< XIterateContainer
> xIter( mxNode
, UNO_QUERY
);
1133 DBG_ASSERT( xIter
.is(), "sd::CustomAnimationEffect::setIterateInterval(), not an iteration node" );
1136 mfIterateInterval
= fIterateInterval
;
1137 xIter
->setIterateInterval( fIterateInterval
);
1140 calculateIterateDuration();
1144 // --------------------------------------------------------------------
1146 ::rtl::OUString
CustomAnimationEffect::getPath() const
1148 ::rtl::OUString aPath
;
1150 if( mxNode
.is() ) try
1152 Reference
< XEnumerationAccess
> xEnumerationAccess( mxNode
, UNO_QUERY_THROW
);
1153 Reference
< XEnumeration
> xEnumeration( xEnumerationAccess
->createEnumeration(), UNO_QUERY_THROW
);
1154 while( xEnumeration
->hasMoreElements() )
1156 Reference
< XAnimateMotion
> xMotion( xEnumeration
->nextElement(), UNO_QUERY
);
1159 xMotion
->getPath() >>= aPath
;
1164 catch( Exception
& e
)
1167 DBG_ERROR("sd::CustomAnimationEffect::getPath(), exception cought!" );
1173 // --------------------------------------------------------------------
1175 void CustomAnimationEffect::setPath( const ::rtl::OUString
& rPath
)
1177 if( mxNode
.is() ) try
1179 Reference
< XEnumerationAccess
> xEnumerationAccess( mxNode
, UNO_QUERY_THROW
);
1180 Reference
< XEnumeration
> xEnumeration( xEnumerationAccess
->createEnumeration(), UNO_QUERY_THROW
);
1181 while( xEnumeration
->hasMoreElements() )
1183 Reference
< XAnimateMotion
> xMotion( xEnumeration
->nextElement(), UNO_QUERY
);
1187 MainSequenceChangeGuard
aGuard( mpEffectSequence
);
1188 xMotion
->setPath( Any( rPath
) );
1193 catch( Exception
& e
)
1196 DBG_ERROR("sd::CustomAnimationEffect::setPath(), exception cought!" );
1200 // --------------------------------------------------------------------
1202 Any
CustomAnimationEffect::getProperty( sal_Int32 nNodeType
, const OUString
& rAttributeName
, EValue eValue
)
1205 if( mxNode
.is() ) try
1207 Reference
< XEnumerationAccess
> xEnumerationAccess( mxNode
, UNO_QUERY
);
1208 if( xEnumerationAccess
.is() )
1210 Reference
< XEnumeration
> xEnumeration( xEnumerationAccess
->createEnumeration(), UNO_QUERY
);
1211 if( xEnumeration
.is() )
1213 while( xEnumeration
->hasMoreElements() && !aProperty
.hasValue() )
1215 Reference
< XAnimate
> xAnimate( xEnumeration
->nextElement(), UNO_QUERY
);
1216 if( !xAnimate
.is() )
1219 if( xAnimate
->getType() == nNodeType
)
1221 if( xAnimate
->getAttributeName() == rAttributeName
)
1225 case VALUE_FROM
: aProperty
= xAnimate
->getFrom(); break;
1226 case VALUE_TO
: aProperty
= xAnimate
->getTo(); break;
1227 case VALUE_BY
: aProperty
= xAnimate
->getBy(); break;
1231 Sequence
<Any
> aValues( xAnimate
->getValues() );
1232 if( aValues
.hasElements() )
1233 aProperty
= aValues
[ eValue
== VALUE_FIRST
? 0 : aValues
.getLength() - 1 ];
1243 catch( Exception
& e
)
1246 DBG_ERROR("sd::CustomAnimationEffect::getProperty(), exception cought!" );
1252 // --------------------------------------------------------------------
1254 bool CustomAnimationEffect::setProperty( sal_Int32 nNodeType
, const OUString
& rAttributeName
, EValue eValue
, const Any
& rValue
)
1256 bool bChanged
= false;
1257 if( mxNode
.is() ) try
1259 Reference
< XEnumerationAccess
> xEnumerationAccess( mxNode
, UNO_QUERY
);
1260 if( xEnumerationAccess
.is() )
1262 Reference
< XEnumeration
> xEnumeration( xEnumerationAccess
->createEnumeration(), UNO_QUERY
);
1263 if( xEnumeration
.is() )
1265 while( xEnumeration
->hasMoreElements() )
1267 Reference
< XAnimate
> xAnimate( xEnumeration
->nextElement(), UNO_QUERY
);
1268 if( !xAnimate
.is() )
1271 if( xAnimate
->getType() == nNodeType
)
1273 if( xAnimate
->getAttributeName() == rAttributeName
)
1278 if( xAnimate
->getFrom() != rValue
)
1280 xAnimate
->setFrom( rValue
);
1285 if( xAnimate
->getTo() != rValue
)
1287 xAnimate
->setTo( rValue
);
1292 if( xAnimate
->getTo() != rValue
)
1294 xAnimate
->setBy( rValue
);
1301 Sequence
<Any
> aValues( xAnimate
->getValues() );
1302 if( !aValues
.hasElements() )
1305 sal_Int32 nIndex
= eValue
== VALUE_FIRST
? 0 : aValues
.getLength() - 1;
1307 if( aValues
[ nIndex
] != rValue
)
1309 aValues
[ nIndex
] = rValue
;
1310 xAnimate
->setValues( aValues
);
1321 catch( Exception
& e
)
1324 DBG_ERROR("sd::CustomAnimationEffect::setProperty(), exception cought!" );
1330 // --------------------------------------------------------------------
1332 static bool implIsColorAttribute( const OUString
& rAttributeName
)
1334 return rAttributeName
.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("FillColor") ) ||
1335 rAttributeName
.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("LineColor") ) ||
1336 rAttributeName
.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("CharColor") );
1339 // --------------------------------------------------------------------
1341 Any
CustomAnimationEffect::getColor( sal_Int32 nIndex
)
1344 if( mxNode
.is() ) try
1346 Reference
< XEnumerationAccess
> xEnumerationAccess( mxNode
, UNO_QUERY
);
1347 if( xEnumerationAccess
.is() )
1349 Reference
< XEnumeration
> xEnumeration( xEnumerationAccess
->createEnumeration(), UNO_QUERY
);
1350 if( xEnumeration
.is() )
1352 while( xEnumeration
->hasMoreElements() && !aColor
.hasValue() )
1354 Reference
< XAnimate
> xAnimate( xEnumeration
->nextElement(), UNO_QUERY
);
1355 if( !xAnimate
.is() )
1358 switch( xAnimate
->getType() )
1360 case AnimationNodeType::SET
:
1361 case AnimationNodeType::ANIMATE
:
1362 if( !implIsColorAttribute( xAnimate
->getAttributeName() ) )
1364 case AnimationNodeType::ANIMATECOLOR
:
1365 Sequence
<Any
> aValues( xAnimate
->getValues() );
1366 if( aValues
.hasElements() )
1368 if( aValues
.getLength() > nIndex
)
1369 aColor
= aValues
[nIndex
];
1371 else if( nIndex
== 0 )
1372 aColor
= xAnimate
->getFrom();
1374 aColor
= xAnimate
->getTo();
1380 catch( Exception
& e
)
1383 DBG_ERROR("sd::CustomAnimationEffect::getColor(), exception cought!" );
1389 // --------------------------------------------------------------------
1391 void CustomAnimationEffect::setColor( sal_Int32 nIndex
, const Any
& rColor
)
1393 if( mxNode
.is() ) try
1395 Reference
< XEnumerationAccess
> xEnumerationAccess( mxNode
, UNO_QUERY
);
1396 if( xEnumerationAccess
.is() )
1398 Reference
< XEnumeration
> xEnumeration( xEnumerationAccess
->createEnumeration(), UNO_QUERY
);
1399 if( xEnumeration
.is() )
1401 while( xEnumeration
->hasMoreElements() )
1403 Reference
< XAnimate
> xAnimate( xEnumeration
->nextElement(), UNO_QUERY
);
1404 if( !xAnimate
.is() )
1407 switch( xAnimate
->getType() )
1409 case AnimationNodeType::SET
:
1410 case AnimationNodeType::ANIMATE
:
1411 if( !implIsColorAttribute( xAnimate
->getAttributeName() ) )
1413 case AnimationNodeType::ANIMATECOLOR
:
1415 Sequence
<Any
> aValues( xAnimate
->getValues() );
1416 if( aValues
.hasElements() )
1418 if( aValues
.getLength() > nIndex
)
1420 aValues
[nIndex
] = rColor
;
1421 xAnimate
->setValues( aValues
);
1424 else if( (nIndex
== 0) && xAnimate
->getFrom().hasValue() )
1425 xAnimate
->setFrom(rColor
);
1426 else if( (nIndex
== 1) && xAnimate
->getTo().hasValue() )
1427 xAnimate
->setTo(rColor
);
1436 catch( Exception
& e
)
1439 DBG_ERROR("sd::CustomAnimationEffect::setColor(), exception cought!" );
1443 // --------------------------------------------------------------------
1445 Any
CustomAnimationEffect::getTransformationProperty( sal_Int32 nTransformType
, EValue eValue
)
1448 if( mxNode
.is() ) try
1450 Reference
< XEnumerationAccess
> xEnumerationAccess( mxNode
, UNO_QUERY
);
1451 if( xEnumerationAccess
.is() )
1453 Reference
< XEnumeration
> xEnumeration( xEnumerationAccess
->createEnumeration(), UNO_QUERY
);
1454 if( xEnumeration
.is() )
1456 while( xEnumeration
->hasMoreElements() && !aProperty
.hasValue() )
1458 Reference
< XAnimateTransform
> xTransform( xEnumeration
->nextElement(), UNO_QUERY
);
1459 if( !xTransform
.is() )
1462 if( xTransform
->getTransformType() == nTransformType
)
1466 case VALUE_FROM
: aProperty
= xTransform
->getFrom(); break;
1467 case VALUE_TO
: aProperty
= xTransform
->getTo(); break;
1468 case VALUE_BY
: aProperty
= xTransform
->getBy(); break;
1472 Sequence
<Any
> aValues( xTransform
->getValues() );
1473 if( aValues
.hasElements() )
1474 aProperty
= aValues
[ eValue
== VALUE_FIRST
? 0 : aValues
.getLength() - 1 ];
1483 catch( Exception
& e
)
1486 DBG_ERROR("sd::CustomAnimationEffect::getTransformationProperty(), exception cought!" );
1492 // --------------------------------------------------------------------
1494 bool CustomAnimationEffect::setTransformationProperty( sal_Int32 nTransformType
, EValue eValue
, const Any
& rValue
)
1496 bool bChanged
= false;
1497 if( mxNode
.is() ) try
1499 Reference
< XEnumerationAccess
> xEnumerationAccess( mxNode
, UNO_QUERY
);
1500 if( xEnumerationAccess
.is() )
1502 Reference
< XEnumeration
> xEnumeration( xEnumerationAccess
->createEnumeration(), UNO_QUERY
);
1503 if( xEnumeration
.is() )
1505 while( xEnumeration
->hasMoreElements() )
1507 Reference
< XAnimateTransform
> xTransform( xEnumeration
->nextElement(), UNO_QUERY
);
1508 if( !xTransform
.is() )
1511 if( xTransform
->getTransformType() == nTransformType
)
1516 if( xTransform
->getFrom() != rValue
)
1518 xTransform
->setFrom( rValue
);
1523 if( xTransform
->getTo() != rValue
)
1525 xTransform
->setTo( rValue
);
1530 if( xTransform
->getBy() != rValue
)
1532 xTransform
->setBy( rValue
);
1539 Sequence
<Any
> aValues( xTransform
->getValues() );
1540 if( !aValues
.hasElements() )
1543 sal_Int32 nIndex
= eValue
== VALUE_FIRST
? 0 : aValues
.getLength() - 1;
1544 if( aValues
[nIndex
] != rValue
)
1546 aValues
[nIndex
] = rValue
;
1547 xTransform
->setValues( aValues
);
1557 catch( Exception
& e
)
1560 DBG_ERROR("sd::CustomAnimationEffect::setTransformationProperty(), exception cought!" );
1566 // --------------------------------------------------------------------
1568 void CustomAnimationEffect::createAudio( const ::com::sun::star::uno::Any
& rSource
, double fVolume
/* = 1.0 */ )
1570 DBG_ASSERT( !mxAudio
.is(), "sd::CustomAnimationEffect::createAudio(), node already has an audio!" );
1572 if( !mxAudio
.is() ) try
1574 Reference
< XMultiServiceFactory
> xMsf( ::comphelper::getProcessServiceFactory() );
1575 Reference
< XAudio
> xAudio( xMsf
->createInstance( OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.animations.Audio") ) ), UNO_QUERY_THROW
);
1576 xAudio
->setSource( rSource
);
1577 xAudio
->setVolume( fVolume
);
1580 catch( Exception
& e
)
1583 DBG_ERROR("sd::CustomAnimationEffect::createAudio(), exception cought!" );
1587 // --------------------------------------------------------------------
1589 static Reference
< XCommand
> findCommandNode( const Reference
< XAnimationNode
>& xRootNode
)
1591 Reference
< XCommand
> xCommand
;
1593 if( xRootNode
.is() ) try
1595 Reference
< XEnumerationAccess
> xEnumerationAccess( xRootNode
, UNO_QUERY_THROW
);
1596 Reference
< XEnumeration
> xEnumeration( xEnumerationAccess
->createEnumeration(), UNO_QUERY_THROW
);
1597 while( !xCommand
.is() && xEnumeration
->hasMoreElements() )
1599 Reference
< XAnimationNode
> xNode( xEnumeration
->nextElement(), UNO_QUERY
);
1600 if( xNode
.is() && (xNode
->getType() == AnimationNodeType::COMMAND
) )
1601 xCommand
.set( xNode
, UNO_QUERY_THROW
);
1604 catch( Exception
& e
)
1607 DBG_ERROR("sd::findCommandNode(), exception caught!" );
1613 void CustomAnimationEffect::removeAudio()
1617 Reference
< XAnimationNode
> xChild
;
1621 xChild
.set( mxAudio
, UNO_QUERY
);
1624 else if( mnCommand
== EffectCommands::STOPAUDIO
)
1626 xChild
.set( findCommandNode( mxNode
), UNO_QUERY
);
1632 Reference
< XTimeContainer
> xContainer( mxNode
, UNO_QUERY
);
1633 if( xContainer
.is() )
1634 xContainer
->removeChild( xChild
);
1637 catch( Exception
& e
)
1640 DBG_ERROR("sd::CustomAnimationEffect::removeAudio(), exception caught!" );
1645 // --------------------------------------------------------------------
1647 void CustomAnimationEffect::setAudio( const Reference
< ::com::sun::star::animations::XAudio
>& xAudio
)
1649 if( mxAudio
!= xAudio
) try
1653 Reference
< XTimeContainer
> xContainer( mxNode
, UNO_QUERY
);
1654 Reference
< XAnimationNode
> xChild( mxAudio
, UNO_QUERY
);
1655 if( xContainer
.is() && xChild
.is() )
1656 xContainer
->appendChild( xChild
);
1658 catch( Exception
& e
)
1661 DBG_ERROR("sd::CustomAnimationEffect::setAudio(), exception caught!" );
1665 // --------------------------------------------------------------------
1667 void CustomAnimationEffect::setStopAudio()
1669 if( mnCommand
!= EffectCommands::STOPAUDIO
) try
1674 Reference
< XMultiServiceFactory
> xMsf( ::comphelper::getProcessServiceFactory() );
1675 Reference
< XCommand
> xCommand( xMsf
->createInstance( OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.animations.Command") ) ), UNO_QUERY_THROW
);
1677 xCommand
->setCommand( EffectCommands::STOPAUDIO
);
1679 Reference
< XTimeContainer
> xContainer( mxNode
, UNO_QUERY_THROW
);
1680 Reference
< XAnimationNode
> xChild( xCommand
, UNO_QUERY_THROW
);
1681 xContainer
->appendChild( xChild
);
1683 mnCommand
= EffectCommands::STOPAUDIO
;
1685 catch( Exception
& e
)
1688 DBG_ERROR("sd::CustomAnimationEffect::setStopAudio(), exception caught!" );
1692 // --------------------------------------------------------------------
1694 bool CustomAnimationEffect::getStopAudio() const
1696 return mnCommand
== EffectCommands::STOPAUDIO
;
1699 // --------------------------------------------------------------------
1701 SdrPathObj
* CustomAnimationEffect::createSdrPathObjFromPath()
1703 SdrPathObj
* pPathObj
= new SdrPathObj( OBJ_PATHLINE
);
1704 updateSdrPathObjFromPath( *pPathObj
);
1708 // --------------------------------------------------------------------
1710 void CustomAnimationEffect::updateSdrPathObjFromPath( SdrPathObj
& rPathObj
)
1712 ::basegfx::B2DPolyPolygon xPolyPoly
;
1713 if( ::basegfx::tools::importFromSvgD( xPolyPoly
, getPath() ) )
1715 SdrObject
* pObj
= GetSdrObjectFromXShape( getTargetShape() );
1718 ::basegfx::B2DHomMatrix aTransform
;
1720 SdrPage
* pPage
= pObj
->GetPage();
1723 const Size
aPageSize( pPage
->GetSize() );
1724 aTransform
.scale( (double)aPageSize
.Width(), (double)aPageSize
.Height() );
1725 xPolyPoly
.transform( aTransform
);
1726 aTransform
.identity();
1729 const Rectangle
aBoundRect( pObj
->GetCurrentBoundRect() );
1730 const Point
aCenter( aBoundRect
.Center() );
1731 aTransform
.translate( aCenter
.X(), aCenter
.Y() );
1732 xPolyPoly
.transform( aTransform
);
1736 rPathObj
.SetPathPoly( xPolyPoly
);
1739 // --------------------------------------------------------------------
1741 void CustomAnimationEffect::updatePathFromSdrPathObj( const SdrPathObj
& rPathObj
)
1743 ::basegfx::B2DPolyPolygon
xPolyPoly( rPathObj
.GetPathPoly() );
1745 SdrObject
* pObj
= GetSdrObjectFromXShape( getTargetShape() );
1748 const Rectangle
aBoundRect( pObj
->GetCurrentBoundRect() );
1749 const Point
aCenter( aBoundRect
.Center() );
1751 ::basegfx::B2DHomMatrix aTransform
;
1752 aTransform
.translate( -aCenter
.X(), -aCenter
.Y() );
1753 xPolyPoly
.transform( aTransform
);
1755 SdrPage
* pPage
= pObj
->GetPage();
1758 aTransform
.identity();
1759 const Size
aPageSize( pPage
->GetSize() );
1760 aTransform
.scale( 1.0 / (double)aPageSize
.Width(), 1.0 / (double)aPageSize
.Height() );
1761 xPolyPoly
.transform( aTransform
);
1765 setPath( ::basegfx::tools::exportToSvgD( xPolyPoly
) );
1768 // ====================================================================
1770 EffectSequenceHelper::EffectSequenceHelper()
1771 : mnSequenceType( EffectNodeType::DEFAULT
)
1775 // --------------------------------------------------------------------
1777 EffectSequenceHelper::EffectSequenceHelper( const ::com::sun::star::uno::Reference
< ::com::sun::star::animations::XTimeContainer
>& xSequenceRoot
)
1778 : mxSequenceRoot( xSequenceRoot
), mnSequenceType( EffectNodeType::DEFAULT
)
1780 Reference
< XAnimationNode
> xNode( mxSequenceRoot
, UNO_QUERY_THROW
);
1784 // --------------------------------------------------------------------
1786 EffectSequenceHelper::~EffectSequenceHelper()
1791 // --------------------------------------------------------------------
1793 void EffectSequenceHelper::reset()
1795 EffectSequence::iterator
aIter( maEffects
.begin() );
1796 EffectSequence::iterator
aEnd( maEffects
.end() );
1799 CustomAnimationEffectPtr pEffect
= (*aIter
++);
1800 pEffect
->setEffectSequence(0);
1805 Reference
< XAnimationNode
> EffectSequenceHelper::getRootNode()
1807 Reference
< XAnimationNode
> xRoot( mxSequenceRoot
, UNO_QUERY
);
1811 // --------------------------------------------------------------------
1813 void EffectSequenceHelper::append( const CustomAnimationEffectPtr
& pEffect
)
1815 pEffect
->setEffectSequence( this );
1816 maEffects
.push_back(pEffect
);
1820 // --------------------------------------------------------------------
1822 void EffectSequenceHelper::insert( EffectSequence::iterator
& rPos
, const CustomAnimationEffectPtr
& pEffect
)
1824 pEffect
->setEffectSequence( this );
1825 maEffects
.insert( rPos
, pEffect
);
1829 // --------------------------------------------------------------------
1831 CustomAnimationEffectPtr
EffectSequenceHelper::append( const CustomAnimationPresetPtr
& pPreset
, const Any
& rTarget
, double fDuration
/* = -1.0 */ )
1833 CustomAnimationEffectPtr pEffect
;
1838 Reference
< XAnimationNode
> xNode( pPreset
->create( strEmpty
) );
1841 // first, filter all only ui relevant user data
1842 std::vector
< NamedValue
> aNewUserData
;
1843 Sequence
< NamedValue
> aUserData( xNode
->getUserData() );
1844 sal_Int32 nLength
= aUserData
.getLength();
1845 const NamedValue
* p
= aUserData
.getConstArray();
1846 bool bFilter
= false;
1850 if( !p
->Name
.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "text-only" ) ) &&
1851 !p
->Name
.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "preset-property" ) ) )
1853 aNewUserData
.push_back( *p
);
1861 aUserData
= ::comphelper::containerToSequence
< NamedValue
, std::vector
< NamedValue
> >( aNewUserData
);
1862 xNode
->setUserData( aUserData
);
1865 // check target, maybe we need to force it to text
1866 Any
aTarget( rTarget
);
1867 sal_Int16 nSubItem
= ShapeAnimationSubType::AS_WHOLE
;
1869 if( aTarget
.getValueType() == ::getCppuType((const ParagraphTarget
*)0) )
1871 nSubItem
= ShapeAnimationSubType::ONLY_TEXT
;
1873 else if( pPreset
->isTextOnly() )
1875 Reference
< XShape
> xShape
;
1879 // thats bad, we target a shape here but the effect is only for text
1880 // so change subitem
1881 nSubItem
= ShapeAnimationSubType::ONLY_TEXT
;
1885 // now create effect from preset
1886 pEffect
.reset( new CustomAnimationEffect( xNode
) );
1887 pEffect
->setEffectSequence( this );
1888 pEffect
->setTarget( aTarget
);
1889 pEffect
->setTargetSubItem( nSubItem
);
1890 if( fDuration
!= -1.0 )
1891 pEffect
->setDuration( fDuration
);
1893 maEffects
.push_back(pEffect
);
1899 DBG_ASSERT( pEffect
.get(), "sd::EffectSequenceHelper::append(), failed!" );
1903 // --------------------------------------------------------------------
1905 CustomAnimationEffectPtr
EffectSequenceHelper::append( const SdrPathObj
& rPathObj
, const Any
& rTarget
, double fDuration
/* = -1.0 */ )
1907 CustomAnimationEffectPtr pEffect
;
1909 if( fDuration
<= 0.0 )
1914 Reference
< XTimeContainer
> xEffectContainer( createParallelTimeContainer() );
1915 const OUString
aServiceName( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.animations.AnimateMotion" ) );
1916 Reference
< XAnimationNode
> xAnimateMotion( ::comphelper::getProcessServiceFactory()->createInstance(aServiceName
), UNO_QUERY_THROW
);
1918 xAnimateMotion
->setDuration( Any( fDuration
) );
1919 xAnimateMotion
->setFill( AnimationFill::HOLD
);
1920 xEffectContainer
->appendChild( xAnimateMotion
);
1922 sal_Int16 nSubItem
= ShapeAnimationSubType::AS_WHOLE
;
1924 if( rTarget
.getValueType() == ::getCppuType((const ParagraphTarget
*)0) )
1925 nSubItem
= ShapeAnimationSubType::ONLY_TEXT
;
1927 Reference
< XAnimationNode
> xEffectNode( xEffectContainer
, UNO_QUERY_THROW
);
1928 pEffect
.reset( new CustomAnimationEffect( xEffectNode
) );
1929 pEffect
->setEffectSequence( this );
1930 pEffect
->setTarget( rTarget
);
1931 pEffect
->setTargetSubItem( nSubItem
);
1932 pEffect
->setNodeType( ::com::sun::star::presentation::EffectNodeType::ON_CLICK
);
1933 pEffect
->setPresetClass( ::com::sun::star::presentation::EffectPresetClass::MOTIONPATH
);
1934 pEffect
->setAcceleration( 0.5 );
1935 pEffect
->setDecelerate( 0.5 );
1936 pEffect
->setFill( AnimationFill::HOLD
);
1937 pEffect
->setBegin( 0.0 );
1938 pEffect
->updatePathFromSdrPathObj( rPathObj
);
1939 if( fDuration
!= -1.0 )
1940 pEffect
->setDuration( fDuration
);
1942 maEffects
.push_back(pEffect
);
1948 DBG_ERROR( "sd::EffectSequenceHelper::append(), exception cought!" );
1954 // --------------------------------------------------------------------
1956 void EffectSequenceHelper::replace( const CustomAnimationEffectPtr
& pEffect
, const CustomAnimationPresetPtr
& pPreset
, const OUString
& rPresetSubType
, double fDuration
/* = -1.0 */ )
1958 if( pEffect
.get() && pPreset
.get() ) try
1960 Reference
< XAnimationNode
> xNewNode( pPreset
->create( rPresetSubType
) );
1963 pEffect
->replaceNode( xNewNode
);
1964 if( fDuration
!= -1.0 )
1965 pEffect
->setDuration( fDuration
);
1970 catch( Exception
& e
)
1973 DBG_ERROR( "sd::EffectSequenceHelper::replace(), exception cought!" );
1977 // --------------------------------------------------------------------
1979 void EffectSequenceHelper::replace( const CustomAnimationEffectPtr
& pEffect
, const CustomAnimationPresetPtr
& pPreset
, double fDuration
/* = -1.0 */ )
1982 replace( pEffect
, pPreset
, strEmpty
, fDuration
);
1985 // --------------------------------------------------------------------
1987 void EffectSequenceHelper::remove( const CustomAnimationEffectPtr
& pEffect
)
1991 pEffect
->setEffectSequence( 0 );
1992 maEffects
.remove( pEffect
);
1998 // --------------------------------------------------------------------
2000 void EffectSequenceHelper::rebuild()
2005 // --------------------------------------------------------------------
2007 void EffectSequenceHelper::implRebuild()
2011 // first we delete all time containers on the first two levels
2012 Reference
< XEnumerationAccess
> xEnumerationAccess( mxSequenceRoot
, UNO_QUERY_THROW
);
2013 Reference
< XEnumeration
> xEnumeration( xEnumerationAccess
->createEnumeration(), UNO_QUERY_THROW
);
2014 while( xEnumeration
->hasMoreElements() )
2016 Reference
< XAnimationNode
> xChildNode( xEnumeration
->nextElement(), UNO_QUERY_THROW
);
2017 Reference
< XTimeContainer
> xChildContainer( xChildNode
, UNO_QUERY_THROW
);
2019 Reference
< XEnumerationAccess
> xChildEnumerationAccess( xChildNode
, UNO_QUERY_THROW
);
2020 Reference
< XEnumeration
> xChildEnumeration( xChildEnumerationAccess
->createEnumeration(), UNO_QUERY_THROW
);
2021 while( xChildEnumeration
->hasMoreElements() )
2023 Reference
< XAnimationNode
> xNode( xChildEnumeration
->nextElement(), UNO_QUERY_THROW
);
2024 xChildContainer
->removeChild( xNode
);
2027 mxSequenceRoot
->removeChild( xChildNode
);
2030 // second, rebuild main sequence
2031 EffectSequence::iterator
aIter( maEffects
.begin() );
2032 EffectSequence::iterator
aEnd( maEffects
.end() );
2035 AfterEffectNodeList aAfterEffects
;
2037 CustomAnimationEffectPtr pEffect
= (*aIter
++);
2042 // create a par container for the next click node and all following with and after effects
2043 Reference
< XTimeContainer
> xOnClickContainer( createParallelTimeContainer() );
2046 if( mxEventSource
.is() )
2048 aEvent
.Source
<<= mxEventSource
;
2049 aEvent
.Trigger
= EventTrigger::ON_CLICK
;
2053 aEvent
.Trigger
= EventTrigger::ON_NEXT
;
2057 Any
aBegin( makeAny( aEvent
) );
2060 // if the first node is not a click action, this click container
2061 // must not have INDEFINITE begin but start at 0s
2063 if( pEffect
->getNodeType() != EffectNodeType::ON_CLICK
)
2064 aBegin
<<= (double)0.0;
2067 xOnClickContainer
->setBegin( aBegin
);
2069 Reference
< XAnimationNode
> xOnClickContainerNode( xOnClickContainer
, UNO_QUERY_THROW
);
2070 mxSequenceRoot
->appendChild( xOnClickContainerNode
);
2072 double fBegin
= 0.0;
2076 // create a par container for the current click or after effect node and all following with effects
2077 Reference
< XTimeContainer
> xWithContainer( createParallelTimeContainer() );
2078 Reference
< XAnimationNode
> xWithContainerNode( xWithContainer
, UNO_QUERY_THROW
);
2079 xWithContainer
->setBegin( makeAny( fBegin
) );
2080 xOnClickContainer
->appendChild( xWithContainerNode
);
2082 double fDuration
= 0.0;
2085 Reference
< XAnimationNode
> xEffectNode( pEffect
->getNode() );
2086 xWithContainer
->appendChild( xEffectNode
);
2088 if( pEffect
->hasAfterEffect() )
2090 Reference
< XAnimationNode
> xAfterEffect( pEffect
->createAfterEffectNode() );
2091 AfterEffectNode
a( xAfterEffect
, xEffectNode
, pEffect
->IsAfterEffectOnNext() );
2092 aAfterEffects
.push_back( a
);
2095 double fTemp
= pEffect
->getBegin() + pEffect
->getAbsoluteDuration();
2096 if( fTemp
> fDuration
)
2100 pEffect
= (*aIter
++);
2104 while( pEffect
.get() && (pEffect
->getNodeType() == EffectNodeType::WITH_PREVIOUS
) );
2106 fBegin
+= fDuration
;
2108 while( pEffect
.get() && (pEffect
->getNodeType() != EffectNodeType::ON_CLICK
) );
2110 while( pEffect
.get() );
2112 // process after effect nodes
2113 std::for_each( aAfterEffects
.begin(), aAfterEffects
.end(), stl_process_after_effect_node_func
);
2117 // reset duration, might have been altered (see below)
2118 mxSequenceRoot
->setDuration( Any() );
2122 // empty sequence, set duration to 0.0 explicitely
2123 // (otherwise, this sequence will never end)
2124 mxSequenceRoot
->setDuration( makeAny((double)0.0) );
2127 catch( Exception
& e
)
2130 DBG_ERROR( "sd::EffectSequenceHelper::rebuild(), exception cought!" );
2134 // --------------------------------------------------------------------
2136 Reference
< XTimeContainer
> EffectSequenceHelper::createParallelTimeContainer() const
2138 const OUString
aServiceName( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.animations.ParallelTimeContainer" ) );
2139 return Reference
< XTimeContainer
>( ::comphelper::getProcessServiceFactory()->createInstance(aServiceName
), UNO_QUERY
);
2142 // --------------------------------------------------------------------
2144 stl_CustomAnimationEffect_search_node_predict::stl_CustomAnimationEffect_search_node_predict( const ::com::sun::star::uno::Reference
< ::com::sun::star::animations::XAnimationNode
>& xSearchNode
)
2145 : mxSearchNode( xSearchNode
)
2149 // --------------------------------------------------------------------
2151 bool stl_CustomAnimationEffect_search_node_predict::operator()( CustomAnimationEffectPtr pEffect
) const
2153 return pEffect
->getNode() == mxSearchNode
;
2156 // --------------------------------------------------------------------
2158 static bool implFindNextContainer( Reference
< XTimeContainer
>& xParent
, Reference
< XTimeContainer
>& xCurrent
, Reference
< XTimeContainer
>& xNext
)
2161 Reference
< XEnumerationAccess
> xEnumerationAccess( xParent
, UNO_QUERY_THROW
);
2162 Reference
< XEnumeration
> xEnumeration( xEnumerationAccess
->createEnumeration() );
2163 if( xEnumeration
.is() )
2165 Reference
< XInterface
> x
;
2166 while( xEnumeration
->hasMoreElements() && !xNext
.is() )
2168 if( (xEnumeration
->nextElement() >>= x
) && (x
== xCurrent
) )
2170 if( xEnumeration
->hasMoreElements() )
2171 xEnumeration
->nextElement() >>= xNext
;
2178 // --------------------------------------------------------------------
2180 void stl_process_after_effect_node_func(AfterEffectNode
& rNode
)
2184 if( rNode
.mxNode
.is() && rNode
.mxMaster
.is() )
2187 Reference
< XAnimationNode
> xMasterNode( rNode
.mxMaster
, UNO_QUERY_THROW
);
2188 Sequence
< NamedValue
> aUserData( rNode
.mxNode
->getUserData() );
2189 sal_Int32 nSize
= aUserData
.getLength();
2190 aUserData
.realloc(nSize
+1);
2191 aUserData
[nSize
].Name
= OUString( RTL_CONSTASCII_USTRINGPARAM( "master-element" ) );
2192 aUserData
[nSize
].Value
<<= xMasterNode
;
2193 rNode
.mxNode
->setUserData( aUserData
);
2195 // insert after effect node into timeline
2196 Reference
< XTimeContainer
> xContainer( rNode
.mxMaster
->getParent(), UNO_QUERY_THROW
);
2198 if( !rNode
.mbOnNextEffect
) // sameClick
2200 // insert the aftereffect after its effect is animated
2201 xContainer
->insertAfter( rNode
.mxNode
, rNode
.mxMaster
);
2205 Reference
< XMultiServiceFactory
> xMsf( ::comphelper::getProcessServiceFactory() );
2206 // insert the aftereffect in the next group
2208 Reference
< XTimeContainer
> xClickContainer( xContainer
->getParent(), UNO_QUERY_THROW
);
2209 Reference
< XTimeContainer
> xSequenceContainer( xClickContainer
->getParent(), UNO_QUERY_THROW
);
2211 Reference
< XTimeContainer
> xNextContainer
;
2213 // first try if we have an after effect container
2214 if( !implFindNextContainer( xClickContainer
, xContainer
, xNextContainer
) )
2216 Reference
< XTimeContainer
> xNextClickContainer
;
2217 // if not, try to find the next click effect container
2218 if( implFindNextContainer( xSequenceContainer
, xClickContainer
, xNextClickContainer
) )
2220 Reference
< XEnumerationAccess
> xEnumerationAccess( xNextClickContainer
, UNO_QUERY_THROW
);
2221 Reference
< XEnumeration
> xEnumeration( xEnumerationAccess
->createEnumeration(), UNO_QUERY_THROW
);
2222 if( xEnumeration
->hasMoreElements() )
2224 // the next container is the first child container
2225 xEnumeration
->nextElement() >>= xNextContainer
;
2229 // this does not yet have a child container, create one
2230 const OUString
aServiceName( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.animations.ParallelTimeContainer") );
2231 xNextContainer
= Reference
< XTimeContainer
>::query( xMsf
->createInstance(aServiceName
) );
2233 if( xNextContainer
.is() )
2235 Reference
< XAnimationNode
> xNode( xNextContainer
, UNO_QUERY_THROW
);
2236 xNode
->setBegin( makeAny( (double)0.0 ) );
2237 // xNode->setFill( AnimationFill::HOLD );
2238 xNextClickContainer
->appendChild( xNode
);
2241 DBG_ASSERT( xNextContainer
.is(), "ppt::stl_process_after_effect_node_func::operator(), could not find/create container!" );
2245 // if we don't have a next container, we add one to the sequence container
2246 if( !xNextContainer
.is() )
2248 const OUString
aServiceName( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.animations.ParallelTimeContainer") );
2249 Reference
< XTimeContainer
> xNewClickContainer( xMsf
->createInstance(aServiceName
), UNO_QUERY_THROW
);
2251 Reference
< XAnimationNode
> xNewClickNode( xNewClickContainer
, UNO_QUERY_THROW
);
2254 aEvent
.Trigger
= EventTrigger::ON_NEXT
;
2256 xNewClickNode
->setBegin( makeAny( aEvent
) );
2258 Reference
< XAnimationNode
> xRefNode( xClickContainer
, UNO_QUERY_THROW
);
2259 xSequenceContainer
->insertAfter( xNewClickNode
, xRefNode
);
2261 xNextContainer
= Reference
< XTimeContainer
>::query( xMsf
->createInstance(aServiceName
) );
2263 DBG_ASSERT( xNextContainer
.is(), "ppt::stl_process_after_effect_node_func::operator(), could not create container!" );
2264 if( xNextContainer
.is() )
2266 Reference
< XAnimationNode
> xNode( xNextContainer
, UNO_QUERY_THROW
);
2267 xNode
->setBegin( makeAny( (double)0.0 ) );
2268 // xNode->setFill( AnimationFill::HOLD );
2269 xNewClickContainer
->appendChild( xNode
);
2273 if( xNextContainer
.is() )
2275 // find begin time of first element
2276 Reference
< XEnumerationAccess
> xEnumerationAccess( xNextContainer
, UNO_QUERY_THROW
);
2277 Reference
< XEnumeration
> xEnumeration( xEnumerationAccess
->createEnumeration(), UNO_QUERY_THROW
);
2278 if( xEnumeration
->hasMoreElements() )
2280 Reference
< XAnimationNode
> xChild
;
2281 // the next container is the first child container
2282 xEnumeration
->nextElement() >>= xChild
;
2285 Any
aBegin( xChild
->getBegin() );
2286 double fBegin
= 0.0;
2287 if( (aBegin
>>= fBegin
) && (fBegin
>= 0.0))
2288 rNode
.mxNode
->setBegin( aBegin
);
2292 xNextContainer
->appendChild( rNode
.mxNode
);
2297 catch( Exception
& e
)
2300 DBG_ERROR( "ppt::stl_process_after_effect_node_func::operator(), exception cought!" );
2304 // --------------------------------------------------------------------
2306 EffectSequence::iterator
EffectSequenceHelper::find( const CustomAnimationEffectPtr
& pEffect
)
2308 return std::find( maEffects
.begin(), maEffects
.end(), pEffect
);
2311 // --------------------------------------------------------------------
2313 CustomAnimationEffectPtr
EffectSequenceHelper::findEffect( const ::com::sun::star::uno::Reference
< ::com::sun::star::animations::XAnimationNode
>& xNode
) const
2315 CustomAnimationEffectPtr pEffect
;
2317 EffectSequence::const_iterator
aIter( maEffects
.begin() );
2318 for( ; aIter
!= maEffects
.end(); aIter
++ )
2320 if( (*aIter
)->getNode() == xNode
)
2330 // --------------------------------------------------------------------
2332 sal_Int32
EffectSequenceHelper::getOffsetFromEffect( const CustomAnimationEffectPtr
& xEffect
) const
2334 sal_Int32 nOffset
= 0;
2336 EffectSequence::const_iterator
aIter( maEffects
.begin() );
2337 for( ; aIter
!= maEffects
.end(); aIter
++, nOffset
++ )
2339 if( (*aIter
) == xEffect
)
2346 // --------------------------------------------------------------------
2348 CustomAnimationEffectPtr
EffectSequenceHelper::getEffectFromOffset( sal_Int32 nOffset
) const
2350 EffectSequence::const_iterator
aIter( maEffects
.begin() );
2351 while( nOffset
-- && aIter
!= maEffects
.end() )
2354 CustomAnimationEffectPtr pEffect
;
2355 if( aIter
!= maEffects
.end() )
2361 // --------------------------------------------------------------------
2363 bool EffectSequenceHelper::disposeShape( const Reference
< XShape
>& xShape
)
2365 bool bChanges
= false;
2367 EffectSequence::iterator
aIter( maEffects
.begin() );
2368 while( aIter
!= maEffects
.end() )
2370 if( (*aIter
)->getTargetShape() == xShape
)
2372 (*aIter
)->setEffectSequence( 0 );
2374 aIter
= maEffects
.erase( aIter
);
2385 // --------------------------------------------------------------------
2387 bool EffectSequenceHelper::hasEffect( const com::sun::star::uno::Reference
< com::sun::star::drawing::XShape
>& xShape
)
2389 EffectSequence::iterator
aIter( maEffects
.begin() );
2390 while( aIter
!= maEffects
.end() )
2392 if( (*aIter
)->getTargetShape() == xShape
)
2400 // --------------------------------------------------------------------
2402 void EffectSequenceHelper::insertTextRange( const com::sun::star::uno::Any
& aTarget
)
2404 bool bChanges
= false;
2406 ParagraphTarget aParaTarget
;
2407 if( !(aTarget
>>= aParaTarget
) )
2410 EffectSequence::iterator
aIter( maEffects
.begin() );
2411 while( aIter
!= maEffects
.end() )
2413 if( (*aIter
)->getTargetShape() == aParaTarget
.Shape
)
2414 bChanges
|= (*aIter
)->checkForText();
2422 // --------------------------------------------------------------------
2424 void EffectSequenceHelper::disposeTextRange( const com::sun::star::uno::Any
& aTarget
)
2426 ParagraphTarget aParaTarget
;
2427 if( !(aTarget
>>= aParaTarget
) )
2430 bool bChanges
= false;
2431 bool bErased
= false;
2433 EffectSequence::iterator
aIter( maEffects
.begin() );
2434 while( aIter
!= maEffects
.end() )
2436 Any
aIterTarget( (*aIter
)->getTarget() );
2437 if( aIterTarget
.getValueType() == ::getCppuType((const ParagraphTarget
*)0) )
2439 ParagraphTarget aIterParaTarget
;
2440 if( (aIterTarget
>>= aIterParaTarget
) && (aIterParaTarget
.Shape
== aParaTarget
.Shape
) )
2442 if( aIterParaTarget
.Paragraph
== aParaTarget
.Paragraph
)
2444 // delete this effect if it targets the disposed paragraph directly
2445 (*aIter
)->setEffectSequence( 0 );
2446 aIter
= maEffects
.erase( aIter
);
2452 if( aIterParaTarget
.Paragraph
> aParaTarget
.Paragraph
)
2454 // shift all paragraphs after disposed paragraph
2455 aIterParaTarget
.Paragraph
--;
2456 (*aIter
)->setTarget( makeAny( aIterParaTarget
) );
2461 else if( (*aIter
)->getTargetShape() == aParaTarget
.Shape
)
2463 bChanges
|= (*aIter
)->checkForText();
2476 // --------------------------------------------------------------------
2478 CustomAnimationTextGroup::CustomAnimationTextGroup( const Reference
< XShape
>& rTarget
, sal_Int32 nGroupId
)
2479 : maTarget( rTarget
),
2480 mnGroupId( nGroupId
)
2485 // --------------------------------------------------------------------
2487 void CustomAnimationTextGroup::reset()
2489 mnTextGrouping
= -1;
2490 mbAnimateForm
= false;
2491 mbTextReverse
= false;
2492 mfGroupingAuto
= -1.0;
2493 mnLastPara
= -1; // used to check for TextReverse
2496 while( i
-- ) mnDepthFlags
[i
] = 0;
2501 // --------------------------------------------------------------------
2503 void CustomAnimationTextGroup::addEffect( CustomAnimationEffectPtr
& pEffect
)
2505 maEffects
.push_back( pEffect
);
2507 Any
aTarget( pEffect
->getTarget() );
2508 if( aTarget
.getValueType() == ::getCppuType((const ParagraphTarget
*)0) )
2510 // now look at the paragraph
2511 ParagraphTarget aParaTarget
;
2512 aTarget
>>= aParaTarget
;
2514 if( mnLastPara
!= -1 )
2515 mbTextReverse
= mnLastPara
> aParaTarget
.Paragraph
;
2517 mnLastPara
= aParaTarget
.Paragraph
;
2519 const sal_Int32 nParaDepth
= pEffect
->getParaDepth();
2521 // only look at the first 5 levels
2522 if( nParaDepth
< 5 )
2524 // our first paragraph with this level?
2525 if( mnDepthFlags
[nParaDepth
] == 0 )
2527 // so set it to the first found
2528 mnDepthFlags
[nParaDepth
] = (sal_Int8
)pEffect
->getNodeType();
2530 else if( mnDepthFlags
[nParaDepth
] != pEffect
->getNodeType() )
2532 mnDepthFlags
[nParaDepth
] = -1;
2535 if( pEffect
->getNodeType() == EffectNodeType::AFTER_PREVIOUS
)
2536 mfGroupingAuto
= pEffect
->getBegin();
2539 while( (mnTextGrouping
< 5) && (mnDepthFlags
[mnTextGrouping
] > 0) )
2545 // if we have an effect with the shape as a target, we animate the background
2546 mbAnimateForm
= pEffect
->getTargetSubItem() != ShapeAnimationSubType::ONLY_TEXT
;
2550 // --------------------------------------------------------------------
2552 class TextGroupMapImpl
: public std::map
< sal_Int32
, CustomAnimationTextGroup
* >
2555 CustomAnimationTextGroup
* findGroup( sal_Int32 nGroupId
);
2558 // --------------------------------------------------------------------
2560 CustomAnimationTextGroupPtr
EffectSequenceHelper::findGroup( sal_Int32 nGroupId
)
2562 CustomAnimationTextGroupPtr aPtr
;
2564 CustomAnimationTextGroupMap::iterator
aIter( maGroupMap
.find( nGroupId
) );
2565 if( aIter
!= maGroupMap
.end() )
2566 aPtr
= (*aIter
).second
;
2571 // --------------------------------------------------------------------
2573 void EffectSequenceHelper::updateTextGroups()
2577 // first create all the groups
2578 EffectSequence::iterator
aIter( maEffects
.begin() );
2579 const EffectSequence::iterator
aEnd( maEffects
.end() );
2580 while( aIter
!= aEnd
)
2582 CustomAnimationEffectPtr
pEffect( (*aIter
++) );
2584 const sal_Int32 nGroupId
= pEffect
->getGroupId();
2586 if( nGroupId
== -1 )
2587 continue; // trivial case, no group
2589 CustomAnimationTextGroupPtr pGroup
= findGroup( nGroupId
);
2592 pGroup
.reset( new CustomAnimationTextGroup( pEffect
->getTargetShape(), nGroupId
) );
2593 maGroupMap
[nGroupId
] = pGroup
;
2596 pGroup
->addEffect( pEffect
);
2600 // --------------------------------------------------------------------
2602 CustomAnimationTextGroupPtr
EffectSequenceHelper::createTextGroup( CustomAnimationEffectPtr pEffect
, sal_Int32 nTextGrouping
, double fTextGroupingAuto
, sal_Bool bAnimateForm
, sal_Bool bTextReverse
)
2604 // first finde a free group-id
2605 sal_Int32 nGroupId
= 0;
2607 CustomAnimationTextGroupMap::iterator
aIter( maGroupMap
.begin() );
2608 const CustomAnimationTextGroupMap::iterator
aEnd( maGroupMap
.end() );
2609 while( aIter
!= aEnd
)
2611 if( (*aIter
).first
== nGroupId
)
2614 aIter
= maGroupMap
.begin();
2622 Reference
< XShape
> xTarget( pEffect
->getTargetShape() );
2624 CustomAnimationTextGroupPtr
pTextGroup( new CustomAnimationTextGroup( xTarget
, nGroupId
) );
2625 maGroupMap
[nGroupId
] = pTextGroup
;
2629 // do we need to target the shape?
2630 if( (nTextGrouping
== 0) || bAnimateForm
)
2633 if( nTextGrouping
== 0)
2634 nSubItem
= bAnimateForm
? ShapeAnimationSubType::AS_WHOLE
: ShapeAnimationSubType::ONLY_TEXT
;
2636 nSubItem
= ShapeAnimationSubType::ONLY_BACKGROUND
;
2638 pEffect
->setTarget( makeAny( xTarget
) );
2639 pEffect
->setTargetSubItem( nSubItem
);
2640 pEffect
->setEffectSequence( this );
2641 pEffect
->setGroupId( nGroupId
);
2643 pTextGroup
->addEffect( pEffect
);
2647 pTextGroup
->mnTextGrouping
= nTextGrouping
;
2648 pTextGroup
->mfGroupingAuto
= fTextGroupingAuto
;
2649 pTextGroup
->mbTextReverse
= bTextReverse
;
2651 // now add an effect for each paragraph
2652 createTextGroupParagraphEffects( pTextGroup
, pEffect
, bUsed
);
2659 // --------------------------------------------------------------------
2661 void EffectSequenceHelper::createTextGroupParagraphEffects( CustomAnimationTextGroupPtr pTextGroup
, CustomAnimationEffectPtr pEffect
, bool bUsed
)
2663 Reference
< XShape
> xTarget( pTextGroup
->maTarget
);
2665 sal_Int32 nTextGrouping
= pTextGroup
->mnTextGrouping
;
2666 double fTextGroupingAuto
= pTextGroup
->mfGroupingAuto
;
2667 sal_Bool bTextReverse
= pTextGroup
->mbTextReverse
;
2669 // now add an effect for each paragraph
2670 if( nTextGrouping
>= 0 ) try
2672 EffectSequence::iterator
aInsertIter( find( pEffect
) );
2674 const OUString
strNumberingLevel( RTL_CONSTASCII_USTRINGPARAM("NumberingLevel") );
2675 Reference
< XEnumerationAccess
> xText( xTarget
, UNO_QUERY_THROW
);
2676 Reference
< XEnumeration
> xEnumeration( xText
->createEnumeration(), UNO_QUERY_THROW
);
2678 std::list
< sal_Int16
> aParaList
;
2681 // fill the list with all valid paragraphs
2682 for( nPara
= 0; xEnumeration
->hasMoreElements(); nPara
++ )
2684 Reference
< XTextRange
> xRange( xEnumeration
->nextElement(), UNO_QUERY
);
2685 if( xRange
.is() && xRange
->getString().getLength() )
2687 if( bTextReverse
) // sort them
2688 aParaList
.push_front( nPara
);
2690 aParaList
.push_back( nPara
);
2694 ParagraphTarget aTarget
;
2695 aTarget
.Shape
= xTarget
;
2697 std::list
< sal_Int16
>::iterator
aIter( aParaList
.begin() );
2698 std::list
< sal_Int16
>::iterator
aEnd( aParaList
.end() );
2699 while( aIter
!= aEnd
)
2701 aTarget
.Paragraph
= (*aIter
++);
2703 CustomAnimationEffectPtr pNewEffect
;
2706 // clone a new effect from first effect
2707 pNewEffect
= pEffect
->clone();
2709 aInsertIter
= maEffects
.insert( aInsertIter
, pNewEffect
);
2713 // reuse first effect if its not yet used
2714 pNewEffect
= pEffect
;
2716 aInsertIter
= find( pNewEffect
);
2719 // set target and group-id
2720 pNewEffect
->setTarget( makeAny( aTarget
) );
2721 pNewEffect
->setTargetSubItem( ShapeAnimationSubType::ONLY_TEXT
);
2722 pNewEffect
->setGroupId( pTextGroup
->mnGroupId
);
2723 pNewEffect
->setEffectSequence( this );
2725 // set correct node type
2726 if( pNewEffect
->getParaDepth() < nTextGrouping
)
2728 if( fTextGroupingAuto
== -1.0 )
2730 pNewEffect
->setNodeType( EffectNodeType::ON_CLICK
);
2731 pNewEffect
->setBegin( 0.0 );
2735 pNewEffect
->setNodeType( EffectNodeType::AFTER_PREVIOUS
);
2736 pNewEffect
->setBegin( fTextGroupingAuto
);
2741 pNewEffect
->setNodeType( EffectNodeType::WITH_PREVIOUS
);
2742 pNewEffect
->setBegin( 0.0 );
2745 pTextGroup
->addEffect( pNewEffect
);
2749 catch( Exception
& e
)
2752 DBG_ERROR("sd::EffectSequenceHelper::createTextGroup(), exception cought!" );
2756 // --------------------------------------------------------------------
2758 void EffectSequenceHelper::setTextGrouping( CustomAnimationTextGroupPtr pTextGroup
, sal_Int32 nTextGrouping
)
2760 if( pTextGroup
->mnTextGrouping
== nTextGrouping
)
2762 // first case, trivial case, do nothing
2764 else if( (pTextGroup
->mnTextGrouping
== -1) && (nTextGrouping
>= 0) )
2766 // second case, we need to add new effects for each paragraph
2768 CustomAnimationEffectPtr
pEffect( pTextGroup
->maEffects
.front() );
2770 pTextGroup
->mnTextGrouping
= nTextGrouping
;
2771 createTextGroupParagraphEffects( pTextGroup
, pEffect
, true );
2774 else if( (pTextGroup
->mnTextGrouping
>= 0) && (nTextGrouping
== -1 ) )
2776 // third case, we need to remove effects for each paragraph
2778 EffectSequence
aEffects( pTextGroup
->maEffects
);
2779 pTextGroup
->reset();
2781 EffectSequence::iterator
aIter( aEffects
.begin() );
2782 const EffectSequence::iterator
aEnd( aEffects
.end() );
2783 while( aIter
!= aEnd
)
2785 CustomAnimationEffectPtr
pEffect( (*aIter
++) );
2787 if( pEffect
->getTarget().getValueType() == ::getCppuType((const ParagraphTarget
*)0) )
2790 pTextGroup
->addEffect( pEffect
);
2796 // fourth case, we need to change the node types for the text nodes
2797 double fTextGroupingAuto
= pTextGroup
->mfGroupingAuto
;
2799 EffectSequence
aEffects( pTextGroup
->maEffects
);
2800 pTextGroup
->reset();
2802 EffectSequence::iterator
aIter( aEffects
.begin() );
2803 const EffectSequence::iterator
aEnd( aEffects
.end() );
2804 while( aIter
!= aEnd
)
2806 CustomAnimationEffectPtr
pEffect( (*aIter
++) );
2808 if( pEffect
->getTarget().getValueType() == ::getCppuType((const ParagraphTarget
*)0) )
2810 // set correct node type
2811 if( pEffect
->getParaDepth() < nTextGrouping
)
2813 if( fTextGroupingAuto
== -1.0 )
2815 pEffect
->setNodeType( EffectNodeType::ON_CLICK
);
2816 pEffect
->setBegin( 0.0 );
2820 pEffect
->setNodeType( EffectNodeType::AFTER_PREVIOUS
);
2821 pEffect
->setBegin( fTextGroupingAuto
);
2826 pEffect
->setNodeType( EffectNodeType::WITH_PREVIOUS
);
2827 pEffect
->setBegin( 0.0 );
2831 pTextGroup
->addEffect( pEffect
);
2838 // --------------------------------------------------------------------
2840 void EffectSequenceHelper::setAnimateForm( CustomAnimationTextGroupPtr pTextGroup
, sal_Bool bAnimateForm
)
2842 if( pTextGroup
->mbAnimateForm
== bAnimateForm
)
2844 // trivial case, do nothing
2848 EffectSequence
aEffects( pTextGroup
->maEffects
);
2849 pTextGroup
->reset();
2851 EffectSequence::iterator
aIter( aEffects
.begin() );
2852 const EffectSequence::iterator
aEnd( aEffects
.end() );
2854 // first insert if we have to
2857 EffectSequence::iterator
aInsertIter( find( (*aIter
) ) );
2859 CustomAnimationEffectPtr pEffect
;
2860 if( (aEffects
.size() == 1) && ((*aIter
)->getTarget().getValueType() != ::getCppuType((const ParagraphTarget
*)0) ) )
2862 // special case, only one effect and that targets whole text,
2863 // convert this to target whole shape
2864 pEffect
= (*aIter
++);
2865 pEffect
->setTargetSubItem( ShapeAnimationSubType::AS_WHOLE
);
2869 pEffect
= (*aIter
)->clone();
2870 pEffect
->setTarget( makeAny( (*aIter
)->getTargetShape() ) );
2871 pEffect
->setTargetSubItem( ShapeAnimationSubType::ONLY_BACKGROUND
);
2872 maEffects
.insert( aInsertIter
, pEffect
);
2875 pTextGroup
->addEffect( pEffect
);
2878 if( !bAnimateForm
&& (aEffects
.size() == 1) )
2880 CustomAnimationEffectPtr
pEffect( (*aIter
) );
2881 pEffect
->setTarget( makeAny( (*aIter
)->getTargetShape() ) );
2882 pEffect
->setTargetSubItem( ShapeAnimationSubType::ONLY_TEXT
);
2883 pTextGroup
->addEffect( pEffect
);
2887 // readd the rest to the group again
2888 while( aIter
!= aEnd
)
2890 CustomAnimationEffectPtr
pEffect( (*aIter
++) );
2892 if( pEffect
->getTarget().getValueType() == ::getCppuType((const ParagraphTarget
*)0) )
2894 pTextGroup
->addEffect( pEffect
);
2898 DBG_ASSERT( !bAnimateForm
, "sd::EffectSequenceHelper::setAnimateForm(), something is wrong here!" );
2907 // --------------------------------------------------------------------
2909 void EffectSequenceHelper::setTextGroupingAuto( CustomAnimationTextGroupPtr pTextGroup
, double fTextGroupingAuto
)
2911 sal_Int32 nTextGrouping
= pTextGroup
->mnTextGrouping
;
2913 EffectSequence
aEffects( pTextGroup
->maEffects
);
2914 pTextGroup
->reset();
2916 EffectSequence::iterator
aIter( aEffects
.begin() );
2917 const EffectSequence::iterator
aEnd( aEffects
.end() );
2918 while( aIter
!= aEnd
)
2920 CustomAnimationEffectPtr
pEffect( (*aIter
++) );
2922 if( pEffect
->getTarget().getValueType() == ::getCppuType((const ParagraphTarget
*)0) )
2924 // set correct node type
2925 if( pEffect
->getParaDepth() < nTextGrouping
)
2927 if( fTextGroupingAuto
== -1.0 )
2929 pEffect
->setNodeType( EffectNodeType::ON_CLICK
);
2930 pEffect
->setBegin( 0.0 );
2934 pEffect
->setNodeType( EffectNodeType::AFTER_PREVIOUS
);
2935 pEffect
->setBegin( fTextGroupingAuto
);
2940 pEffect
->setNodeType( EffectNodeType::WITH_PREVIOUS
);
2941 pEffect
->setBegin( 0.0 );
2945 pTextGroup
->addEffect( pEffect
);
2951 // --------------------------------------------------------------------
2953 struct ImplStlTextGroupSortHelper
2955 ImplStlTextGroupSortHelper( bool bReverse
) : mbReverse( bReverse
) {};
2956 bool operator()( const CustomAnimationEffectPtr
& p1
, const CustomAnimationEffectPtr
& p2
);
2958 sal_Int32
getTargetParagraph( const CustomAnimationEffectPtr
& p1
);
2961 // --------------------------------------------------------------------
2963 sal_Int32
ImplStlTextGroupSortHelper::getTargetParagraph( const CustomAnimationEffectPtr
& p1
)
2965 const Any
aTarget(p1
->getTarget());
2966 if( aTarget
.hasValue() && aTarget
.getValueType() == ::getCppuType((const ParagraphTarget
*)0) )
2968 ParagraphTarget aParaTarget
;
2969 aTarget
>>= aParaTarget
;
2970 return aParaTarget
.Paragraph
;
2974 return mbReverse
? 0x7fffffff : -1;
2978 // --------------------------------------------------------------------
2980 bool ImplStlTextGroupSortHelper::operator()( const CustomAnimationEffectPtr
& p1
, const CustomAnimationEffectPtr
& p2
)
2984 return getTargetParagraph( p2
) < getTargetParagraph( p1
);
2988 return getTargetParagraph( p1
) < getTargetParagraph( p2
);
2992 // --------------------------------------------------------------------
2994 void EffectSequenceHelper::setTextReverse( CustomAnimationTextGroupPtr pTextGroup
, sal_Bool bTextReverse
)
2996 if( pTextGroup
->mbTextReverse
== bTextReverse
)
3002 std::vector
< CustomAnimationEffectPtr
> aSortedVector(pTextGroup
->maEffects
.size());
3003 std::copy( pTextGroup
->maEffects
.begin(), pTextGroup
->maEffects
.end(), aSortedVector
.begin() );
3004 ImplStlTextGroupSortHelper
aSortHelper( bTextReverse
);
3005 std::sort( aSortedVector
.begin(), aSortedVector
.end(), aSortHelper
);
3007 pTextGroup
->reset();
3009 std::vector
< CustomAnimationEffectPtr
>::iterator
aIter( aSortedVector
.begin() );
3010 const std::vector
< CustomAnimationEffectPtr
>::iterator
aEnd( aSortedVector
.end() );
3014 pTextGroup
->addEffect( (*aIter
) );
3015 EffectSequence::iterator
aInsertIter( find( (*aIter
++) ) );
3016 while( aIter
!= aEnd
)
3018 CustomAnimationEffectPtr
pEffect( (*aIter
++) );
3019 maEffects
.erase( find( pEffect
) );
3020 aInsertIter
= maEffects
.insert( ++aInsertIter
, pEffect
);
3021 pTextGroup
->addEffect( pEffect
);
3028 // --------------------------------------------------------------------
3030 void EffectSequenceHelper::addListener( ISequenceListener
* pListener
)
3032 if( std::find( maListeners
.begin(), maListeners
.end(), pListener
) == maListeners
.end() )
3033 maListeners
.push_back( pListener
);
3036 // --------------------------------------------------------------------
3038 void EffectSequenceHelper::removeListener( ISequenceListener
* pListener
)
3040 maListeners
.remove( pListener
);
3043 // --------------------------------------------------------------------
3045 struct stl_notify_listeners_func
: public std::unary_function
<ISequenceListener
*, void>
3047 stl_notify_listeners_func() {}
3048 void operator()(ISequenceListener
* pListener
) { pListener
->notify_change(); }
3051 // --------------------------------------------------------------------
3053 void EffectSequenceHelper::notify_listeners()
3055 stl_notify_listeners_func aFunc
;
3056 std::for_each( maListeners
.begin(), maListeners
.end(), aFunc
);
3059 // --------------------------------------------------------------------
3061 void EffectSequenceHelper::create( const ::com::sun::star::uno::Reference
< ::com::sun::star::animations::XAnimationNode
>& xNode
)
3063 DBG_ASSERT( xNode
.is(), "sd::EffectSequenceHelper::create(), illegal argument" );
3065 if( xNode
.is() ) try
3067 Reference
< XEnumerationAccess
> xEnumerationAccess( xNode
, UNO_QUERY_THROW
);
3068 Reference
< XEnumeration
> xEnumeration( xEnumerationAccess
->createEnumeration(), UNO_QUERY_THROW
);
3069 while( xEnumeration
->hasMoreElements() )
3071 Reference
< XAnimationNode
> xChildNode( xEnumeration
->nextElement(), UNO_QUERY_THROW
);
3072 createEffectsequence( xChildNode
);
3077 DBG_ERROR( "sd::EffectSequenceHelper::create(), exception cought!" );
3081 // --------------------------------------------------------------------
3083 void EffectSequenceHelper::createEffectsequence( const Reference
< XAnimationNode
>& xNode
)
3085 DBG_ASSERT( xNode
.is(), "sd::EffectSequenceHelper::createEffectsequence(), illegal argument" );
3087 if( xNode
.is() ) try
3089 Reference
< XEnumerationAccess
> xEnumerationAccess( xNode
, UNO_QUERY_THROW
);
3090 Reference
< XEnumeration
> xEnumeration( xEnumerationAccess
->createEnumeration(), UNO_QUERY_THROW
);
3091 while( xEnumeration
->hasMoreElements() )
3093 Reference
< XAnimationNode
> xChildNode( xEnumeration
->nextElement(), UNO_QUERY_THROW
);
3095 createEffects( xChildNode
);
3100 DBG_ERROR( "sd::EffectSequenceHelper::createEffectsequence(), exception cought!" );
3104 // --------------------------------------------------------------------
3106 void EffectSequenceHelper::createEffects( const Reference
< XAnimationNode
>& xNode
)
3108 DBG_ASSERT( xNode
.is(), "sd::EffectSequenceHelper::createEffects(), illegal argument" );
3110 if( xNode
.is() ) try
3112 Reference
< XEnumerationAccess
> xEnumerationAccess( xNode
, UNO_QUERY_THROW
);
3113 Reference
< XEnumeration
> xEnumeration( xEnumerationAccess
->createEnumeration(), UNO_QUERY_THROW
);
3114 while( xEnumeration
->hasMoreElements() )
3116 Reference
< XAnimationNode
> xChildNode( xEnumeration
->nextElement(), UNO_QUERY_THROW
);
3118 switch( xChildNode
->getType() )
3121 case AnimationNodeType::PAR
:
3122 case AnimationNodeType::ITERATE
:
3124 CustomAnimationEffectPtr
pEffect( new CustomAnimationEffect( xChildNode
) );
3126 if( pEffect
->mnNodeType
!= -1 )
3128 pEffect
->setEffectSequence( this );
3129 maEffects
.push_back(pEffect
);
3134 // found an after effect
3135 case AnimationNodeType::SET
:
3136 case AnimationNodeType::ANIMATECOLOR
:
3138 processAfterEffect( xChildNode
);
3144 catch( Exception
& e
)
3147 DBG_ERROR( "sd::EffectSequenceHelper::createEffects(), exception cought!" );
3151 // --------------------------------------------------------------------
3153 void EffectSequenceHelper::processAfterEffect( const Reference
< XAnimationNode
>& xNode
)
3157 Reference
< XAnimationNode
> xMaster
;
3159 Sequence
< NamedValue
> aUserData( xNode
->getUserData() );
3160 sal_Int32 nLength
= aUserData
.getLength();
3161 const NamedValue
* p
= aUserData
.getConstArray();
3165 if( p
->Name
.equalsAscii( "master-element" ) )
3167 p
->Value
>>= xMaster
;
3173 // only process if this is a valid after effect
3176 CustomAnimationEffectPtr pMasterEffect
;
3178 // find the master effect
3179 stl_CustomAnimationEffect_search_node_predict
aSearchPredict( xMaster
);
3180 EffectSequence::iterator
aIter( std::find_if( maEffects
.begin(), maEffects
.end(), aSearchPredict
) );
3181 if( aIter
!= maEffects
.end() )
3182 pMasterEffect
= (*aIter
);
3184 if( pMasterEffect
.get() )
3186 pMasterEffect
->setHasAfterEffect( true );
3188 // find out what kind of after effect this is
3189 if( xNode
->getType() == AnimationNodeType::ANIMATECOLOR
)
3192 Reference
< XAnimate
> xAnimate( xNode
, UNO_QUERY_THROW
);
3193 pMasterEffect
->setDimColor( xAnimate
->getTo() );
3194 pMasterEffect
->setAfterEffectOnNext( true );
3199 Reference
< XChild
> xNodeChild( xNode
, UNO_QUERY_THROW
);
3200 Reference
< XChild
> xMasterChild( xMaster
, UNO_QUERY_THROW
);
3201 pMasterEffect
->setAfterEffectOnNext( xNodeChild
->getParent() != xMasterChild
->getParent() );
3206 catch( Exception
& e
)
3209 DBG_ERROR( "sd::EffectSequenceHelper::processAfterEffect(), exception cought!" );
3214 double EffectSequenceHelper::calculateIterateNodeDuration(
3216 Reference< i18n::XBreakIterator > xBI( ImplGetBreakIterator() );
3219 sal_Int32 nNextCellBreak( xBI->nextCharacters(rTxt, nIdx, rLocale, i18n::CharacterIteratorMode::SKIPCELL, 0, nDone) );
3220 i18n::Boundary nNextWordBoundary( xBI->getWordBoundary(rTxt, nIdx, rLocale, i18n::WordType::ANY_WORD, sal_True) );
3221 sal_Int32 nNextSentenceBreak( xBI->endOfSentence(rTxt, nIdx, rLocale) );
3223 const sal_Int32 nEndPos( nIdx + nLen );
3224 sal_Int32 i, currOffset(0);
3225 for( i=nIdx; i<nEndPos; ++i )
3227 // TODO: Check whether position update is valid for CTL/BiDi
3228 rOutDev.DrawText( rPos + Point(currOffset,0), rTxt, i, 1 );
3229 currOffset = *pDXArray++;
3231 // issue the comments at the respective break positions
3232 if( i == nNextCellBreak )
3234 rMtf.AddAction( new MetaCommentAction( "XTEXT_EOC" ) );
3235 nNextCellBreak = xBI->nextCharacters(rTxt, i, rLocale, i18n::CharacterIteratorMode::SKIPCELL, 1, nDone);
3237 if( i == nNextWordBoundary.endPos )
3239 rMtf.AddAction( new MetaCommentAction( "XTEXT_EOW" ) );
3240 nNextWordBoundary = xBI->getWordBoundary(rTxt, i+1, rLocale, i18n::WordType::ANY_WORD, sal_True);
3242 if( i == nNextSentenceBreak )
3244 rMtf.AddAction( new MetaCommentAction( "XTEXT_EOS" ) );
3245 nNextSentenceBreak = xBI->endOfSentence(rTxt, i+1, rLocale);
3251 // ====================================================================
3253 class AnimationChangeListener
: public cppu::WeakImplHelper1
< XChangesListener
>
3256 AnimationChangeListener( MainSequence
* pMainSequence
) : mpMainSequence( pMainSequence
) {}
3258 virtual void SAL_CALL
changesOccurred( const ::com::sun::star::util::ChangesEvent
& Event
) throw (RuntimeException
);
3259 virtual void SAL_CALL
disposing( const ::com::sun::star::lang::EventObject
& Source
) throw (RuntimeException
);
3261 MainSequence
* mpMainSequence
;
3264 void SAL_CALL
AnimationChangeListener::changesOccurred( const ::com::sun::star::util::ChangesEvent
& ) throw (RuntimeException
)
3266 if( mpMainSequence
)
3267 mpMainSequence
->startRecreateTimer();
3270 void SAL_CALL
AnimationChangeListener::disposing( const ::com::sun::star::lang::EventObject
& ) throw (RuntimeException
)
3274 // ====================================================================
3276 MainSequence::MainSequence()
3277 : mxTimingRootNode( ::comphelper::getProcessServiceFactory()->createInstance(OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.animations.SequenceTimeContainer"))), UNO_QUERY
)
3278 , mbRebuilding( false )
3279 , mnRebuildLockGuard( 0 )
3280 , mbPendingRebuildRequest( false )
3282 if( mxTimingRootNode
.is() )
3284 Sequence
< ::com::sun::star::beans::NamedValue
> aUserData( 1 );
3285 aUserData
[0].Name
= OUString( RTL_CONSTASCII_USTRINGPARAM( "node-type" ) );
3286 aUserData
[0].Value
<<= ::com::sun::star::presentation::EffectNodeType::MAIN_SEQUENCE
;
3287 mxTimingRootNode
->setUserData( aUserData
);
3292 // --------------------------------------------------------------------
3294 MainSequence::MainSequence( const ::com::sun::star::uno::Reference
< ::com::sun::star::animations::XAnimationNode
>& xNode
)
3295 : mxTimingRootNode( xNode
, UNO_QUERY
)
3296 , mbRebuilding( false )
3297 , mnRebuildLockGuard( 0 )
3298 , mbPendingRebuildRequest( false )
3299 , mbIgnoreChanges( 0 )
3304 // --------------------------------------------------------------------
3306 MainSequence::~MainSequence()
3311 // --------------------------------------------------------------------
3313 void MainSequence::init()
3315 mnSequenceType
= EffectNodeType::MAIN_SEQUENCE
;
3317 maTimer
.SetTimeoutHdl( LINK(this, MainSequence
, onTimerHdl
) );
3318 maTimer
.SetTimeout(500);
3320 mxChangesListener
.set( new AnimationChangeListener( this ) );
3322 createMainSequence();
3325 // --------------------------------------------------------------------
3327 void MainSequence::reset( const ::com::sun::star::uno::Reference
< ::com::sun::star::animations::XAnimationNode
>& xTimingRootNode
)
3331 mxTimingRootNode
.set( xTimingRootNode
, UNO_QUERY
);
3333 createMainSequence();
3336 // --------------------------------------------------------------------
3338 Reference
< ::com::sun::star::animations::XAnimationNode
> MainSequence::getRootNode()
3340 DBG_ASSERT( mnRebuildLockGuard
== 0, "MainSequence::getRootNode(), rebuild is locked, ist this really what you want?" );
3342 if( maTimer
.IsActive() && mbTimerMode
)
3344 // force a rebuild NOW if one is pending
3349 return EffectSequenceHelper::getRootNode();
3352 // --------------------------------------------------------------------
3354 void MainSequence::createMainSequence()
3356 if( mxTimingRootNode
.is() ) try
3358 Reference
< XEnumerationAccess
> xEnumerationAccess( mxTimingRootNode
, UNO_QUERY_THROW
);
3359 Reference
< XEnumeration
> xEnumeration( xEnumerationAccess
->createEnumeration(), UNO_QUERY_THROW
);
3360 while( xEnumeration
->hasMoreElements() )
3362 Reference
< XAnimationNode
> xChildNode( xEnumeration
->nextElement(), UNO_QUERY_THROW
);
3363 sal_Int32 nNodeType
= CustomAnimationEffect::get_node_type( xChildNode
);
3364 if( nNodeType
== EffectNodeType::MAIN_SEQUENCE
)
3366 mxSequenceRoot
.set( xChildNode
, UNO_QUERY
);
3367 EffectSequenceHelper::create( xChildNode
);
3369 else if( nNodeType
== EffectNodeType::INTERACTIVE_SEQUENCE
)
3371 Reference
< XTimeContainer
> xInteractiveRoot( xChildNode
, UNO_QUERY_THROW
);
3372 InteractiveSequencePtr
pIS( new InteractiveSequence( xInteractiveRoot
, this ) );
3373 pIS
->addListener( this );
3374 maInteractiveSequenceList
.push_back( pIS
);
3378 // see if we have a mainsequence at all. if not, create one...
3379 if( !mxSequenceRoot
.is() )
3381 mxSequenceRoot
= Reference
< XTimeContainer
>::query(::comphelper::getProcessServiceFactory()->createInstance(OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.animations.SequenceTimeContainer"))));
3382 if( mxSequenceRoot
.is() )
3384 uno::Sequence
< ::com::sun::star::beans::NamedValue
> aUserData( 1 );
3385 aUserData
[0].Name
= OUString( RTL_CONSTASCII_USTRINGPARAM( "node-type" ) );
3386 aUserData
[0].Value
<<= ::com::sun::star::presentation::EffectNodeType::MAIN_SEQUENCE
;
3387 mxSequenceRoot
->setUserData( aUserData
);
3389 // empty sequence until now, set duration to 0.0
3390 // explicitely (otherwise, this sequence will never
3392 mxSequenceRoot
->setDuration( makeAny((double)0.0) );
3394 Reference
< XAnimationNode
> xMainSequenceNode( mxSequenceRoot
, UNO_QUERY_THROW
);
3395 mxTimingRootNode
->appendChild( xMainSequenceNode
);
3403 Reference
< XChangesNotifier
> xNotifier( mxTimingRootNode
, UNO_QUERY
);
3404 if( xNotifier
.is() )
3405 xNotifier
->addChangesListener( mxChangesListener
);
3407 catch( Exception
& e
)
3410 DBG_ERROR( "sd::MainSequence::create(), exception cought!" );
3414 DBG_ASSERT( mxSequenceRoot
.is(), "sd::MainSequence::create(), found no main sequence!" );
3417 // --------------------------------------------------------------------
3419 void MainSequence::reset()
3421 EffectSequenceHelper::reset();
3423 InteractiveSequenceList::iterator aIter
;
3424 for( aIter
= maInteractiveSequenceList
.begin(); aIter
!= maInteractiveSequenceList
.end(); aIter
++ )
3426 maInteractiveSequenceList
.clear();
3430 Reference
< XChangesNotifier
> xNotifier( mxTimingRootNode
, UNO_QUERY
);
3431 if( xNotifier
.is() )
3432 xNotifier
->removeChangesListener( mxChangesListener
);
3440 // --------------------------------------------------------------------
3442 InteractiveSequencePtr
MainSequence::createInteractiveSequence( const ::com::sun::star::uno::Reference
< ::com::sun::star::drawing::XShape
>& xShape
)
3444 InteractiveSequencePtr pIS
;
3446 // create a new interactive sequence container
3447 Reference
< XTimeContainer
> xISRoot( ::comphelper::getProcessServiceFactory()->createInstance(OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.animations.SequenceTimeContainer"))), UNO_QUERY
);
3448 DBG_ASSERT( xISRoot
.is(), "sd::MainSequence::createInteractiveSequence(), could not create \"com.sun.star.animations.SequenceTimeContainer\"!");
3451 uno::Sequence
< ::com::sun::star::beans::NamedValue
> aUserData( 1 );
3452 aUserData
[0].Name
= OUString( RTL_CONSTASCII_USTRINGPARAM( "node-type" ) );
3453 aUserData
[0].Value
<<= ::com::sun::star::presentation::EffectNodeType::INTERACTIVE_SEQUENCE
;
3454 xISRoot
->setUserData( aUserData
);
3456 Reference
< XChild
> xChild( mxSequenceRoot
, UNO_QUERY_THROW
);
3457 Reference
< XAnimationNode
> xISNode( xISRoot
, UNO_QUERY_THROW
);
3458 Reference
< XTimeContainer
> xParent( xChild
->getParent(), UNO_QUERY_THROW
);
3459 xParent
->appendChild( xISNode
);
3461 pIS
.reset( new InteractiveSequence( xISRoot
, this) );
3462 pIS
->setTriggerShape( xShape
);
3463 pIS
->addListener( this );
3464 maInteractiveSequenceList
.push_back( pIS
);
3468 // --------------------------------------------------------------------
3470 CustomAnimationEffectPtr
MainSequence::findEffect( const ::com::sun::star::uno::Reference
< ::com::sun::star::animations::XAnimationNode
>& xNode
) const
3472 CustomAnimationEffectPtr pEffect
= EffectSequenceHelper::findEffect( xNode
);
3474 if( pEffect
.get() == 0 )
3476 InteractiveSequenceList::const_iterator aIter
;
3477 for( aIter
= maInteractiveSequenceList
.begin(); (aIter
!= maInteractiveSequenceList
.end()) && (pEffect
.get() == 0); aIter
++ )
3479 pEffect
= (*aIter
)->findEffect( xNode
);
3485 // --------------------------------------------------------------------
3487 sal_Int32
MainSequence::getOffsetFromEffect( const CustomAnimationEffectPtr
& pEffect
) const
3489 sal_Int32 nOffset
= EffectSequenceHelper::getOffsetFromEffect( pEffect
);
3494 nOffset
= EffectSequenceHelper::getCount();
3496 InteractiveSequenceList::const_iterator aIter
;
3497 for( aIter
= maInteractiveSequenceList
.begin(); aIter
!= maInteractiveSequenceList
.end(); aIter
++ )
3499 sal_Int32 nTemp
= (*aIter
)->getOffsetFromEffect( pEffect
);
3501 return nOffset
+ nTemp
;
3503 nOffset
+= (*aIter
)->getCount();
3509 // --------------------------------------------------------------------
3511 CustomAnimationEffectPtr
MainSequence::getEffectFromOffset( sal_Int32 nOffset
) const
3515 if( nOffset
< getCount() )
3516 return EffectSequenceHelper::getEffectFromOffset( nOffset
);
3518 nOffset
-= getCount();
3520 InteractiveSequenceList::const_iterator
aIter( maInteractiveSequenceList
.begin() );
3522 while( (aIter
!= maInteractiveSequenceList
.end()) && (nOffset
> (*aIter
)->getCount()) )
3523 nOffset
-= (*aIter
++)->getCount();
3525 if( (aIter
!= maInteractiveSequenceList
.end()) && (nOffset
>= 0) )
3526 return (*aIter
)->getEffectFromOffset( nOffset
);
3529 CustomAnimationEffectPtr pEffect
;
3533 // --------------------------------------------------------------------
3535 bool MainSequence::disposeShape( const Reference
< XShape
>& xShape
)
3537 bool bChanges
= EffectSequenceHelper::disposeShape( xShape
);
3539 InteractiveSequenceList::iterator aIter
;
3540 for( aIter
= maInteractiveSequenceList
.begin(); aIter
!= maInteractiveSequenceList
.end(); )
3542 if( (*aIter
)->getTriggerShape() == xShape
)
3544 aIter
= maInteractiveSequenceList
.erase( aIter
);
3549 bChanges
|= (*aIter
++)->disposeShape( xShape
);
3554 startRebuildTimer();
3559 // --------------------------------------------------------------------
3561 bool MainSequence::hasEffect( const com::sun::star::uno::Reference
< com::sun::star::drawing::XShape
>& xShape
)
3563 if( EffectSequenceHelper::hasEffect( xShape
) )
3566 InteractiveSequenceList::iterator aIter
;
3567 for( aIter
= maInteractiveSequenceList
.begin(); aIter
!= maInteractiveSequenceList
.end(); )
3569 if( (*aIter
)->getTriggerShape() == xShape
)
3572 if( (*aIter
++)->hasEffect( xShape
) )
3579 // --------------------------------------------------------------------
3581 void MainSequence::insertTextRange( const com::sun::star::uno::Any
& aTarget
)
3583 EffectSequenceHelper::insertTextRange( aTarget
);
3585 InteractiveSequenceList::iterator aIter
;
3586 for( aIter
= maInteractiveSequenceList
.begin(); aIter
!= maInteractiveSequenceList
.end(); aIter
++ )
3588 (*aIter
)->insertTextRange( aTarget
);
3591 // --------------------------------------------------------------------
3593 void MainSequence::disposeTextRange( const com::sun::star::uno::Any
& aTarget
)
3595 EffectSequenceHelper::disposeTextRange( aTarget
);
3597 InteractiveSequenceList::iterator aIter
;
3598 for( aIter
= maInteractiveSequenceList
.begin(); aIter
!= maInteractiveSequenceList
.end(); aIter
++ )
3600 (*aIter
)->disposeTextRange( aTarget
);
3604 // --------------------------------------------------------------------
3606 /** callback from the sd::View when an object just left text edit mode */
3607 void MainSequence::onTextChanged( const Reference
< XShape
>& xShape
)
3609 EffectSequenceHelper::onTextChanged( xShape
);
3611 InteractiveSequenceList::iterator aIter
;
3612 for( aIter
= maInteractiveSequenceList
.begin(); aIter
!= maInteractiveSequenceList
.end(); aIter
++ )
3614 (*aIter
)->onTextChanged( xShape
);
3618 // --------------------------------------------------------------------
3620 void EffectSequenceHelper::onTextChanged( const Reference
< XShape
>& xShape
)
3622 bool bChanges
= false;
3624 EffectSequence::iterator aIter
;
3625 for( aIter
= maEffects
.begin(); aIter
!= maEffects
.end(); aIter
++ )
3627 if( (*aIter
)->getTargetShape() == xShape
)
3628 bChanges
|= (*aIter
)->checkForText();
3632 EffectSequenceHelper::implRebuild();
3635 // --------------------------------------------------------------------
3637 void MainSequence::rebuild()
3639 startRebuildTimer();
3642 // --------------------------------------------------------------------
3644 void MainSequence::lockRebuilds()
3646 mnRebuildLockGuard
++;
3649 // --------------------------------------------------------------------
3651 void MainSequence::unlockRebuilds()
3653 DBG_ASSERT( mnRebuildLockGuard
, "sd::MainSequence::unlockRebuilds(), no corresponding lockRebuilds() call!" );
3654 if( mnRebuildLockGuard
)
3655 mnRebuildLockGuard
--;
3657 if( (mnRebuildLockGuard
== 0) && mbPendingRebuildRequest
)
3659 mbPendingRebuildRequest
= false;
3660 startRebuildTimer();
3664 // --------------------------------------------------------------------
3666 void MainSequence::implRebuild()
3668 if( mnRebuildLockGuard
)
3670 mbPendingRebuildRequest
= true;
3674 mbRebuilding
= true;
3676 EffectSequenceHelper::implRebuild();
3678 InteractiveSequenceList::iterator
aIter( maInteractiveSequenceList
.begin() );
3679 const InteractiveSequenceList::iterator
aEnd( maInteractiveSequenceList
.end() );
3680 while( aIter
!= aEnd
)
3682 InteractiveSequencePtr
pIS( (*aIter
) );
3683 if( pIS
->maEffects
.empty() )
3685 // remove empty interactive sequences
3686 aIter
= maInteractiveSequenceList
.erase( aIter
);
3688 Reference
< XChild
> xChild( mxSequenceRoot
, UNO_QUERY_THROW
);
3689 Reference
< XTimeContainer
> xParent( xChild
->getParent(), UNO_QUERY_THROW
);
3690 Reference
< XAnimationNode
> xISNode( pIS
->mxSequenceRoot
, UNO_QUERY_THROW
);
3691 xParent
->removeChild( xISNode
);
3701 mbRebuilding
= false;
3704 // --------------------------------------------------------------------
3706 void MainSequence::notify_change()
3711 // --------------------------------------------------------------------
3713 bool MainSequence::setTrigger( const CustomAnimationEffectPtr
& pEffect
, const ::com::sun::star::uno::Reference
< ::com::sun::star::drawing::XShape
>& xTriggerShape
)
3715 EffectSequenceHelper
* pOldSequence
= pEffect
->getEffectSequence();
3717 EffectSequenceHelper
* pNewSequence
= 0;
3718 if( xTriggerShape
.is() )
3720 InteractiveSequenceList::iterator
aIter( maInteractiveSequenceList
.begin() );
3721 const InteractiveSequenceList::iterator
aEnd( maInteractiveSequenceList
.end() );
3722 while( aIter
!= aEnd
)
3724 InteractiveSequencePtr
pIS( (*aIter
++) );
3725 if( pIS
->getTriggerShape() == xTriggerShape
)
3727 pNewSequence
= pIS
.get();
3733 pNewSequence
= createInteractiveSequence( xTriggerShape
).get();
3737 pNewSequence
= this;
3740 if( pOldSequence
!= pNewSequence
)
3743 pOldSequence
->maEffects
.remove( pEffect
);
3745 pNewSequence
->maEffects
.push_back( pEffect
);
3746 pEffect
->setEffectSequence( pNewSequence
);
3756 // --------------------------------------------------------------------
3758 IMPL_LINK( MainSequence
, onTimerHdl
, Timer
*, EMPTYARG
)
3767 createMainSequence();
3773 // --------------------------------------------------------------------
3775 /** starts a timer that recreates the internal structure from the API core after 1 second */
3776 void MainSequence::startRecreateTimer()
3778 if( !mbRebuilding
&& (mbIgnoreChanges
== 0) )
3780 mbTimerMode
= false;
3785 // --------------------------------------------------------------------
3787 /** starts a timer that rebuilds the API core from the internal structure after 1 second */
3788 void MainSequence::startRebuildTimer()
3794 // ====================================================================
3796 InteractiveSequence::InteractiveSequence( const Reference
< XTimeContainer
>& xSequenceRoot
, MainSequence
* pMainSequence
)
3797 : EffectSequenceHelper( xSequenceRoot
), mpMainSequence( pMainSequence
)
3799 mnSequenceType
= EffectNodeType::INTERACTIVE_SEQUENCE
;
3803 if( mxSequenceRoot
.is() )
3805 Reference
< XEnumerationAccess
> xEnumerationAccess( mxSequenceRoot
, UNO_QUERY_THROW
);
3806 Reference
< XEnumeration
> xEnumeration( xEnumerationAccess
->createEnumeration(), UNO_QUERY_THROW
);
3807 while( !mxEventSource
.is() && xEnumeration
->hasMoreElements() )
3809 Reference
< XAnimationNode
> xChildNode( xEnumeration
->nextElement(), UNO_QUERY_THROW
);
3812 if( (xChildNode
->getBegin() >>= aEvent
) && (aEvent
.Trigger
== EventTrigger::ON_CLICK
) )
3813 aEvent
.Source
>>= mxEventSource
;
3817 catch( Exception
& e
)
3820 DBG_ERROR( "sd::InteractiveSequence::InteractiveSequence(), exception cought!" );
3825 // --------------------------------------------------------------------
3827 void InteractiveSequence::rebuild()
3829 mpMainSequence
->rebuild();
3832 void InteractiveSequence::implRebuild()
3834 EffectSequenceHelper::implRebuild();
3837 // --------------------------------------------------------------------
3839 MainSequenceRebuildGuard::MainSequenceRebuildGuard( const MainSequencePtr
& pMainSequence
)
3840 : mpMainSequence( pMainSequence
)
3842 if( mpMainSequence
.get() )
3843 mpMainSequence
->lockRebuilds();
3846 MainSequenceRebuildGuard::~MainSequenceRebuildGuard()
3848 if( mpMainSequence
.get() )
3849 mpMainSequence
->unlockRebuilds();