1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <tools/debug.hxx>
21 #include <com/sun/star/animations/AnimationNodeType.hpp>
22 #include <com/sun/star/animations/AnimateColor.hpp>
23 #include <com/sun/star/animations/AnimateMotion.hpp>
24 #include <com/sun/star/animations/AnimateSet.hpp>
25 #include <com/sun/star/animations/AnimationFill.hpp>
26 #include <com/sun/star/animations/AnimationTransformType.hpp>
27 #include <com/sun/star/animations/Audio.hpp>
28 #include <com/sun/star/animations/Command.hpp>
29 #include <com/sun/star/animations/Event.hpp>
30 #include <com/sun/star/animations/EventTrigger.hpp>
31 #include <com/sun/star/animations/IterateContainer.hpp>
32 #include <com/sun/star/animations/ParallelTimeContainer.hpp>
33 #include <com/sun/star/animations/SequenceTimeContainer.hpp>
34 #include <com/sun/star/animations/Timing.hpp>
35 #include <com/sun/star/animations/XCommand.hpp>
36 #include <com/sun/star/animations/XIterateContainer.hpp>
37 #include <com/sun/star/animations/XAnimateTransform.hpp>
38 #include <com/sun/star/animations/XAnimateMotion.hpp>
39 #include <com/sun/star/animations/XAnimate.hpp>
40 #include <com/sun/star/beans/NamedValue.hpp>
41 #include <com/sun/star/beans/XPropertySet.hpp>
42 #include <com/sun/star/container/XEnumerationAccess.hpp>
43 #include <com/sun/star/drawing/XDrawPage.hpp>
44 #include <com/sun/star/lang/XInitialization.hpp>
45 #include <com/sun/star/presentation/EffectNodeType.hpp>
46 #include <com/sun/star/presentation/EffectCommands.hpp>
47 #include <com/sun/star/presentation/EffectPresetClass.hpp>
48 #include <com/sun/star/presentation/ParagraphTarget.hpp>
49 #include <com/sun/star/presentation/ShapeAnimationSubType.hpp>
50 #include <com/sun/star/text/XText.hpp>
51 #include <com/sun/star/util/XCloneable.hpp>
52 #include <com/sun/star/util/XChangesNotifier.hpp>
53 #include <comphelper/processfactory.hxx>
54 #include <comphelper/sequence.hxx>
55 #include <com/sun/star/lang/Locale.hpp>
56 #include <com/sun/star/i18n/BreakIterator.hpp>
57 #include <com/sun/star/i18n/CharacterIteratorMode.hpp>
58 #include <com/sun/star/i18n/WordType.hpp>
59 #include <com/sun/star/presentation/TextAnimationType.hpp>
61 #include <basegfx/polygon/b2dpolypolygon.hxx>
62 #include <basegfx/polygon/b2dpolypolygontools.hxx>
63 #include <basegfx/matrix/b2dhommatrix.hxx>
64 #include <basegfx/range/b2drange.hxx>
65 #include <basegfx/matrix/b2dhommatrixtools.hxx>
69 #include <cppuhelper/implbase1.hxx>
71 #include <drawinglayer/geometry/viewinformation2d.hxx>
72 #include <svx/sdr/contact/viewcontact.hxx>
73 #include <svx/svdopath.hxx>
74 #include <svx/svdpage.hxx>
75 #include <svx/unoapi.hxx>
76 #include "CustomAnimationEffect.hxx"
77 #include <CustomAnimationPreset.hxx>
78 #include "animations.hxx"
80 using namespace ::com::sun::star
;
81 using namespace ::com::sun::star::uno
;
82 using namespace ::com::sun::star::presentation
;
83 using namespace ::com::sun::star::animations
;
85 using ::com::sun::star::container::XEnumerationAccess
;
86 using ::com::sun::star::container::XEnumeration
;
87 using ::com::sun::star::beans::NamedValue
;
88 using ::com::sun::star::container::XChild
;
89 using ::com::sun::star::container::XElementAccess
;
90 using ::com::sun::star::drawing::XShape
;
91 using ::com::sun::star::lang::XInitialization
;
92 using ::com::sun::star::drawing::XShapes
;
93 using ::com::sun::star::drawing::XDrawPage
;
94 using ::com::sun::star::text::XText
;
95 using ::com::sun::star::text::XTextRange
;
96 using ::com::sun::star::beans::XPropertySet
;
97 using ::com::sun::star::lang::XMultiServiceFactory
;
98 using ::com::sun::star::util::XCloneable
;
99 using ::com::sun::star::lang::Locale
;
100 using ::com::sun::star::util::XChangesNotifier
;
101 using ::com::sun::star::util::XChangesListener
;
105 class MainSequenceChangeGuard
108 MainSequenceChangeGuard( EffectSequenceHelper
* pSequence
)
110 mpMainSequence
= dynamic_cast< MainSequence
* >( pSequence
);
111 if( mpMainSequence
== 0 )
113 InteractiveSequence
* pI
= dynamic_cast< InteractiveSequence
* >( pSequence
);
115 mpMainSequence
= pI
->mpMainSequence
;
117 DBG_ASSERT( mpMainSequence
, "sd::MainSequenceChangeGuard::MainSequenceChangeGuard(), no main sequence to guard!" );
120 mpMainSequence
->mbIgnoreChanges
++;
123 ~MainSequenceChangeGuard()
126 mpMainSequence
->mbIgnoreChanges
++;
130 MainSequence
* mpMainSequence
;
133 CustomAnimationEffect::CustomAnimationEffect( const ::com::sun::star::uno::Reference
< ::com::sun::star::animations::XAnimationNode
>& xNode
)
138 mfAbsoluteDuration(-1.0),
141 mfIterateInterval(0.0),
143 mbHasText(sal_False
),
144 mfAcceleration( 1.0 ),
146 mbAutoReverse(false),
149 mpEffectSequence( 0 ),
150 mbHasAfterEffect(false),
151 mbAfterEffectOnNextEffect(false)
156 // --------------------------------------------------------------------
158 void CustomAnimationEffect::setNode( const ::com::sun::star::uno::Reference
< ::com::sun::star::animations::XAnimationNode
>& xNode
)
163 Sequence
< NamedValue
> aUserData( mxNode
->getUserData() );
164 sal_Int32 nLength
= aUserData
.getLength();
165 const NamedValue
* p
= aUserData
.getConstArray();
169 if ( p
->Name
== "node-type" )
171 p
->Value
>>= mnNodeType
;
173 else if ( p
->Name
== "preset-id" )
175 p
->Value
>>= maPresetId
;
177 else if ( p
->Name
== "preset-sub-type" )
179 p
->Value
>>= maPresetSubType
;
181 else if ( p
->Name
== "preset-class" )
183 p
->Value
>>= mnPresetClass
;
185 else if ( p
->Name
== "preset-property" )
187 p
->Value
>>= maProperty
;
189 else if ( p
->Name
== "group-id" )
191 p
->Value
>>= mnGroupId
;
197 // get effect start time
198 mxNode
->getBegin() >>= mfBegin
;
200 mfAcceleration
= mxNode
->getAcceleration();
201 mfDecelerate
= mxNode
->getDecelerate();
202 mbAutoReverse
= mxNode
->getAutoReverse();
204 // get iteration data
205 Reference
< XIterateContainer
> xIter( mxNode
, UNO_QUERY
);
208 mfIterateInterval
= xIter
->getIterateInterval();
209 mnIterateType
= xIter
->getIterateType();
210 maTarget
= xIter
->getTarget();
211 mnTargetSubItem
= xIter
->getSubItem();
215 mfIterateInterval
= 0.0f
;
219 // calculate effect duration and get target shape
220 Reference
< XEnumerationAccess
> xEnumerationAccess( mxNode
, UNO_QUERY
);
221 if( xEnumerationAccess
.is() )
223 Reference
< XEnumeration
> xEnumeration( xEnumerationAccess
->createEnumeration(), UNO_QUERY
);
224 if( xEnumeration
.is() )
226 while( xEnumeration
->hasMoreElements() )
228 Reference
< XAnimationNode
> xChildNode( xEnumeration
->nextElement(), UNO_QUERY
);
229 if( !xChildNode
.is() )
232 if( xChildNode
->getType() == AnimationNodeType::AUDIO
)
234 mxAudio
.set( xChildNode
, UNO_QUERY
);
236 else if( xChildNode
->getType() == AnimationNodeType::COMMAND
)
238 Reference
< XCommand
> xCommand( xChildNode
, UNO_QUERY
);
241 mnCommand
= xCommand
->getCommand();
242 if( !maTarget
.hasValue() )
243 maTarget
= xCommand
->getTarget();
249 double fDuration
= 0.0;
250 xChildNode
->getBegin() >>= fBegin
;
251 xChildNode
->getDuration() >>= fDuration
;
254 if( fDuration
> mfDuration
)
255 mfDuration
= fDuration
;
257 // no target shape yet?
258 if( !maTarget
.hasValue() )
261 Reference
< XAnimate
> xAnimate( xChildNode
, UNO_QUERY
);
264 maTarget
= xAnimate
->getTarget();
265 mnTargetSubItem
= xAnimate
->getSubItem();
273 mfAbsoluteDuration
= mfDuration
;
274 double fRepeatCount
= 1.0;
275 if( (mxNode
->getRepeatCount()) >>= fRepeatCount
)
276 mfAbsoluteDuration
*= fRepeatCount
;
281 // --------------------------------------------------------------------
283 sal_Int32
CustomAnimationEffect::getNumberOfSubitems( const Any
& aTarget
, sal_Int16 nIterateType
)
285 sal_Int32 nSubItems
= 0;
289 // first get target text
290 sal_Int32 nOnlyPara
= -1;
292 Reference
< XText
> xShape
;
296 ParagraphTarget aParaTarget
;
297 if( aTarget
>>= aParaTarget
)
299 xShape
.set( aParaTarget
.Shape
, UNO_QUERY
);
300 nOnlyPara
= aParaTarget
.Paragraph
;
304 // now use the break iterator to iterate over the given text
305 // and count the sub items
309 // TODO/LATER: Optimize this, don't create a break iterator each time
310 Reference
< uno::XComponentContext
> xContext( ::comphelper::getProcessComponentContext() );
311 Reference
< i18n::XBreakIterator
> xBI
= i18n::BreakIterator::create(xContext
);
313 Reference
< XEnumerationAccess
> xEA( xShape
, UNO_QUERY_THROW
);
314 Reference
< XEnumeration
> xEnumeration( xEA
->createEnumeration(), UNO_QUERY_THROW
);
316 const OUString
aStrLocaleName( "CharLocale" );
317 Reference
< XTextRange
> xParagraph
;
320 while( xEnumeration
->hasMoreElements() )
322 xEnumeration
->nextElement() >>= xParagraph
;
324 // skip this if its not the only paragraph we want to count
325 if( (nOnlyPara
!= -1) && (nOnlyPara
!= nPara
) )
328 if( nIterateType
== TextAnimationType::BY_PARAGRAPH
)
334 const OUString
aText( xParagraph
->getString() );
335 Reference
< XPropertySet
> xSet( xParagraph
, UNO_QUERY_THROW
);
336 xSet
->getPropertyValue( aStrLocaleName
) >>= aLocale
;
339 const sal_Int32 nEndPos
= aText
.getLength();
341 if( nIterateType
== TextAnimationType::BY_WORD
)
343 for( nPos
= 0; nPos
< nEndPos
; nPos
++ )
345 nPos
= xBI
->getWordBoundary(aText
, nPos
, aLocale
, i18n::WordType::ANY_WORD
, sal_True
).endPos
;
353 for( nPos
= 0; nPos
< nEndPos
; nPos
++ )
355 nPos
= xBI
->nextCharacters(aText
, nPos
, aLocale
, i18n::CharacterIteratorMode::SKIPCELL
, 0, nDone
);
361 if( nPara
== nOnlyPara
)
371 OSL_FAIL( "sd::CustomAnimationEffect::getNumberOfSubitems(), exception caught!" );
377 // --------------------------------------------------------------------
379 CustomAnimationEffect::~CustomAnimationEffect()
383 // --------------------------------------------------------------------
385 CustomAnimationEffectPtr
CustomAnimationEffect::clone() const
387 Reference
< XCloneable
> xCloneable( mxNode
, UNO_QUERY_THROW
);
388 Reference
< XAnimationNode
> xNode( xCloneable
->createClone(), UNO_QUERY_THROW
);
389 CustomAnimationEffectPtr
pEffect( new CustomAnimationEffect( xNode
) );
390 pEffect
->setEffectSequence( getEffectSequence() );
394 // --------------------------------------------------------------------
396 sal_Int32
CustomAnimationEffect::get_node_type( const Reference
< XAnimationNode
>& xNode
)
398 sal_Int16 nNodeType
= -1;
402 Sequence
< NamedValue
> aUserData( xNode
->getUserData() );
403 sal_Int32 nLength
= aUserData
.getLength();
406 const NamedValue
* p
= aUserData
.getConstArray();
409 if ( p
->Name
== "node-type" )
411 p
->Value
>>= nNodeType
;
422 // --------------------------------------------------------------------
424 void CustomAnimationEffect::setPresetClass( sal_Int16 nPresetClass
)
426 if( mnPresetClass
!= nPresetClass
)
428 mnPresetClass
= nPresetClass
;
431 // first try to find a "preset-class" entry in the user data
433 Sequence
< NamedValue
> aUserData( mxNode
->getUserData() );
434 sal_Int32 nLength
= aUserData
.getLength();
438 NamedValue
* p
= aUserData
.getArray();
441 if ( p
->Name
== "preset-class" )
443 p
->Value
<<= mnPresetClass
;
451 // no "node-type" entry inside user data, so add it
454 nLength
= aUserData
.getLength();
455 aUserData
.realloc( nLength
+ 1);
456 aUserData
[nLength
].Name
= "preset-class";
457 aUserData
[nLength
].Value
<<= mnPresetClass
;
460 mxNode
->setUserData( aUserData
);
465 void CustomAnimationEffect::setNodeType( sal_Int16 nNodeType
)
467 if( mnNodeType
!= nNodeType
)
469 mnNodeType
= nNodeType
;
472 // first try to find a "node-type" entry in the user data
474 Sequence
< NamedValue
> aUserData( mxNode
->getUserData() );
475 sal_Int32 nLength
= aUserData
.getLength();
479 NamedValue
* p
= aUserData
.getArray();
482 if ( p
->Name
== "node-type" )
484 p
->Value
<<= mnNodeType
;
492 // no "node-type" entry inside user data, so add it
495 nLength
= aUserData
.getLength();
496 aUserData
.realloc( nLength
+ 1);
497 aUserData
[nLength
].Name
= "node-type";
498 aUserData
[nLength
].Value
<<= mnNodeType
;
501 mxNode
->setUserData( aUserData
);
506 // --------------------------------------------------------------------
508 void CustomAnimationEffect::setGroupId( sal_Int32 nGroupId
)
510 mnGroupId
= nGroupId
;
513 // first try to find a "group-id" entry in the user data
515 Sequence
< NamedValue
> aUserData( mxNode
->getUserData() );
516 sal_Int32 nLength
= aUserData
.getLength();
520 NamedValue
* p
= aUserData
.getArray();
523 if ( p
->Name
== "group-id" )
525 p
->Value
<<= mnGroupId
;
533 // no "node-type" entry inside user data, so add it
536 nLength
= aUserData
.getLength();
537 aUserData
.realloc( nLength
+ 1);
538 aUserData
[nLength
].Name
= "group-id";
539 aUserData
[nLength
].Value
<<= mnGroupId
;
542 mxNode
->setUserData( aUserData
);
546 // --------------------------------------------------------------------
548 /** checks if the text for this effect has changed and updates internal flags.
549 returns true if something changed.
551 bool CustomAnimationEffect::checkForText()
553 bool bChange
= false;
555 Reference
< XText
> xText
;
557 if( maTarget
.getValueType() == ::getCppuType((const ParagraphTarget
*)0) )
560 ParagraphTarget aParaTarget
;
561 maTarget
>>= aParaTarget
;
563 xText
= Reference
< XText
>::query( aParaTarget
.Shape
);
568 Reference
< XEnumerationAccess
> xEA( xText
, UNO_QUERY
);
571 Reference
< XEnumeration
> xEnumeration( xEA
->createEnumeration(), UNO_QUERY
);
572 if( xEnumeration
.is() )
574 sal_Bool bHasText
= xEnumeration
->hasMoreElements();
575 bChange
|= bHasText
!= mbHasText
;
576 mbHasText
= bHasText
;
578 sal_Int32 nPara
= aParaTarget
.Paragraph
;
580 while( xEnumeration
->hasMoreElements() && nPara
-- )
581 xEnumeration
->nextElement();
583 if( xEnumeration
->hasMoreElements() )
585 Reference
< XPropertySet
> xParaSet
;
586 xEnumeration
->nextElement() >>= xParaSet
;
589 sal_Int32 nParaDepth
= 0;
590 const OUString
strNumberingLevel( "NumberingLevel" );
591 xParaSet
->getPropertyValue( strNumberingLevel
) >>= nParaDepth
;
592 bChange
|= nParaDepth
!= mnParaDepth
;
593 mnParaDepth
= nParaDepth
;
603 sal_Bool bHasText
= xText
.is() && !xText
->getString().isEmpty();
604 bChange
|= bHasText
!= mbHasText
;
605 mbHasText
= bHasText
;
608 bChange
|= calculateIterateDuration();
612 bool CustomAnimationEffect::calculateIterateDuration()
614 bool bChange
= false;
616 // if we have an iteration, we must also calculate the
617 // 'true' container duration, that is
618 // ( ( is form animated ) ? [contained effects duration] : 0 ) +
619 // ( [number of animated children] - 1 ) * [interval-delay] + [contained effects duration]
620 Reference
< XIterateContainer
> xIter( mxNode
, UNO_QUERY
);
623 double fDuration
= mfDuration
;
624 const double fSubEffectDuration
= mfDuration
;
626 if( mnTargetSubItem
!= ShapeAnimationSubType::ONLY_BACKGROUND
) // does not make sense for iterate container but better check
628 const sal_Int32 nSubItems
= getNumberOfSubitems( maTarget
, mnIterateType
);
631 const double f
= (nSubItems
-1) * mfIterateInterval
;
636 // if we also animate the form first, we have to add the
637 // sub effect duration to the whole effect duration
638 if( mnTargetSubItem
== ShapeAnimationSubType::AS_WHOLE
)
639 fDuration
+= fSubEffectDuration
;
641 bChange
|= fDuration
!= mfAbsoluteDuration
;
642 mfAbsoluteDuration
= fDuration
;
648 // --------------------------------------------------------------------
650 void CustomAnimationEffect::setTarget( const ::com::sun::star::uno::Any
& rTarget
)
656 // first, check special case for random node
657 Reference
< XInitialization
> xInit( mxNode
, UNO_QUERY
);
660 const Sequence
< Any
> aArgs( &maTarget
, 1 );
661 xInit
->initialize( aArgs
);
665 Reference
< XIterateContainer
> xIter( mxNode
, UNO_QUERY
);
668 xIter
->setTarget(maTarget
);
672 Reference
< XEnumerationAccess
> xEnumerationAccess( mxNode
, UNO_QUERY
);
673 if( xEnumerationAccess
.is() )
675 Reference
< XEnumeration
> xEnumeration( xEnumerationAccess
->createEnumeration(), UNO_QUERY
);
676 if( xEnumeration
.is() )
678 while( xEnumeration
->hasMoreElements() )
680 const Any
aElem( xEnumeration
->nextElement() );
681 Reference
< XAnimate
> xAnimate( aElem
, UNO_QUERY
);
683 xAnimate
->setTarget( rTarget
);
686 Reference
< XCommand
> xCommand( aElem
, UNO_QUERY
);
688 xCommand
->setTarget( rTarget
);
699 OSL_FAIL( "sd::CustomAnimationEffect::setTarget(), exception caught!" );
703 // --------------------------------------------------------------------
705 void CustomAnimationEffect::setTargetSubItem( sal_Int16 nSubItem
)
709 mnTargetSubItem
= nSubItem
;
711 Reference
< XIterateContainer
> xIter( mxNode
, UNO_QUERY
);
714 xIter
->setSubItem(mnTargetSubItem
);
718 Reference
< XEnumerationAccess
> xEnumerationAccess( mxNode
, UNO_QUERY
);
719 if( xEnumerationAccess
.is() )
721 Reference
< XEnumeration
> xEnumeration( xEnumerationAccess
->createEnumeration(), UNO_QUERY
);
722 if( xEnumeration
.is() )
724 while( xEnumeration
->hasMoreElements() )
726 Reference
< XAnimate
> xAnimate( xEnumeration
->nextElement(), UNO_QUERY
);
728 xAnimate
->setSubItem( mnTargetSubItem
);
736 OSL_FAIL( "sd::CustomAnimationEffect::setTargetSubItem(), exception caught!" );
740 // --------------------------------------------------------------------
742 void CustomAnimationEffect::setDuration( double fDuration
)
744 if( (mfDuration
!= -1.0) && (mfDuration
!= fDuration
) ) try
746 double fScale
= fDuration
/ mfDuration
;
747 mfDuration
= fDuration
;
748 double fRepeatCount
= 1.0;
749 getRepeatCount() >>= fRepeatCount
;
750 mfAbsoluteDuration
= mfDuration
* fRepeatCount
;
752 // calculate effect duration and get target shape
753 Reference
< XEnumerationAccess
> xEnumerationAccess( mxNode
, UNO_QUERY
);
754 if( xEnumerationAccess
.is() )
756 Reference
< XEnumeration
> xEnumeration( xEnumerationAccess
->createEnumeration(), UNO_QUERY
);
757 if( xEnumeration
.is() )
759 while( xEnumeration
->hasMoreElements() )
761 Reference
< XAnimationNode
> xChildNode( xEnumeration
->nextElement(), UNO_QUERY
);
762 if( !xChildNode
.is() )
766 double fChildBegin
= 0.0;
767 xChildNode
->getBegin() >>= fChildBegin
;
768 if( fChildBegin
!= 0.0 )
770 fChildBegin
*= fScale
;
771 xChildNode
->setBegin( makeAny( fChildBegin
) );
774 double fChildDuration
= 0.0;
775 xChildNode
->getDuration() >>= fChildDuration
;
776 if( fChildDuration
!= 0.0 )
778 fChildDuration
*= fScale
;
779 xChildNode
->setDuration( makeAny( fChildDuration
) );
784 calculateIterateDuration();
788 OSL_FAIL( "sd::CustomAnimationEffect::setDuration(), exception caught!" );
792 // --------------------------------------------------------------------
794 void CustomAnimationEffect::setBegin( double fBegin
)
796 if( mxNode
.is() ) try
799 mxNode
->setBegin( makeAny( fBegin
) );
803 OSL_FAIL( "sd::CustomAnimationEffect::setBegin(), exception caught!" );
807 // --------------------------------------------------------------------
809 void CustomAnimationEffect::setAcceleration( double fAcceleration
)
811 if( mxNode
.is() ) try
813 mfAcceleration
= fAcceleration
;
814 mxNode
->setAcceleration( fAcceleration
);
818 OSL_FAIL( "sd::CustomAnimationEffect::setAcceleration(), exception caught!" );
821 // --------------------------------------------------------------------
823 void CustomAnimationEffect::setDecelerate( double fDecelerate
)
825 if( mxNode
.is() ) try
827 mfDecelerate
= fDecelerate
;
828 mxNode
->setDecelerate( fDecelerate
);
832 OSL_FAIL( "sd::CustomAnimationEffect::setDecelerate(), exception caught!" );
836 // --------------------------------------------------------------------
838 void CustomAnimationEffect::setAutoReverse( sal_Bool bAutoReverse
)
840 if( mxNode
.is() ) try
842 mbAutoReverse
= bAutoReverse
;
843 mxNode
->setAutoReverse( bAutoReverse
);
847 OSL_FAIL( "sd::CustomAnimationEffect::setAutoReverse(), exception caught!" );
851 // --------------------------------------------------------------------
853 void CustomAnimationEffect::replaceNode( const ::com::sun::star::uno::Reference
< ::com::sun::star::animations::XAnimationNode
>& xNode
)
855 sal_Int16 nNodeType
= mnNodeType
;
856 Any aTarget
= maTarget
;
858 double fBegin
= mfBegin
;
859 double fDuration
= mfDuration
;
860 double fAcceleration
= mfAcceleration
;
861 double fDecelerate
= mfDecelerate
;
862 sal_Bool bAutoReverse
= mbAutoReverse
;
863 Reference
< XAudio
> xAudio( mxAudio
);
864 sal_Int16 nIterateType
= mnIterateType
;
865 double fIterateInterval
= mfIterateInterval
;
866 sal_Int16 nSubItem
= mnTargetSubItem
;
871 setNodeType( nNodeType
);
872 setTarget( aTarget
);
873 setTargetSubItem( nSubItem
);
874 setDuration( fDuration
);
877 setAcceleration( fAcceleration
);
878 setDecelerate( fDecelerate
);
879 setAutoReverse( bAutoReverse
);
881 if( nIterateType
!= mnIterateType
)
882 setIterateType( nIterateType
);
884 if( mnIterateType
&& ( fIterateInterval
!= mfIterateInterval
) )
885 setIterateInterval( fIterateInterval
);
888 // --------------------------------------------------------------------
890 Reference
< XShape
> CustomAnimationEffect::getTargetShape() const
892 Reference
< XShape
> xShape
;
896 ParagraphTarget aParaTarget
;
897 if( maTarget
>>= aParaTarget
)
898 xShape
= aParaTarget
.Shape
;
904 // --------------------------------------------------------------------
906 Any
CustomAnimationEffect::getRepeatCount() const
910 return mxNode
->getRepeatCount();
919 // --------------------------------------------------------------------
921 Any
CustomAnimationEffect::getEnd() const
925 return mxNode
->getEnd();
934 // --------------------------------------------------------------------
936 sal_Int16
CustomAnimationEffect::getFill() const
939 return mxNode
->getFill();
944 // --------------------------------------------------------------------
946 void CustomAnimationEffect::setRepeatCount( const Any
& rRepeatCount
)
950 mxNode
->setRepeatCount( rRepeatCount
);
951 double fRepeatCount
= 1.0;
952 rRepeatCount
>>= fRepeatCount
;
953 mfAbsoluteDuration
= mfDuration
* fRepeatCount
;
957 // --------------------------------------------------------------------
959 void CustomAnimationEffect::setEnd( const Any
& rEnd
)
962 mxNode
->setEnd( rEnd
);
965 // --------------------------------------------------------------------
967 void CustomAnimationEffect::setFill( sal_Int16 nFill
)
970 mxNode
->setFill( nFill
);
973 // --------------------------------------------------------------------
975 Reference
< XAnimationNode
> CustomAnimationEffect::createAfterEffectNode() const throw (Exception
)
977 DBG_ASSERT( mbHasAfterEffect
, "sd::CustomAnimationEffect::createAfterEffectNode(), this node has no after effect!" );
979 Reference
< XComponentContext
> xContext( ::comphelper::getProcessComponentContext() );
981 Reference
< XAnimate
> xAnimate
;
982 if( maDimColor
.hasValue() )
983 xAnimate
= AnimateColor::create( xContext
);
985 xAnimate
= AnimateSet::create( xContext
);
988 OUString aAttributeName
;
990 if( maDimColor
.hasValue() )
993 aAttributeName
= "DimColor";
997 aTo
= makeAny( (sal_Bool
)sal_False
);
998 aAttributeName
= "Visibility";
1002 if( !mbAfterEffectOnNextEffect
) // sameClick
1006 aEvent
.Source
<<= getNode();
1007 aEvent
.Trigger
= EventTrigger::END_EVENT
;
1014 aBegin
<<= (double)0.0;
1017 xAnimate
->setBegin( aBegin
);
1018 xAnimate
->setTo( aTo
);
1019 xAnimate
->setAttributeName( aAttributeName
);
1021 xAnimate
->setDuration( makeAny( (double)0.001 ) );
1022 xAnimate
->setFill( AnimationFill::HOLD
);
1023 xAnimate
->setTarget( maTarget
);
1028 // --------------------------------------------------------------------
1030 void CustomAnimationEffect::setIterateType( sal_Int16 nIterateType
)
1032 if( mnIterateType
!= nIterateType
) try
1034 // do we need to exchange the container node?
1035 if( (mnIterateType
== 0) || (nIterateType
== 0) )
1037 sal_Int16 nTargetSubItem
= mnTargetSubItem
;
1039 Reference
< XComponentContext
> xContext( ::comphelper::getProcessComponentContext() );
1040 Reference
< XTimeContainer
> xNewContainer
;
1043 xNewContainer
.set( IterateContainer::create( xContext
) );
1046 xNewContainer
.set( ParallelTimeContainer::create( xContext
), UNO_QUERY_THROW
);
1048 Reference
< XTimeContainer
> xOldContainer( mxNode
, UNO_QUERY_THROW
);
1049 Reference
< XEnumerationAccess
> xEnumerationAccess( mxNode
, UNO_QUERY_THROW
);
1050 Reference
< XEnumeration
> xEnumeration( xEnumerationAccess
->createEnumeration(), UNO_QUERY_THROW
);
1051 while( xEnumeration
->hasMoreElements() )
1053 Reference
< XAnimationNode
> xChildNode( xEnumeration
->nextElement(), UNO_QUERY_THROW
);
1054 xOldContainer
->removeChild( xChildNode
);
1055 xNewContainer
->appendChild( xChildNode
);
1058 Reference
< XAnimationNode
> xNewNode( xNewContainer
, UNO_QUERY_THROW
);
1060 xNewNode
->setBegin( mxNode
->getBegin() );
1061 xNewNode
->setDuration( mxNode
->getDuration() );
1062 xNewNode
->setEnd( mxNode
->getEnd() );
1063 xNewNode
->setEndSync( mxNode
->getEndSync() );
1064 xNewNode
->setRepeatCount( mxNode
->getRepeatCount() );
1065 xNewNode
->setFill( mxNode
->getFill() );
1066 xNewNode
->setFillDefault( mxNode
->getFillDefault() );
1067 xNewNode
->setRestart( mxNode
->getRestart() );
1068 xNewNode
->setRestartDefault( mxNode
->getRestartDefault() );
1069 xNewNode
->setAcceleration( mxNode
->getAcceleration() );
1070 xNewNode
->setDecelerate( mxNode
->getDecelerate() );
1071 xNewNode
->setAutoReverse( mxNode
->getAutoReverse() );
1072 xNewNode
->setRepeatDuration( mxNode
->getRepeatDuration() );
1073 xNewNode
->setEndSync( mxNode
->getEndSync() );
1074 xNewNode
->setRepeatCount( mxNode
->getRepeatCount() );
1075 xNewNode
->setUserData( mxNode
->getUserData() );
1082 Reference
< XIterateContainer
> xIter( mxNode
, UNO_QUERY_THROW
);
1083 xIter
->setTarget(maTarget
);
1084 xIter
->setSubItem( nTargetSubItem
);
1091 Reference
< XEnumerationAccess
> xEA( mxNode
, UNO_QUERY_THROW
);
1092 Reference
< XEnumeration
> xE( xEA
->createEnumeration(), UNO_QUERY_THROW
);
1093 while( xE
->hasMoreElements() )
1095 Reference
< XAnimate
> xAnimate( xE
->nextElement(), UNO_QUERY
);
1098 xAnimate
->setTarget( aTarget
);
1099 xAnimate
->setSubItem( nTargetSubItem
);
1104 mnIterateType
= nIterateType
;
1106 // if we have an iteration container, we must set its type
1109 Reference
< XIterateContainer
> xIter( mxNode
, UNO_QUERY_THROW
);
1110 xIter
->setIterateType( nIterateType
);
1117 OSL_FAIL( "sd::CustomAnimationEffect::setIterateType(), Exception caught!" );
1121 // --------------------------------------------------------------------
1123 void CustomAnimationEffect::setIterateInterval( double fIterateInterval
)
1125 if( mfIterateInterval
!= fIterateInterval
)
1127 Reference
< XIterateContainer
> xIter( mxNode
, UNO_QUERY
);
1129 DBG_ASSERT( xIter
.is(), "sd::CustomAnimationEffect::setIterateInterval(), not an iteration node" );
1132 mfIterateInterval
= fIterateInterval
;
1133 xIter
->setIterateInterval( fIterateInterval
);
1136 calculateIterateDuration();
1140 // --------------------------------------------------------------------
1142 OUString
CustomAnimationEffect::getPath() const
1146 if( mxNode
.is() ) try
1148 Reference
< XEnumerationAccess
> xEnumerationAccess( mxNode
, UNO_QUERY_THROW
);
1149 Reference
< XEnumeration
> xEnumeration( xEnumerationAccess
->createEnumeration(), UNO_QUERY_THROW
);
1150 while( xEnumeration
->hasMoreElements() )
1152 Reference
< XAnimateMotion
> xMotion( xEnumeration
->nextElement(), UNO_QUERY
);
1155 xMotion
->getPath() >>= aPath
;
1162 OSL_FAIL("sd::CustomAnimationEffect::getPath(), exception caught!" );
1168 // --------------------------------------------------------------------
1170 void CustomAnimationEffect::setPath( const OUString
& rPath
)
1172 if( mxNode
.is() ) try
1174 Reference
< XEnumerationAccess
> xEnumerationAccess( mxNode
, UNO_QUERY_THROW
);
1175 Reference
< XEnumeration
> xEnumeration( xEnumerationAccess
->createEnumeration(), UNO_QUERY_THROW
);
1176 while( xEnumeration
->hasMoreElements() )
1178 Reference
< XAnimateMotion
> xMotion( xEnumeration
->nextElement(), UNO_QUERY
);
1182 MainSequenceChangeGuard
aGuard( mpEffectSequence
);
1183 xMotion
->setPath( Any( rPath
) );
1190 OSL_FAIL("sd::CustomAnimationEffect::setPath(), exception caught!" );
1194 // --------------------------------------------------------------------
1196 Any
CustomAnimationEffect::getProperty( sal_Int32 nNodeType
, const OUString
& rAttributeName
, EValue eValue
)
1199 if( mxNode
.is() ) try
1201 Reference
< XEnumerationAccess
> xEnumerationAccess( mxNode
, UNO_QUERY
);
1202 if( xEnumerationAccess
.is() )
1204 Reference
< XEnumeration
> xEnumeration( xEnumerationAccess
->createEnumeration(), UNO_QUERY
);
1205 if( xEnumeration
.is() )
1207 while( xEnumeration
->hasMoreElements() && !aProperty
.hasValue() )
1209 Reference
< XAnimate
> xAnimate( xEnumeration
->nextElement(), UNO_QUERY
);
1210 if( !xAnimate
.is() )
1213 if( xAnimate
->getType() == nNodeType
)
1215 if( xAnimate
->getAttributeName() == rAttributeName
)
1219 case VALUE_FROM
: aProperty
= xAnimate
->getFrom(); break;
1220 case VALUE_TO
: aProperty
= xAnimate
->getTo(); break;
1221 case VALUE_BY
: aProperty
= xAnimate
->getBy(); break;
1225 Sequence
<Any
> aValues( xAnimate
->getValues() );
1226 if( aValues
.hasElements() )
1227 aProperty
= aValues
[ eValue
== VALUE_FIRST
? 0 : aValues
.getLength() - 1 ];
1239 OSL_FAIL("sd::CustomAnimationEffect::getProperty(), exception caught!" );
1245 // --------------------------------------------------------------------
1247 bool CustomAnimationEffect::setProperty( sal_Int32 nNodeType
, const OUString
& rAttributeName
, EValue eValue
, const Any
& rValue
)
1249 bool bChanged
= false;
1250 if( mxNode
.is() ) try
1252 Reference
< XEnumerationAccess
> xEnumerationAccess( mxNode
, UNO_QUERY
);
1253 if( xEnumerationAccess
.is() )
1255 Reference
< XEnumeration
> xEnumeration( xEnumerationAccess
->createEnumeration(), UNO_QUERY
);
1256 if( xEnumeration
.is() )
1258 while( xEnumeration
->hasMoreElements() )
1260 Reference
< XAnimate
> xAnimate( xEnumeration
->nextElement(), UNO_QUERY
);
1261 if( !xAnimate
.is() )
1264 if( xAnimate
->getType() == nNodeType
)
1266 if( xAnimate
->getAttributeName() == rAttributeName
)
1271 if( xAnimate
->getFrom() != rValue
)
1273 xAnimate
->setFrom( rValue
);
1278 if( xAnimate
->getTo() != rValue
)
1280 xAnimate
->setTo( rValue
);
1285 if( xAnimate
->getTo() != rValue
)
1287 xAnimate
->setBy( rValue
);
1294 Sequence
<Any
> aValues( xAnimate
->getValues() );
1295 if( !aValues
.hasElements() )
1298 sal_Int32 nIndex
= eValue
== VALUE_FIRST
? 0 : aValues
.getLength() - 1;
1300 if( aValues
[ nIndex
] != rValue
)
1302 aValues
[ nIndex
] = rValue
;
1303 xAnimate
->setValues( aValues
);
1316 OSL_FAIL("sd::CustomAnimationEffect::setProperty(), exception caught!" );
1322 // --------------------------------------------------------------------
1324 static bool implIsColorAttribute( const OUString
& rAttributeName
)
1326 return rAttributeName
== "FillColor" || rAttributeName
== "LineColor" || rAttributeName
== "CharColor";
1329 // --------------------------------------------------------------------
1331 Any
CustomAnimationEffect::getColor( sal_Int32 nIndex
)
1334 if( mxNode
.is() ) try
1336 Reference
< XEnumerationAccess
> xEnumerationAccess( mxNode
, UNO_QUERY
);
1337 if( xEnumerationAccess
.is() )
1339 Reference
< XEnumeration
> xEnumeration( xEnumerationAccess
->createEnumeration(), UNO_QUERY
);
1340 if( xEnumeration
.is() )
1342 while( xEnumeration
->hasMoreElements() && !aColor
.hasValue() )
1344 Reference
< XAnimate
> xAnimate( xEnumeration
->nextElement(), UNO_QUERY
);
1345 if( !xAnimate
.is() )
1348 switch( xAnimate
->getType() )
1350 case AnimationNodeType::SET
:
1351 case AnimationNodeType::ANIMATE
:
1352 if( !implIsColorAttribute( xAnimate
->getAttributeName() ) )
1354 case AnimationNodeType::ANIMATECOLOR
:
1355 Sequence
<Any
> aValues( xAnimate
->getValues() );
1356 if( aValues
.hasElements() )
1358 if( aValues
.getLength() > nIndex
)
1359 aColor
= aValues
[nIndex
];
1361 else if( nIndex
== 0 )
1362 aColor
= xAnimate
->getFrom();
1364 aColor
= xAnimate
->getTo();
1372 OSL_FAIL("sd::CustomAnimationEffect::getColor(), exception caught!" );
1378 // --------------------------------------------------------------------
1380 void CustomAnimationEffect::setColor( sal_Int32 nIndex
, const Any
& rColor
)
1382 if( mxNode
.is() ) try
1384 Reference
< XEnumerationAccess
> xEnumerationAccess( mxNode
, UNO_QUERY
);
1385 if( xEnumerationAccess
.is() )
1387 Reference
< XEnumeration
> xEnumeration( xEnumerationAccess
->createEnumeration(), UNO_QUERY
);
1388 if( xEnumeration
.is() )
1390 while( xEnumeration
->hasMoreElements() )
1392 Reference
< XAnimate
> xAnimate( xEnumeration
->nextElement(), UNO_QUERY
);
1393 if( !xAnimate
.is() )
1396 switch( xAnimate
->getType() )
1398 case AnimationNodeType::SET
:
1399 case AnimationNodeType::ANIMATE
:
1400 if( !implIsColorAttribute( xAnimate
->getAttributeName() ) )
1402 case AnimationNodeType::ANIMATECOLOR
:
1404 Sequence
<Any
> aValues( xAnimate
->getValues() );
1405 if( aValues
.hasElements() )
1407 if( aValues
.getLength() > nIndex
)
1409 aValues
[nIndex
] = rColor
;
1410 xAnimate
->setValues( aValues
);
1413 else if( (nIndex
== 0) && xAnimate
->getFrom().hasValue() )
1414 xAnimate
->setFrom(rColor
);
1415 else if( (nIndex
== 1) && xAnimate
->getTo().hasValue() )
1416 xAnimate
->setTo(rColor
);
1427 OSL_FAIL("sd::CustomAnimationEffect::setColor(), exception caught!" );
1431 // --------------------------------------------------------------------
1433 Any
CustomAnimationEffect::getTransformationProperty( sal_Int32 nTransformType
, EValue eValue
)
1436 if( mxNode
.is() ) try
1438 Reference
< XEnumerationAccess
> xEnumerationAccess( mxNode
, UNO_QUERY
);
1439 if( xEnumerationAccess
.is() )
1441 Reference
< XEnumeration
> xEnumeration( xEnumerationAccess
->createEnumeration(), UNO_QUERY
);
1442 if( xEnumeration
.is() )
1444 while( xEnumeration
->hasMoreElements() && !aProperty
.hasValue() )
1446 Reference
< XAnimateTransform
> xTransform( xEnumeration
->nextElement(), UNO_QUERY
);
1447 if( !xTransform
.is() )
1450 if( xTransform
->getTransformType() == nTransformType
)
1454 case VALUE_FROM
: aProperty
= xTransform
->getFrom(); break;
1455 case VALUE_TO
: aProperty
= xTransform
->getTo(); break;
1456 case VALUE_BY
: aProperty
= xTransform
->getBy(); break;
1460 Sequence
<Any
> aValues( xTransform
->getValues() );
1461 if( aValues
.hasElements() )
1462 aProperty
= aValues
[ eValue
== VALUE_FIRST
? 0 : aValues
.getLength() - 1 ];
1473 OSL_FAIL("sd::CustomAnimationEffect::getTransformationProperty(), exception caught!" );
1479 // --------------------------------------------------------------------
1481 bool CustomAnimationEffect::setTransformationProperty( sal_Int32 nTransformType
, EValue eValue
, const Any
& rValue
)
1483 bool bChanged
= false;
1484 if( mxNode
.is() ) try
1486 Reference
< XEnumerationAccess
> xEnumerationAccess( mxNode
, UNO_QUERY
);
1487 if( xEnumerationAccess
.is() )
1489 Reference
< XEnumeration
> xEnumeration( xEnumerationAccess
->createEnumeration(), UNO_QUERY
);
1490 if( xEnumeration
.is() )
1492 while( xEnumeration
->hasMoreElements() )
1494 Reference
< XAnimateTransform
> xTransform( xEnumeration
->nextElement(), UNO_QUERY
);
1495 if( !xTransform
.is() )
1498 if( xTransform
->getTransformType() == nTransformType
)
1503 if( xTransform
->getFrom() != rValue
)
1505 xTransform
->setFrom( rValue
);
1510 if( xTransform
->getTo() != rValue
)
1512 xTransform
->setTo( rValue
);
1517 if( xTransform
->getBy() != rValue
)
1519 xTransform
->setBy( rValue
);
1526 Sequence
<Any
> aValues( xTransform
->getValues() );
1527 if( !aValues
.hasElements() )
1530 sal_Int32 nIndex
= eValue
== VALUE_FIRST
? 0 : aValues
.getLength() - 1;
1531 if( aValues
[nIndex
] != rValue
)
1533 aValues
[nIndex
] = rValue
;
1534 xTransform
->setValues( aValues
);
1546 OSL_FAIL("sd::CustomAnimationEffect::setTransformationProperty(), exception caught!" );
1552 // --------------------------------------------------------------------
1554 void CustomAnimationEffect::createAudio( const ::com::sun::star::uno::Any
& rSource
, double fVolume
/* = 1.0 */ )
1556 DBG_ASSERT( !mxAudio
.is(), "sd::CustomAnimationEffect::createAudio(), node already has an audio!" );
1558 if( !mxAudio
.is() ) try
1560 Reference
< XComponentContext
> xContext( ::comphelper::getProcessComponentContext() );
1561 Reference
< XAudio
> xAudio( Audio::create( xContext
) );
1562 xAudio
->setSource( rSource
);
1563 xAudio
->setVolume( fVolume
);
1568 OSL_FAIL("sd::CustomAnimationEffect::createAudio(), exception caught!" );
1572 // --------------------------------------------------------------------
1574 static Reference
< XCommand
> findCommandNode( const Reference
< XAnimationNode
>& xRootNode
)
1576 Reference
< XCommand
> xCommand
;
1578 if( xRootNode
.is() ) try
1580 Reference
< XEnumerationAccess
> xEnumerationAccess( xRootNode
, UNO_QUERY_THROW
);
1581 Reference
< XEnumeration
> xEnumeration( xEnumerationAccess
->createEnumeration(), UNO_QUERY_THROW
);
1582 while( !xCommand
.is() && xEnumeration
->hasMoreElements() )
1584 Reference
< XAnimationNode
> xNode( xEnumeration
->nextElement(), UNO_QUERY
);
1585 if( xNode
.is() && (xNode
->getType() == AnimationNodeType::COMMAND
) )
1586 xCommand
.set( xNode
, UNO_QUERY_THROW
);
1591 OSL_FAIL("sd::findCommandNode(), exception caught!" );
1597 void CustomAnimationEffect::removeAudio()
1601 Reference
< XAnimationNode
> xChild
;
1605 xChild
.set( mxAudio
, UNO_QUERY
);
1608 else if( mnCommand
== EffectCommands::STOPAUDIO
)
1610 xChild
.set( findCommandNode( mxNode
), UNO_QUERY
);
1616 Reference
< XTimeContainer
> xContainer( mxNode
, UNO_QUERY
);
1617 if( xContainer
.is() )
1618 xContainer
->removeChild( xChild
);
1623 OSL_FAIL("sd::CustomAnimationEffect::removeAudio(), exception caught!" );
1628 // --------------------------------------------------------------------
1630 void CustomAnimationEffect::setAudio( const Reference
< ::com::sun::star::animations::XAudio
>& xAudio
)
1632 if( mxAudio
!= xAudio
) try
1636 Reference
< XTimeContainer
> xContainer( mxNode
, UNO_QUERY
);
1637 Reference
< XAnimationNode
> xChild( mxAudio
, UNO_QUERY
);
1638 if( xContainer
.is() && xChild
.is() )
1639 xContainer
->appendChild( xChild
);
1643 OSL_FAIL("sd::CustomAnimationEffect::setAudio(), exception caught!" );
1647 // --------------------------------------------------------------------
1649 void CustomAnimationEffect::setStopAudio()
1651 if( mnCommand
!= EffectCommands::STOPAUDIO
) try
1656 Reference
< XComponentContext
> xContext( ::comphelper::getProcessComponentContext() );
1657 Reference
< XCommand
> xCommand( Command::create( xContext
) );
1659 xCommand
->setCommand( EffectCommands::STOPAUDIO
);
1661 Reference
< XTimeContainer
> xContainer( mxNode
, UNO_QUERY_THROW
);
1662 Reference
< XAnimationNode
> xChild( xCommand
, UNO_QUERY_THROW
);
1663 xContainer
->appendChild( xChild
);
1665 mnCommand
= EffectCommands::STOPAUDIO
;
1669 OSL_FAIL("sd::CustomAnimationEffect::setStopAudio(), exception caught!" );
1673 // --------------------------------------------------------------------
1675 bool CustomAnimationEffect::getStopAudio() const
1677 return mnCommand
== EffectCommands::STOPAUDIO
;
1680 // --------------------------------------------------------------------
1682 SdrPathObj
* CustomAnimationEffect::createSdrPathObjFromPath()
1684 SdrPathObj
* pPathObj
= new SdrPathObj( OBJ_PATHLINE
);
1685 updateSdrPathObjFromPath( *pPathObj
);
1689 // --------------------------------------------------------------------
1691 void CustomAnimationEffect::updateSdrPathObjFromPath( SdrPathObj
& rPathObj
)
1693 ::basegfx::B2DPolyPolygon xPolyPoly
;
1694 if( ::basegfx::tools::importFromSvgD( xPolyPoly
, getPath() ) )
1696 SdrObject
* pObj
= GetSdrObjectFromXShape( getTargetShape() );
1699 SdrPage
* pPage
= pObj
->GetPage();
1702 const Size
aPageSize( pPage
->GetSize() );
1703 xPolyPoly
.transform(basegfx::tools::createScaleB2DHomMatrix((double)aPageSize
.Width(), (double)aPageSize
.Height()));
1706 const Rectangle
aBoundRect( pObj
->GetCurrentBoundRect() );
1707 const Point
aCenter( aBoundRect
.Center() );
1708 xPolyPoly
.transform(basegfx::tools::createTranslateB2DHomMatrix(aCenter
.X(), aCenter
.Y()));
1712 rPathObj
.SetPathPoly( xPolyPoly
);
1715 // --------------------------------------------------------------------
1717 void CustomAnimationEffect::updatePathFromSdrPathObj( const SdrPathObj
& rPathObj
)
1719 ::basegfx::B2DPolyPolygon
xPolyPoly( rPathObj
.GetPathPoly() );
1721 SdrObject
* pObj
= GetSdrObjectFromXShape( getTargetShape() );
1724 Rectangle
aBoundRect(0,0,0,0);
1726 const drawinglayer::primitive2d::Primitive2DSequence
xPrimitives(pObj
->GetViewContact().getViewIndependentPrimitive2DSequence());
1727 const drawinglayer::geometry::ViewInformation2D aViewInformation2D
;
1728 const basegfx::B2DRange
aRange(drawinglayer::primitive2d::getB2DRangeFromPrimitive2DSequence(xPrimitives
, aViewInformation2D
));
1730 if(!aRange
.isEmpty())
1732 aBoundRect
= Rectangle(
1733 (sal_Int32
)floor(aRange
.getMinX()), (sal_Int32
)floor(aRange
.getMinY()),
1734 (sal_Int32
)ceil(aRange
.getMaxX()), (sal_Int32
)ceil(aRange
.getMaxY()));
1737 const Point
aCenter( aBoundRect
.Center() );
1739 xPolyPoly
.transform(basegfx::tools::createTranslateB2DHomMatrix(-aCenter
.X(), -aCenter
.Y()));
1741 SdrPage
* pPage
= pObj
->GetPage();
1744 const Size
aPageSize( pPage
->GetSize() );
1745 xPolyPoly
.transform(basegfx::tools::createScaleB2DHomMatrix(
1746 1.0 / (double)aPageSize
.Width(), 1.0 / (double)aPageSize
.Height()));
1750 setPath( ::basegfx::tools::exportToSvgD( xPolyPoly
) );
1753 // ====================================================================
1755 EffectSequenceHelper::EffectSequenceHelper()
1756 : mnSequenceType( EffectNodeType::DEFAULT
)
1760 // --------------------------------------------------------------------
1762 EffectSequenceHelper::EffectSequenceHelper( const ::com::sun::star::uno::Reference
< ::com::sun::star::animations::XTimeContainer
>& xSequenceRoot
)
1763 : mxSequenceRoot( xSequenceRoot
), mnSequenceType( EffectNodeType::DEFAULT
)
1765 Reference
< XAnimationNode
> xNode( mxSequenceRoot
, UNO_QUERY_THROW
);
1769 // --------------------------------------------------------------------
1771 EffectSequenceHelper::~EffectSequenceHelper()
1776 // --------------------------------------------------------------------
1778 void EffectSequenceHelper::reset()
1780 EffectSequence::iterator
aIter( maEffects
.begin() );
1781 EffectSequence::iterator
aEnd( maEffects
.end() );
1784 CustomAnimationEffectPtr pEffect
= (*aIter
++);
1785 pEffect
->setEffectSequence(0);
1790 Reference
< XAnimationNode
> EffectSequenceHelper::getRootNode()
1792 Reference
< XAnimationNode
> xRoot( mxSequenceRoot
, UNO_QUERY
);
1796 // --------------------------------------------------------------------
1798 void EffectSequenceHelper::append( const CustomAnimationEffectPtr
& pEffect
)
1800 pEffect
->setEffectSequence( this );
1801 maEffects
.push_back(pEffect
);
1805 // --------------------------------------------------------------------
1807 CustomAnimationEffectPtr
EffectSequenceHelper::append( const CustomAnimationPresetPtr
& pPreset
, const Any
& rTarget
, double fDuration
/* = -1.0 */ )
1809 CustomAnimationEffectPtr pEffect
;
1814 Reference
< XAnimationNode
> xNode( pPreset
->create( strEmpty
) );
1817 // first, filter all only ui relevant user data
1818 std::vector
< NamedValue
> aNewUserData
;
1819 Sequence
< NamedValue
> aUserData( xNode
->getUserData() );
1820 sal_Int32 nLength
= aUserData
.getLength();
1821 const NamedValue
* p
= aUserData
.getConstArray();
1822 bool bFilter
= false;
1826 if( p
->Name
!= "text-only" && p
->Name
!= "preset-property" )
1828 aNewUserData
.push_back( *p
);
1836 aUserData
= ::comphelper::containerToSequence
< NamedValue
, std::vector
< NamedValue
> >( aNewUserData
);
1837 xNode
->setUserData( aUserData
);
1840 // check target, maybe we need to force it to text
1841 Any
aTarget( rTarget
);
1842 sal_Int16 nSubItem
= ShapeAnimationSubType::AS_WHOLE
;
1844 if( aTarget
.getValueType() == ::getCppuType((const ParagraphTarget
*)0) )
1846 nSubItem
= ShapeAnimationSubType::ONLY_TEXT
;
1848 else if( pPreset
->isTextOnly() )
1850 Reference
< XShape
> xShape
;
1854 // thats bad, we target a shape here but the effect is only for text
1855 // so change subitem
1856 nSubItem
= ShapeAnimationSubType::ONLY_TEXT
;
1860 // now create effect from preset
1861 pEffect
.reset( new CustomAnimationEffect( xNode
) );
1862 pEffect
->setEffectSequence( this );
1863 pEffect
->setTarget( aTarget
);
1864 pEffect
->setTargetSubItem( nSubItem
);
1865 if( fDuration
!= -1.0 )
1866 pEffect
->setDuration( fDuration
);
1868 maEffects
.push_back(pEffect
);
1874 DBG_ASSERT( pEffect
.get(), "sd::EffectSequenceHelper::append(), failed!" );
1878 // --------------------------------------------------------------------
1880 CustomAnimationEffectPtr
EffectSequenceHelper::append( const SdrPathObj
& rPathObj
, const Any
& rTarget
, double fDuration
/* = -1.0 */ )
1882 CustomAnimationEffectPtr pEffect
;
1884 if( fDuration
<= 0.0 )
1889 Reference
< XTimeContainer
> xEffectContainer( ParallelTimeContainer::create( ::comphelper::getProcessComponentContext() ), UNO_QUERY_THROW
);
1890 Reference
< XAnimationNode
> xAnimateMotion( AnimateMotion::create( ::comphelper::getProcessComponentContext() ) );
1892 xAnimateMotion
->setDuration( Any( fDuration
) );
1893 xAnimateMotion
->setFill( AnimationFill::HOLD
);
1894 xEffectContainer
->appendChild( xAnimateMotion
);
1896 sal_Int16 nSubItem
= ShapeAnimationSubType::AS_WHOLE
;
1898 if( rTarget
.getValueType() == ::getCppuType((const ParagraphTarget
*)0) )
1899 nSubItem
= ShapeAnimationSubType::ONLY_TEXT
;
1901 Reference
< XAnimationNode
> xEffectNode( xEffectContainer
, UNO_QUERY_THROW
);
1902 pEffect
.reset( new CustomAnimationEffect( xEffectNode
) );
1903 pEffect
->setEffectSequence( this );
1904 pEffect
->setTarget( rTarget
);
1905 pEffect
->setTargetSubItem( nSubItem
);
1906 pEffect
->setNodeType( ::com::sun::star::presentation::EffectNodeType::ON_CLICK
);
1907 pEffect
->setPresetClass( ::com::sun::star::presentation::EffectPresetClass::MOTIONPATH
);
1908 pEffect
->setAcceleration( 0.5 );
1909 pEffect
->setDecelerate( 0.5 );
1910 pEffect
->setFill( AnimationFill::HOLD
);
1911 pEffect
->setBegin( 0.0 );
1912 pEffect
->updatePathFromSdrPathObj( rPathObj
);
1913 if( fDuration
!= -1.0 )
1914 pEffect
->setDuration( fDuration
);
1916 maEffects
.push_back(pEffect
);
1922 OSL_FAIL( "sd::EffectSequenceHelper::append(), exception caught!" );
1928 // --------------------------------------------------------------------
1930 void EffectSequenceHelper::replace( const CustomAnimationEffectPtr
& pEffect
, const CustomAnimationPresetPtr
& pPreset
, const OUString
& rPresetSubType
, double fDuration
/* = -1.0 */ )
1932 if( pEffect
.get() && pPreset
.get() ) try
1934 Reference
< XAnimationNode
> xNewNode( pPreset
->create( rPresetSubType
) );
1937 pEffect
->replaceNode( xNewNode
);
1938 if( fDuration
!= -1.0 )
1939 pEffect
->setDuration( fDuration
);
1946 OSL_FAIL( "sd::EffectSequenceHelper::replace(), exception caught!" );
1950 // --------------------------------------------------------------------
1952 void EffectSequenceHelper::replace( const CustomAnimationEffectPtr
& pEffect
, const CustomAnimationPresetPtr
& pPreset
, double fDuration
/* = -1.0 */ )
1955 replace( pEffect
, pPreset
, strEmpty
, fDuration
);
1958 // --------------------------------------------------------------------
1960 void EffectSequenceHelper::remove( const CustomAnimationEffectPtr
& pEffect
)
1964 pEffect
->setEffectSequence( 0 );
1965 maEffects
.remove( pEffect
);
1971 // --------------------------------------------------------------------
1973 void EffectSequenceHelper::rebuild()
1978 // --------------------------------------------------------------------
1980 void EffectSequenceHelper::implRebuild()
1984 // first we delete all time containers on the first two levels
1985 Reference
< XEnumerationAccess
> xEnumerationAccess( mxSequenceRoot
, UNO_QUERY_THROW
);
1986 Reference
< XEnumeration
> xEnumeration( xEnumerationAccess
->createEnumeration(), UNO_QUERY_THROW
);
1987 while( xEnumeration
->hasMoreElements() )
1989 Reference
< XAnimationNode
> xChildNode( xEnumeration
->nextElement(), UNO_QUERY_THROW
);
1990 Reference
< XTimeContainer
> xChildContainer( xChildNode
, UNO_QUERY_THROW
);
1992 Reference
< XEnumerationAccess
> xChildEnumerationAccess( xChildNode
, UNO_QUERY_THROW
);
1993 Reference
< XEnumeration
> xChildEnumeration( xChildEnumerationAccess
->createEnumeration(), UNO_QUERY_THROW
);
1994 while( xChildEnumeration
->hasMoreElements() )
1996 Reference
< XAnimationNode
> xNode( xChildEnumeration
->nextElement(), UNO_QUERY_THROW
);
1997 xChildContainer
->removeChild( xNode
);
2000 mxSequenceRoot
->removeChild( xChildNode
);
2003 // second, rebuild main sequence
2004 EffectSequence::iterator
aIter( maEffects
.begin() );
2005 EffectSequence::iterator
aEnd( maEffects
.end() );
2008 AfterEffectNodeList aAfterEffects
;
2010 CustomAnimationEffectPtr pEffect
= (*aIter
++);
2015 // create a par container for the next click node and all following with and after effects
2016 Reference
< XTimeContainer
> xOnClickContainer( ParallelTimeContainer::create( ::comphelper::getProcessComponentContext() ), UNO_QUERY_THROW
);
2019 if( mxEventSource
.is() )
2021 aEvent
.Source
<<= mxEventSource
;
2022 aEvent
.Trigger
= EventTrigger::ON_CLICK
;
2026 aEvent
.Trigger
= EventTrigger::ON_NEXT
;
2030 Any
aBegin( makeAny( aEvent
) );
2033 // if the first node is not a click action, this click container
2034 // must not have INDEFINITE begin but start at 0s
2036 if( pEffect
->getNodeType() != EffectNodeType::ON_CLICK
)
2037 aBegin
<<= (double)0.0;
2040 xOnClickContainer
->setBegin( aBegin
);
2042 Reference
< XAnimationNode
> xOnClickContainerNode( xOnClickContainer
, UNO_QUERY_THROW
);
2043 mxSequenceRoot
->appendChild( xOnClickContainerNode
);
2045 double fBegin
= 0.0;
2049 // create a par container for the current click or after effect node and all following with effects
2050 Reference
< XTimeContainer
> xWithContainer( ParallelTimeContainer::create( ::comphelper::getProcessComponentContext() ), UNO_QUERY_THROW
);
2051 Reference
< XAnimationNode
> xWithContainerNode( xWithContainer
, UNO_QUERY_THROW
);
2052 xWithContainer
->setBegin( makeAny( fBegin
) );
2053 xOnClickContainer
->appendChild( xWithContainerNode
);
2055 double fDuration
= 0.0;
2058 Reference
< XAnimationNode
> xEffectNode( pEffect
->getNode() );
2059 xWithContainer
->appendChild( xEffectNode
);
2061 if( pEffect
->hasAfterEffect() )
2063 Reference
< XAnimationNode
> xAfterEffect( pEffect
->createAfterEffectNode() );
2064 AfterEffectNode
a( xAfterEffect
, xEffectNode
, pEffect
->IsAfterEffectOnNext() );
2065 aAfterEffects
.push_back( a
);
2068 double fTemp
= pEffect
->getBegin() + pEffect
->getAbsoluteDuration();
2069 if( fTemp
> fDuration
)
2073 pEffect
= (*aIter
++);
2077 while( pEffect
.get() && (pEffect
->getNodeType() == EffectNodeType::WITH_PREVIOUS
) );
2079 fBegin
+= fDuration
;
2081 while( pEffect
.get() && (pEffect
->getNodeType() != EffectNodeType::ON_CLICK
) );
2083 while( pEffect
.get() );
2085 // process after effect nodes
2086 std::for_each( aAfterEffects
.begin(), aAfterEffects
.end(), stl_process_after_effect_node_func
);
2090 // reset duration, might have been altered (see below)
2091 mxSequenceRoot
->setDuration( Any() );
2095 // empty sequence, set duration to 0.0 explicitly
2096 // (otherwise, this sequence will never end)
2097 mxSequenceRoot
->setDuration( makeAny((double)0.0) );
2102 OSL_FAIL( "sd::EffectSequenceHelper::rebuild(), exception caught!" );
2106 // --------------------------------------------------------------------
2108 stl_CustomAnimationEffect_search_node_predict::stl_CustomAnimationEffect_search_node_predict( const ::com::sun::star::uno::Reference
< ::com::sun::star::animations::XAnimationNode
>& xSearchNode
)
2109 : mxSearchNode( xSearchNode
)
2113 // --------------------------------------------------------------------
2115 bool stl_CustomAnimationEffect_search_node_predict::operator()( CustomAnimationEffectPtr pEffect
) const
2117 return pEffect
->getNode() == mxSearchNode
;
2120 // --------------------------------------------------------------------
2122 static bool implFindNextContainer( Reference
< XTimeContainer
>& xParent
, Reference
< XTimeContainer
>& xCurrent
, Reference
< XTimeContainer
>& xNext
)
2125 Reference
< XEnumerationAccess
> xEnumerationAccess( xParent
, UNO_QUERY_THROW
);
2126 Reference
< XEnumeration
> xEnumeration( xEnumerationAccess
->createEnumeration() );
2127 if( xEnumeration
.is() )
2129 Reference
< XInterface
> x
;
2130 while( xEnumeration
->hasMoreElements() && !xNext
.is() )
2132 if( (xEnumeration
->nextElement() >>= x
) && (x
== xCurrent
) )
2134 if( xEnumeration
->hasMoreElements() )
2135 xEnumeration
->nextElement() >>= xNext
;
2142 // --------------------------------------------------------------------
2144 void stl_process_after_effect_node_func(AfterEffectNode
& rNode
)
2148 if( rNode
.mxNode
.is() && rNode
.mxMaster
.is() )
2151 Reference
< XAnimationNode
> xMasterNode( rNode
.mxMaster
, UNO_QUERY_THROW
);
2152 Sequence
< NamedValue
> aUserData( rNode
.mxNode
->getUserData() );
2153 sal_Int32 nSize
= aUserData
.getLength();
2154 aUserData
.realloc(nSize
+1);
2155 aUserData
[nSize
].Name
= "master-element";
2156 aUserData
[nSize
].Value
<<= xMasterNode
;
2157 rNode
.mxNode
->setUserData( aUserData
);
2159 // insert after effect node into timeline
2160 Reference
< XTimeContainer
> xContainer( rNode
.mxMaster
->getParent(), UNO_QUERY_THROW
);
2162 if( !rNode
.mbOnNextEffect
) // sameClick
2164 // insert the aftereffect after its effect is animated
2165 xContainer
->insertAfter( rNode
.mxNode
, rNode
.mxMaster
);
2169 Reference
< XComponentContext
> xContext( ::comphelper::getProcessComponentContext() );
2170 // insert the aftereffect in the next group
2172 Reference
< XTimeContainer
> xClickContainer( xContainer
->getParent(), UNO_QUERY_THROW
);
2173 Reference
< XTimeContainer
> xSequenceContainer( xClickContainer
->getParent(), UNO_QUERY_THROW
);
2175 Reference
< XTimeContainer
> xNextContainer
;
2177 // first try if we have an after effect container
2178 if( !implFindNextContainer( xClickContainer
, xContainer
, xNextContainer
) )
2180 Reference
< XTimeContainer
> xNextClickContainer
;
2181 // if not, try to find the next click effect container
2182 if( implFindNextContainer( xSequenceContainer
, xClickContainer
, xNextClickContainer
) )
2184 Reference
< XEnumerationAccess
> xEnumerationAccess( xNextClickContainer
, UNO_QUERY_THROW
);
2185 Reference
< XEnumeration
> xEnumeration( xEnumerationAccess
->createEnumeration(), UNO_QUERY_THROW
);
2186 if( xEnumeration
->hasMoreElements() )
2188 // the next container is the first child container
2189 xEnumeration
->nextElement() >>= xNextContainer
;
2193 // this does not yet have a child container, create one
2194 xNextContainer
.set( ParallelTimeContainer::create(xContext
), UNO_QUERY_THROW
);
2196 Reference
< XAnimationNode
> xNode( xNextContainer
, UNO_QUERY_THROW
);
2197 xNode
->setBegin( makeAny( (double)0.0 ) );
2198 xNextClickContainer
->appendChild( xNode
);
2200 DBG_ASSERT( xNextContainer
.is(), "ppt::stl_process_after_effect_node_func::operator(), could not find/create container!" );
2204 // if we don't have a next container, we add one to the sequence container
2205 if( !xNextContainer
.is() )
2207 Reference
< XTimeContainer
> xNewClickContainer( ParallelTimeContainer::create( xContext
), UNO_QUERY_THROW
);
2209 Reference
< XAnimationNode
> xNewClickNode( xNewClickContainer
, UNO_QUERY_THROW
);
2212 aEvent
.Trigger
= EventTrigger::ON_NEXT
;
2214 xNewClickNode
->setBegin( makeAny( aEvent
) );
2216 Reference
< XAnimationNode
> xRefNode( xClickContainer
, UNO_QUERY_THROW
);
2217 xSequenceContainer
->insertAfter( xNewClickNode
, xRefNode
);
2219 xNextContainer
.set( ParallelTimeContainer::create( xContext
), UNO_QUERY_THROW
);
2221 DBG_ASSERT( xNextContainer
.is(), "ppt::stl_process_after_effect_node_func::operator(), could not create container!" );
2222 if( xNextContainer
.is() )
2224 Reference
< XAnimationNode
> xNode( xNextContainer
, UNO_QUERY_THROW
);
2225 xNode
->setBegin( makeAny( (double)0.0 ) );
2226 xNewClickContainer
->appendChild( xNode
);
2230 if( xNextContainer
.is() )
2232 // find begin time of first element
2233 Reference
< XEnumerationAccess
> xEnumerationAccess( xNextContainer
, UNO_QUERY_THROW
);
2234 Reference
< XEnumeration
> xEnumeration( xEnumerationAccess
->createEnumeration(), UNO_QUERY_THROW
);
2235 if( xEnumeration
->hasMoreElements() )
2237 Reference
< XAnimationNode
> xChild
;
2238 // the next container is the first child container
2239 xEnumeration
->nextElement() >>= xChild
;
2242 Any
aBegin( xChild
->getBegin() );
2243 double fBegin
= 0.0;
2244 if( (aBegin
>>= fBegin
) && (fBegin
>= 0.0))
2245 rNode
.mxNode
->setBegin( aBegin
);
2249 xNextContainer
->appendChild( rNode
.mxNode
);
2256 OSL_FAIL( "ppt::stl_process_after_effect_node_func::operator(), exception caught!" );
2260 // --------------------------------------------------------------------
2262 EffectSequence::iterator
EffectSequenceHelper::find( const CustomAnimationEffectPtr
& pEffect
)
2264 return std::find( maEffects
.begin(), maEffects
.end(), pEffect
);
2267 // --------------------------------------------------------------------
2269 CustomAnimationEffectPtr
EffectSequenceHelper::findEffect( const ::com::sun::star::uno::Reference
< ::com::sun::star::animations::XAnimationNode
>& xNode
) const
2271 CustomAnimationEffectPtr pEffect
;
2273 EffectSequence::const_iterator
aIter( maEffects
.begin() );
2274 for( ; aIter
!= maEffects
.end(); ++aIter
)
2276 if( (*aIter
)->getNode() == xNode
)
2286 // --------------------------------------------------------------------
2288 sal_Int32
EffectSequenceHelper::getOffsetFromEffect( const CustomAnimationEffectPtr
& xEffect
) const
2290 sal_Int32 nOffset
= 0;
2292 EffectSequence::const_iterator
aIter( maEffects
.begin() );
2293 for( ; aIter
!= maEffects
.end(); ++aIter
, nOffset
++ )
2295 if( (*aIter
) == xEffect
)
2302 // --------------------------------------------------------------------
2304 CustomAnimationEffectPtr
EffectSequenceHelper::getEffectFromOffset( sal_Int32 nOffset
) const
2306 EffectSequence::const_iterator
aIter( maEffects
.begin() );
2307 while( nOffset
-- && aIter
!= maEffects
.end() )
2310 CustomAnimationEffectPtr pEffect
;
2311 if( aIter
!= maEffects
.end() )
2317 // --------------------------------------------------------------------
2319 bool EffectSequenceHelper::disposeShape( const Reference
< XShape
>& xShape
)
2321 bool bChanges
= false;
2323 EffectSequence::iterator
aIter( maEffects
.begin() );
2324 while( aIter
!= maEffects
.end() )
2326 if( (*aIter
)->getTargetShape() == xShape
)
2328 (*aIter
)->setEffectSequence( 0 );
2330 aIter
= maEffects
.erase( aIter
);
2341 // --------------------------------------------------------------------
2343 bool EffectSequenceHelper::hasEffect( const com::sun::star::uno::Reference
< com::sun::star::drawing::XShape
>& xShape
)
2345 EffectSequence::iterator
aIter( maEffects
.begin() );
2346 while( aIter
!= maEffects
.end() )
2348 if( (*aIter
)->getTargetShape() == xShape
)
2356 // --------------------------------------------------------------------
2358 void EffectSequenceHelper::insertTextRange( const com::sun::star::uno::Any
& aTarget
)
2360 bool bChanges
= false;
2362 ParagraphTarget aParaTarget
;
2363 if( !(aTarget
>>= aParaTarget
) )
2366 EffectSequence::iterator
aIter( maEffects
.begin() );
2367 while( aIter
!= maEffects
.end() )
2369 if( (*aIter
)->getTargetShape() == aParaTarget
.Shape
)
2370 bChanges
|= (*aIter
)->checkForText();
2378 // --------------------------------------------------------------------
2380 void EffectSequenceHelper::disposeTextRange( const com::sun::star::uno::Any
& aTarget
)
2382 ParagraphTarget aParaTarget
;
2383 if( !(aTarget
>>= aParaTarget
) )
2386 bool bChanges
= false;
2387 bool bErased
= false;
2389 EffectSequence::iterator
aIter( maEffects
.begin() );
2390 while( aIter
!= maEffects
.end() )
2392 Any
aIterTarget( (*aIter
)->getTarget() );
2393 if( aIterTarget
.getValueType() == ::getCppuType((const ParagraphTarget
*)0) )
2395 ParagraphTarget aIterParaTarget
;
2396 if( (aIterTarget
>>= aIterParaTarget
) && (aIterParaTarget
.Shape
== aParaTarget
.Shape
) )
2398 if( aIterParaTarget
.Paragraph
== aParaTarget
.Paragraph
)
2400 // delete this effect if it targets the disposed paragraph directly
2401 (*aIter
)->setEffectSequence( 0 );
2402 aIter
= maEffects
.erase( aIter
);
2408 if( aIterParaTarget
.Paragraph
> aParaTarget
.Paragraph
)
2410 // shift all paragraphs after disposed paragraph
2411 aIterParaTarget
.Paragraph
--;
2412 (*aIter
)->setTarget( makeAny( aIterParaTarget
) );
2417 else if( (*aIter
)->getTargetShape() == aParaTarget
.Shape
)
2419 bChanges
|= (*aIter
)->checkForText();
2432 // --------------------------------------------------------------------
2434 CustomAnimationTextGroup::CustomAnimationTextGroup( const Reference
< XShape
>& rTarget
, sal_Int32 nGroupId
)
2435 : maTarget( rTarget
),
2436 mnGroupId( nGroupId
)
2441 // --------------------------------------------------------------------
2443 void CustomAnimationTextGroup::reset()
2445 mnTextGrouping
= -1;
2446 mbAnimateForm
= false;
2447 mbTextReverse
= false;
2448 mfGroupingAuto
= -1.0;
2449 mnLastPara
= -1; // used to check for TextReverse
2451 for (int i
= 0; i
< PARA_LEVELS
; ++i
)
2453 mnDepthFlags
[i
] = 0;
2459 // --------------------------------------------------------------------
2461 void CustomAnimationTextGroup::addEffect( CustomAnimationEffectPtr
& pEffect
)
2463 maEffects
.push_back( pEffect
);
2465 Any
aTarget( pEffect
->getTarget() );
2466 if( aTarget
.getValueType() == ::getCppuType((const ParagraphTarget
*)0) )
2468 // now look at the paragraph
2469 ParagraphTarget aParaTarget
;
2470 aTarget
>>= aParaTarget
;
2472 if( mnLastPara
!= -1 )
2473 mbTextReverse
= mnLastPara
> aParaTarget
.Paragraph
;
2475 mnLastPara
= aParaTarget
.Paragraph
;
2477 const sal_Int32 nParaDepth
= pEffect
->getParaDepth();
2479 // only look at the first PARA_LEVELS levels
2480 if( nParaDepth
< PARA_LEVELS
)
2482 // our first paragraph with this level?
2483 if( mnDepthFlags
[nParaDepth
] == 0 )
2485 // so set it to the first found
2486 mnDepthFlags
[nParaDepth
] = (sal_Int8
)pEffect
->getNodeType();
2488 else if( mnDepthFlags
[nParaDepth
] != pEffect
->getNodeType() )
2490 mnDepthFlags
[nParaDepth
] = -1;
2493 if( pEffect
->getNodeType() == EffectNodeType::AFTER_PREVIOUS
)
2494 mfGroupingAuto
= pEffect
->getBegin();
2496 mnTextGrouping
= PARA_LEVELS
;
2497 while( (mnTextGrouping
> 0)
2498 && (mnDepthFlags
[mnTextGrouping
- 1] <= 0) )
2504 // if we have an effect with the shape as a target, we animate the background
2505 mbAnimateForm
= pEffect
->getTargetSubItem() != ShapeAnimationSubType::ONLY_TEXT
;
2509 // --------------------------------------------------------------------
2511 class TextGroupMapImpl
: public std::map
< sal_Int32
, CustomAnimationTextGroup
* >
2514 CustomAnimationTextGroup
* findGroup( sal_Int32 nGroupId
);
2517 // --------------------------------------------------------------------
2519 CustomAnimationTextGroupPtr
EffectSequenceHelper::findGroup( sal_Int32 nGroupId
)
2521 CustomAnimationTextGroupPtr aPtr
;
2523 CustomAnimationTextGroupMap::iterator
aIter( maGroupMap
.find( nGroupId
) );
2524 if( aIter
!= maGroupMap
.end() )
2525 aPtr
= (*aIter
).second
;
2530 // --------------------------------------------------------------------
2532 void EffectSequenceHelper::updateTextGroups()
2536 // first create all the groups
2537 EffectSequence::iterator
aIter( maEffects
.begin() );
2538 const EffectSequence::iterator
aEnd( maEffects
.end() );
2539 while( aIter
!= aEnd
)
2541 CustomAnimationEffectPtr
pEffect( (*aIter
++) );
2543 const sal_Int32 nGroupId
= pEffect
->getGroupId();
2545 if( nGroupId
== -1 )
2546 continue; // trivial case, no group
2548 CustomAnimationTextGroupPtr pGroup
= findGroup( nGroupId
);
2551 pGroup
.reset( new CustomAnimationTextGroup( pEffect
->getTargetShape(), nGroupId
) );
2552 maGroupMap
[nGroupId
] = pGroup
;
2555 pGroup
->addEffect( pEffect
);
2559 // --------------------------------------------------------------------
2561 CustomAnimationTextGroupPtr
EffectSequenceHelper::createTextGroup( CustomAnimationEffectPtr pEffect
, sal_Int32 nTextGrouping
, double fTextGroupingAuto
, sal_Bool bAnimateForm
, sal_Bool bTextReverse
)
2563 // first finde a free group-id
2564 sal_Int32 nGroupId
= 0;
2566 CustomAnimationTextGroupMap::iterator
aIter( maGroupMap
.begin() );
2567 const CustomAnimationTextGroupMap::iterator
aEnd( maGroupMap
.end() );
2568 while( aIter
!= aEnd
)
2570 if( (*aIter
).first
== nGroupId
)
2573 aIter
= maGroupMap
.begin();
2581 Reference
< XShape
> xTarget( pEffect
->getTargetShape() );
2583 CustomAnimationTextGroupPtr
pTextGroup( new CustomAnimationTextGroup( xTarget
, nGroupId
) );
2584 maGroupMap
[nGroupId
] = pTextGroup
;
2588 // do we need to target the shape?
2589 if( (nTextGrouping
== 0) || bAnimateForm
)
2592 if( nTextGrouping
== 0)
2593 nSubItem
= bAnimateForm
? ShapeAnimationSubType::AS_WHOLE
: ShapeAnimationSubType::ONLY_TEXT
;
2595 nSubItem
= ShapeAnimationSubType::ONLY_BACKGROUND
;
2597 pEffect
->setTarget( makeAny( xTarget
) );
2598 pEffect
->setTargetSubItem( nSubItem
);
2599 pEffect
->setEffectSequence( this );
2600 pEffect
->setGroupId( nGroupId
);
2602 pTextGroup
->addEffect( pEffect
);
2606 pTextGroup
->mnTextGrouping
= nTextGrouping
;
2607 pTextGroup
->mfGroupingAuto
= fTextGroupingAuto
;
2608 pTextGroup
->mbTextReverse
= bTextReverse
;
2610 // now add an effect for each paragraph
2611 createTextGroupParagraphEffects( pTextGroup
, pEffect
, bUsed
);
2618 // --------------------------------------------------------------------
2620 void EffectSequenceHelper::createTextGroupParagraphEffects( CustomAnimationTextGroupPtr pTextGroup
, CustomAnimationEffectPtr pEffect
, bool bUsed
)
2622 Reference
< XShape
> xTarget( pTextGroup
->maTarget
);
2624 sal_Int32 nTextGrouping
= pTextGroup
->mnTextGrouping
;
2625 double fTextGroupingAuto
= pTextGroup
->mfGroupingAuto
;
2626 sal_Bool bTextReverse
= pTextGroup
->mbTextReverse
;
2628 // now add an effect for each paragraph
2629 if( nTextGrouping
>= 0 ) try
2631 EffectSequence::iterator
aInsertIter( find( pEffect
) );
2633 Reference
< XEnumerationAccess
> xText( xTarget
, UNO_QUERY_THROW
);
2634 Reference
< XEnumeration
> xEnumeration( xText
->createEnumeration(), UNO_QUERY_THROW
);
2636 std::list
< sal_Int16
> aParaList
;
2639 // fill the list with all valid paragraphs
2640 for( nPara
= 0; xEnumeration
->hasMoreElements(); nPara
++ )
2642 Reference
< XTextRange
> xRange( xEnumeration
->nextElement(), UNO_QUERY
);
2643 if( xRange
.is() && !xRange
->getString().isEmpty() )
2645 if( bTextReverse
) // sort them
2646 aParaList
.push_front( nPara
);
2648 aParaList
.push_back( nPara
);
2652 ParagraphTarget aTarget
;
2653 aTarget
.Shape
= xTarget
;
2655 std::list
< sal_Int16
>::iterator
aIter( aParaList
.begin() );
2656 std::list
< sal_Int16
>::iterator
aEnd( aParaList
.end() );
2657 while( aIter
!= aEnd
)
2659 aTarget
.Paragraph
= (*aIter
++);
2661 CustomAnimationEffectPtr pNewEffect
;
2664 // clone a new effect from first effect
2665 pNewEffect
= pEffect
->clone();
2667 aInsertIter
= maEffects
.insert( aInsertIter
, pNewEffect
);
2671 // reuse first effect if its not yet used
2672 pNewEffect
= pEffect
;
2674 aInsertIter
= find( pNewEffect
);
2677 // set target and group-id
2678 pNewEffect
->setTarget( makeAny( aTarget
) );
2679 pNewEffect
->setTargetSubItem( ShapeAnimationSubType::ONLY_TEXT
);
2680 pNewEffect
->setGroupId( pTextGroup
->mnGroupId
);
2681 pNewEffect
->setEffectSequence( this );
2683 // set correct node type
2684 if( pNewEffect
->getParaDepth() < nTextGrouping
)
2686 if( fTextGroupingAuto
== -1.0 )
2688 pNewEffect
->setNodeType( EffectNodeType::ON_CLICK
);
2689 pNewEffect
->setBegin( 0.0 );
2693 pNewEffect
->setNodeType( EffectNodeType::AFTER_PREVIOUS
);
2694 pNewEffect
->setBegin( fTextGroupingAuto
);
2699 pNewEffect
->setNodeType( EffectNodeType::WITH_PREVIOUS
);
2700 pNewEffect
->setBegin( 0.0 );
2703 pTextGroup
->addEffect( pNewEffect
);
2709 OSL_FAIL("sd::EffectSequenceHelper::createTextGroup(), exception caught!" );
2713 // --------------------------------------------------------------------
2715 void EffectSequenceHelper::setTextGrouping( CustomAnimationTextGroupPtr pTextGroup
, sal_Int32 nTextGrouping
)
2717 if( pTextGroup
->mnTextGrouping
== nTextGrouping
)
2719 // first case, trivial case, do nothing
2721 else if( (pTextGroup
->mnTextGrouping
== -1) && (nTextGrouping
>= 0) )
2723 // second case, we need to add new effects for each paragraph
2725 CustomAnimationEffectPtr
pEffect( pTextGroup
->maEffects
.front() );
2727 pTextGroup
->mnTextGrouping
= nTextGrouping
;
2728 createTextGroupParagraphEffects( pTextGroup
, pEffect
, true );
2731 else if( (pTextGroup
->mnTextGrouping
>= 0) && (nTextGrouping
== -1 ) )
2733 // third case, we need to remove effects for each paragraph
2735 EffectSequence
aEffects( pTextGroup
->maEffects
);
2736 pTextGroup
->reset();
2738 EffectSequence::iterator
aIter( aEffects
.begin() );
2739 const EffectSequence::iterator
aEnd( aEffects
.end() );
2740 while( aIter
!= aEnd
)
2742 CustomAnimationEffectPtr
pEffect( (*aIter
++) );
2744 if( pEffect
->getTarget().getValueType() == ::getCppuType((const ParagraphTarget
*)0) )
2747 pTextGroup
->addEffect( pEffect
);
2753 // fourth case, we need to change the node types for the text nodes
2754 double fTextGroupingAuto
= pTextGroup
->mfGroupingAuto
;
2756 EffectSequence
aEffects( pTextGroup
->maEffects
);
2757 pTextGroup
->reset();
2759 EffectSequence::iterator
aIter( aEffects
.begin() );
2760 const EffectSequence::iterator
aEnd( aEffects
.end() );
2761 while( aIter
!= aEnd
)
2763 CustomAnimationEffectPtr
pEffect( (*aIter
++) );
2765 if( pEffect
->getTarget().getValueType() == ::getCppuType((const ParagraphTarget
*)0) )
2767 // set correct node type
2768 if( pEffect
->getParaDepth() < nTextGrouping
)
2770 if( fTextGroupingAuto
== -1.0 )
2772 pEffect
->setNodeType( EffectNodeType::ON_CLICK
);
2773 pEffect
->setBegin( 0.0 );
2777 pEffect
->setNodeType( EffectNodeType::AFTER_PREVIOUS
);
2778 pEffect
->setBegin( fTextGroupingAuto
);
2783 pEffect
->setNodeType( EffectNodeType::WITH_PREVIOUS
);
2784 pEffect
->setBegin( 0.0 );
2788 pTextGroup
->addEffect( pEffect
);
2795 // --------------------------------------------------------------------
2797 void EffectSequenceHelper::setAnimateForm( CustomAnimationTextGroupPtr pTextGroup
, sal_Bool bAnimateForm
)
2799 if( pTextGroup
->mbAnimateForm
== bAnimateForm
)
2801 // trivial case, do nothing
2805 EffectSequence
aEffects( pTextGroup
->maEffects
);
2806 pTextGroup
->reset();
2808 SAL_WARN_IF(aEffects
.empty(), "sd", "EffectSequenceHelper::setAnimateForm effects empty" );
2810 if (aEffects
.empty())
2813 EffectSequence::iterator
aIter( aEffects
.begin() );
2814 const EffectSequence::iterator
aEnd( aEffects
.end() );
2816 // first insert if we have to
2819 EffectSequence::iterator
aInsertIter( find( (*aIter
) ) );
2821 CustomAnimationEffectPtr pEffect
;
2822 if( (aEffects
.size() == 1) && ((*aIter
)->getTarget().getValueType() != ::getCppuType((const ParagraphTarget
*)0) ) )
2824 // special case, only one effect and that targets whole text,
2825 // convert this to target whole shape
2826 pEffect
= (*aIter
++);
2827 pEffect
->setTargetSubItem( ShapeAnimationSubType::AS_WHOLE
);
2831 pEffect
= (*aIter
)->clone();
2832 pEffect
->setTarget( makeAny( (*aIter
)->getTargetShape() ) );
2833 pEffect
->setTargetSubItem( ShapeAnimationSubType::ONLY_BACKGROUND
);
2834 maEffects
.insert( aInsertIter
, pEffect
);
2837 pTextGroup
->addEffect( pEffect
);
2840 if( !bAnimateForm
&& (aEffects
.size() == 1) )
2842 CustomAnimationEffectPtr
pEffect( (*aIter
) );
2843 pEffect
->setTarget( makeAny( (*aIter
)->getTargetShape() ) );
2844 pEffect
->setTargetSubItem( ShapeAnimationSubType::ONLY_TEXT
);
2845 pTextGroup
->addEffect( pEffect
);
2849 // readd the rest to the group again
2850 while( aIter
!= aEnd
)
2852 CustomAnimationEffectPtr
pEffect( (*aIter
++) );
2854 if( pEffect
->getTarget().getValueType() == ::getCppuType((const ParagraphTarget
*)0) )
2856 pTextGroup
->addEffect( pEffect
);
2860 DBG_ASSERT( !bAnimateForm
, "sd::EffectSequenceHelper::setAnimateForm(), something is wrong here!" );
2869 // --------------------------------------------------------------------
2871 void EffectSequenceHelper::setTextGroupingAuto( CustomAnimationTextGroupPtr pTextGroup
, double fTextGroupingAuto
)
2873 sal_Int32 nTextGrouping
= pTextGroup
->mnTextGrouping
;
2875 EffectSequence
aEffects( pTextGroup
->maEffects
);
2876 pTextGroup
->reset();
2878 EffectSequence::iterator
aIter( aEffects
.begin() );
2879 const EffectSequence::iterator
aEnd( aEffects
.end() );
2880 while( aIter
!= aEnd
)
2882 CustomAnimationEffectPtr
pEffect( (*aIter
++) );
2884 if( pEffect
->getTarget().getValueType() == ::getCppuType((const ParagraphTarget
*)0) )
2886 // set correct node type
2887 if( pEffect
->getParaDepth() < nTextGrouping
)
2889 if( fTextGroupingAuto
== -1.0 )
2891 pEffect
->setNodeType( EffectNodeType::ON_CLICK
);
2892 pEffect
->setBegin( 0.0 );
2896 pEffect
->setNodeType( EffectNodeType::AFTER_PREVIOUS
);
2897 pEffect
->setBegin( fTextGroupingAuto
);
2902 pEffect
->setNodeType( EffectNodeType::WITH_PREVIOUS
);
2903 pEffect
->setBegin( 0.0 );
2907 pTextGroup
->addEffect( pEffect
);
2913 // --------------------------------------------------------------------
2915 struct ImplStlTextGroupSortHelper
2917 ImplStlTextGroupSortHelper( bool bReverse
) : mbReverse( bReverse
) {};
2918 bool operator()( const CustomAnimationEffectPtr
& p1
, const CustomAnimationEffectPtr
& p2
);
2920 sal_Int32
getTargetParagraph( const CustomAnimationEffectPtr
& p1
);
2923 // --------------------------------------------------------------------
2925 sal_Int32
ImplStlTextGroupSortHelper::getTargetParagraph( const CustomAnimationEffectPtr
& p1
)
2927 const Any
aTarget(p1
->getTarget());
2928 if( aTarget
.hasValue() && aTarget
.getValueType() == ::getCppuType((const ParagraphTarget
*)0) )
2930 ParagraphTarget aParaTarget
;
2931 aTarget
>>= aParaTarget
;
2932 return aParaTarget
.Paragraph
;
2936 return mbReverse
? 0x7fffffff : -1;
2940 // --------------------------------------------------------------------
2942 bool ImplStlTextGroupSortHelper::operator()( const CustomAnimationEffectPtr
& p1
, const CustomAnimationEffectPtr
& p2
)
2946 return getTargetParagraph( p2
) < getTargetParagraph( p1
);
2950 return getTargetParagraph( p1
) < getTargetParagraph( p2
);
2954 // --------------------------------------------------------------------
2956 void EffectSequenceHelper::setTextReverse( CustomAnimationTextGroupPtr pTextGroup
, sal_Bool bTextReverse
)
2958 if( pTextGroup
->mbTextReverse
== bTextReverse
)
2964 std::vector
< CustomAnimationEffectPtr
> aSortedVector(pTextGroup
->maEffects
.size());
2965 std::copy( pTextGroup
->maEffects
.begin(), pTextGroup
->maEffects
.end(), aSortedVector
.begin() );
2966 ImplStlTextGroupSortHelper
aSortHelper( bTextReverse
);
2967 std::sort( aSortedVector
.begin(), aSortedVector
.end(), aSortHelper
);
2969 pTextGroup
->reset();
2971 std::vector
< CustomAnimationEffectPtr
>::iterator
aIter( aSortedVector
.begin() );
2972 const std::vector
< CustomAnimationEffectPtr
>::iterator
aEnd( aSortedVector
.end() );
2976 pTextGroup
->addEffect( (*aIter
) );
2977 EffectSequence::iterator
aInsertIter( find( (*aIter
++) ) );
2978 while( aIter
!= aEnd
)
2980 CustomAnimationEffectPtr
pEffect( (*aIter
++) );
2981 maEffects
.erase( find( pEffect
) );
2982 aInsertIter
= maEffects
.insert( ++aInsertIter
, pEffect
);
2983 pTextGroup
->addEffect( pEffect
);
2990 // --------------------------------------------------------------------
2992 void EffectSequenceHelper::addListener( ISequenceListener
* pListener
)
2994 if( std::find( maListeners
.begin(), maListeners
.end(), pListener
) == maListeners
.end() )
2995 maListeners
.push_back( pListener
);
2998 // --------------------------------------------------------------------
3000 void EffectSequenceHelper::removeListener( ISequenceListener
* pListener
)
3002 maListeners
.remove( pListener
);
3005 // --------------------------------------------------------------------
3007 struct stl_notify_listeners_func
: public std::unary_function
<ISequenceListener
*, void>
3009 stl_notify_listeners_func() {}
3010 void operator()(ISequenceListener
* pListener
) { pListener
->notify_change(); }
3013 // --------------------------------------------------------------------
3015 void EffectSequenceHelper::notify_listeners()
3017 stl_notify_listeners_func aFunc
;
3018 std::for_each( maListeners
.begin(), maListeners
.end(), aFunc
);
3021 // --------------------------------------------------------------------
3023 void EffectSequenceHelper::create( const ::com::sun::star::uno::Reference
< ::com::sun::star::animations::XAnimationNode
>& xNode
)
3025 DBG_ASSERT( xNode
.is(), "sd::EffectSequenceHelper::create(), illegal argument" );
3027 if( xNode
.is() ) try
3029 Reference
< XEnumerationAccess
> xEnumerationAccess( xNode
, UNO_QUERY_THROW
);
3030 Reference
< XEnumeration
> xEnumeration( xEnumerationAccess
->createEnumeration(), UNO_QUERY_THROW
);
3031 while( xEnumeration
->hasMoreElements() )
3033 Reference
< XAnimationNode
> xChildNode( xEnumeration
->nextElement(), UNO_QUERY_THROW
);
3034 createEffectsequence( xChildNode
);
3039 OSL_FAIL( "sd::EffectSequenceHelper::create(), exception caught!" );
3043 // --------------------------------------------------------------------
3045 void EffectSequenceHelper::createEffectsequence( const Reference
< XAnimationNode
>& xNode
)
3047 DBG_ASSERT( xNode
.is(), "sd::EffectSequenceHelper::createEffectsequence(), illegal argument" );
3049 if( xNode
.is() ) try
3051 Reference
< XEnumerationAccess
> xEnumerationAccess( xNode
, UNO_QUERY_THROW
);
3052 Reference
< XEnumeration
> xEnumeration( xEnumerationAccess
->createEnumeration(), UNO_QUERY_THROW
);
3053 while( xEnumeration
->hasMoreElements() )
3055 Reference
< XAnimationNode
> xChildNode( xEnumeration
->nextElement(), UNO_QUERY_THROW
);
3057 createEffects( xChildNode
);
3062 OSL_FAIL( "sd::EffectSequenceHelper::createEffectsequence(), exception caught!" );
3066 // --------------------------------------------------------------------
3068 void EffectSequenceHelper::createEffects( const Reference
< XAnimationNode
>& xNode
)
3070 DBG_ASSERT( xNode
.is(), "sd::EffectSequenceHelper::createEffects(), illegal argument" );
3072 if( xNode
.is() ) try
3074 Reference
< XEnumerationAccess
> xEnumerationAccess( xNode
, UNO_QUERY_THROW
);
3075 Reference
< XEnumeration
> xEnumeration( xEnumerationAccess
->createEnumeration(), UNO_QUERY_THROW
);
3076 while( xEnumeration
->hasMoreElements() )
3078 Reference
< XAnimationNode
> xChildNode( xEnumeration
->nextElement(), UNO_QUERY_THROW
);
3080 switch( xChildNode
->getType() )
3083 case AnimationNodeType::PAR
:
3084 case AnimationNodeType::ITERATE
:
3086 CustomAnimationEffectPtr
pEffect( new CustomAnimationEffect( xChildNode
) );
3088 if( pEffect
->mnNodeType
!= -1 )
3090 pEffect
->setEffectSequence( this );
3091 maEffects
.push_back(pEffect
);
3096 // found an after effect
3097 case AnimationNodeType::SET
:
3098 case AnimationNodeType::ANIMATECOLOR
:
3100 processAfterEffect( xChildNode
);
3108 OSL_FAIL( "sd::EffectSequenceHelper::createEffects(), exception caught!" );
3112 // --------------------------------------------------------------------
3114 void EffectSequenceHelper::processAfterEffect( const Reference
< XAnimationNode
>& xNode
)
3118 Reference
< XAnimationNode
> xMaster
;
3120 Sequence
< NamedValue
> aUserData( xNode
->getUserData() );
3121 sal_Int32 nLength
= aUserData
.getLength();
3122 const NamedValue
* p
= aUserData
.getConstArray();
3126 if ( p
->Name
== "master-element" )
3128 p
->Value
>>= xMaster
;
3134 // only process if this is a valid after effect
3137 CustomAnimationEffectPtr pMasterEffect
;
3139 // find the master effect
3140 stl_CustomAnimationEffect_search_node_predict
aSearchPredict( xMaster
);
3141 EffectSequence::iterator
aIter( std::find_if( maEffects
.begin(), maEffects
.end(), aSearchPredict
) );
3142 if( aIter
!= maEffects
.end() )
3143 pMasterEffect
= (*aIter
);
3145 if( pMasterEffect
.get() )
3147 pMasterEffect
->setHasAfterEffect( true );
3149 // find out what kind of after effect this is
3150 if( xNode
->getType() == AnimationNodeType::ANIMATECOLOR
)
3153 Reference
< XAnimate
> xAnimate( xNode
, UNO_QUERY_THROW
);
3154 pMasterEffect
->setDimColor( xAnimate
->getTo() );
3155 pMasterEffect
->setAfterEffectOnNext( true );
3160 Reference
< XChild
> xNodeChild( xNode
, UNO_QUERY_THROW
);
3161 Reference
< XChild
> xMasterChild( xMaster
, UNO_QUERY_THROW
);
3162 pMasterEffect
->setAfterEffectOnNext( xNodeChild
->getParent() != xMasterChild
->getParent() );
3169 OSL_FAIL( "sd::EffectSequenceHelper::processAfterEffect(), exception caught!" );
3173 // ====================================================================
3175 class AnimationChangeListener
: public cppu::WeakImplHelper1
< XChangesListener
>
3178 AnimationChangeListener( MainSequence
* pMainSequence
) : mpMainSequence( pMainSequence
) {}
3180 virtual void SAL_CALL
changesOccurred( const ::com::sun::star::util::ChangesEvent
& Event
) throw (RuntimeException
);
3181 virtual void SAL_CALL
disposing( const ::com::sun::star::lang::EventObject
& Source
) throw (RuntimeException
);
3183 MainSequence
* mpMainSequence
;
3186 void SAL_CALL
AnimationChangeListener::changesOccurred( const ::com::sun::star::util::ChangesEvent
& ) throw (RuntimeException
)
3188 if( mpMainSequence
)
3189 mpMainSequence
->startRecreateTimer();
3192 void SAL_CALL
AnimationChangeListener::disposing( const ::com::sun::star::lang::EventObject
& ) throw (RuntimeException
)
3196 // ====================================================================
3198 MainSequence::MainSequence()
3199 : mxTimingRootNode( SequenceTimeContainer::create( ::comphelper::getProcessComponentContext() ) )
3200 , mbRebuilding( false )
3201 , mnRebuildLockGuard( 0 )
3202 , mbPendingRebuildRequest( false )
3204 if( mxTimingRootNode
.is() )
3206 Sequence
< ::com::sun::star::beans::NamedValue
> aUserData( 1 );
3207 aUserData
[0].Name
= "node-type";
3208 aUserData
[0].Value
<<= ::com::sun::star::presentation::EffectNodeType::MAIN_SEQUENCE
;
3209 mxTimingRootNode
->setUserData( aUserData
);
3214 // --------------------------------------------------------------------
3216 MainSequence::MainSequence( const ::com::sun::star::uno::Reference
< ::com::sun::star::animations::XAnimationNode
>& xNode
)
3217 : mxTimingRootNode( xNode
, UNO_QUERY
)
3218 , mbRebuilding( false )
3219 , mnRebuildLockGuard( 0 )
3220 , mbPendingRebuildRequest( false )
3221 , mbIgnoreChanges( 0 )
3226 // --------------------------------------------------------------------
3228 MainSequence::~MainSequence()
3233 // --------------------------------------------------------------------
3235 void MainSequence::init()
3237 mnSequenceType
= EffectNodeType::MAIN_SEQUENCE
;
3239 maTimer
.SetTimeoutHdl( LINK(this, MainSequence
, onTimerHdl
) );
3240 maTimer
.SetTimeout(500);
3242 mxChangesListener
.set( new AnimationChangeListener( this ) );
3244 createMainSequence();
3247 // --------------------------------------------------------------------
3249 void MainSequence::reset( const ::com::sun::star::uno::Reference
< ::com::sun::star::animations::XAnimationNode
>& xTimingRootNode
)
3253 mxTimingRootNode
.set( xTimingRootNode
, UNO_QUERY
);
3255 createMainSequence();
3258 // --------------------------------------------------------------------
3260 Reference
< ::com::sun::star::animations::XAnimationNode
> MainSequence::getRootNode()
3262 DBG_ASSERT( mnRebuildLockGuard
== 0, "MainSequence::getRootNode(), rebuild is locked, is this really what you want?" );
3264 if( maTimer
.IsActive() && mbTimerMode
)
3266 // force a rebuild NOW if one is pending
3271 return EffectSequenceHelper::getRootNode();
3274 // --------------------------------------------------------------------
3276 void MainSequence::createMainSequence()
3278 if( mxTimingRootNode
.is() ) try
3280 Reference
< XEnumerationAccess
> xEnumerationAccess( mxTimingRootNode
, UNO_QUERY_THROW
);
3281 Reference
< XEnumeration
> xEnumeration( xEnumerationAccess
->createEnumeration(), UNO_QUERY_THROW
);
3282 while( xEnumeration
->hasMoreElements() )
3284 Reference
< XAnimationNode
> xChildNode( xEnumeration
->nextElement(), UNO_QUERY_THROW
);
3285 sal_Int32 nNodeType
= CustomAnimationEffect::get_node_type( xChildNode
);
3286 if( nNodeType
== EffectNodeType::MAIN_SEQUENCE
)
3288 mxSequenceRoot
.set( xChildNode
, UNO_QUERY
);
3289 EffectSequenceHelper::create( xChildNode
);
3291 else if( nNodeType
== EffectNodeType::INTERACTIVE_SEQUENCE
)
3293 Reference
< XTimeContainer
> xInteractiveRoot( xChildNode
, UNO_QUERY_THROW
);
3294 InteractiveSequencePtr
pIS( new InteractiveSequence( xInteractiveRoot
, this ) );
3295 pIS
->addListener( this );
3296 maInteractiveSequenceList
.push_back( pIS
);
3300 // see if we have a mainsequence at all. if not, create one...
3301 if( !mxSequenceRoot
.is() )
3303 mxSequenceRoot
= SequenceTimeContainer::create( ::comphelper::getProcessComponentContext() );
3305 uno::Sequence
< ::com::sun::star::beans::NamedValue
> aUserData( 1 );
3306 aUserData
[0].Name
= "node-type";
3307 aUserData
[0].Value
<<= ::com::sun::star::presentation::EffectNodeType::MAIN_SEQUENCE
;
3308 mxSequenceRoot
->setUserData( aUserData
);
3310 // empty sequence until now, set duration to 0.0
3311 // explicitly (otherwise, this sequence will never
3313 mxSequenceRoot
->setDuration( makeAny((double)0.0) );
3315 Reference
< XAnimationNode
> xMainSequenceNode( mxSequenceRoot
, UNO_QUERY_THROW
);
3316 mxTimingRootNode
->appendChild( xMainSequenceNode
);
3323 Reference
< XChangesNotifier
> xNotifier( mxTimingRootNode
, UNO_QUERY
);
3324 if( xNotifier
.is() )
3325 xNotifier
->addChangesListener( mxChangesListener
);
3329 OSL_FAIL( "sd::MainSequence::create(), exception caught!" );
3333 DBG_ASSERT( mxSequenceRoot
.is(), "sd::MainSequence::create(), found no main sequence!" );
3336 // --------------------------------------------------------------------
3338 void MainSequence::reset()
3340 EffectSequenceHelper::reset();
3342 InteractiveSequenceList::iterator aIter
;
3343 for( aIter
= maInteractiveSequenceList
.begin(); aIter
!= maInteractiveSequenceList
.end(); ++aIter
)
3345 maInteractiveSequenceList
.clear();
3349 Reference
< XChangesNotifier
> xNotifier( mxTimingRootNode
, UNO_QUERY
);
3350 if( xNotifier
.is() )
3351 xNotifier
->removeChangesListener( mxChangesListener
);
3359 // --------------------------------------------------------------------
3361 InteractiveSequencePtr
MainSequence::createInteractiveSequence( const ::com::sun::star::uno::Reference
< ::com::sun::star::drawing::XShape
>& xShape
)
3363 InteractiveSequencePtr pIS
;
3365 // create a new interactive sequence container
3366 Reference
< XTimeContainer
> xISRoot
= SequenceTimeContainer::create( ::comphelper::getProcessComponentContext() );
3368 uno::Sequence
< ::com::sun::star::beans::NamedValue
> aUserData( 1 );
3369 aUserData
[0].Name
= "node-type";
3370 aUserData
[0].Value
<<= ::com::sun::star::presentation::EffectNodeType::INTERACTIVE_SEQUENCE
;
3371 xISRoot
->setUserData( aUserData
);
3373 Reference
< XChild
> xChild( mxSequenceRoot
, UNO_QUERY_THROW
);
3374 Reference
< XAnimationNode
> xISNode( xISRoot
, UNO_QUERY_THROW
);
3375 Reference
< XTimeContainer
> xParent( xChild
->getParent(), UNO_QUERY_THROW
);
3376 xParent
->appendChild( xISNode
);
3378 pIS
.reset( new InteractiveSequence( xISRoot
, this) );
3379 pIS
->setTriggerShape( xShape
);
3380 pIS
->addListener( this );
3381 maInteractiveSequenceList
.push_back( pIS
);
3385 // --------------------------------------------------------------------
3387 CustomAnimationEffectPtr
MainSequence::findEffect( const ::com::sun::star::uno::Reference
< ::com::sun::star::animations::XAnimationNode
>& xNode
) const
3389 CustomAnimationEffectPtr pEffect
= EffectSequenceHelper::findEffect( xNode
);
3391 if( pEffect
.get() == 0 )
3393 InteractiveSequenceList::const_iterator aIter
;
3394 for( aIter
= maInteractiveSequenceList
.begin(); (aIter
!= maInteractiveSequenceList
.end()) && (pEffect
.get() == 0); ++aIter
)
3396 pEffect
= (*aIter
)->findEffect( xNode
);
3402 // --------------------------------------------------------------------
3404 sal_Int32
MainSequence::getOffsetFromEffect( const CustomAnimationEffectPtr
& pEffect
) const
3406 sal_Int32 nOffset
= EffectSequenceHelper::getOffsetFromEffect( pEffect
);
3411 nOffset
= EffectSequenceHelper::getCount();
3413 InteractiveSequenceList::const_iterator aIter
;
3414 for( aIter
= maInteractiveSequenceList
.begin(); aIter
!= maInteractiveSequenceList
.end(); ++aIter
)
3416 sal_Int32 nTemp
= (*aIter
)->getOffsetFromEffect( pEffect
);
3418 return nOffset
+ nTemp
;
3420 nOffset
+= (*aIter
)->getCount();
3426 // --------------------------------------------------------------------
3428 CustomAnimationEffectPtr
MainSequence::getEffectFromOffset( sal_Int32 nOffset
) const
3432 if( nOffset
< getCount() )
3433 return EffectSequenceHelper::getEffectFromOffset( nOffset
);
3435 nOffset
-= getCount();
3437 InteractiveSequenceList::const_iterator
aIter( maInteractiveSequenceList
.begin() );
3439 while( (aIter
!= maInteractiveSequenceList
.end()) && (nOffset
> (*aIter
)->getCount()) )
3440 nOffset
-= (*aIter
++)->getCount();
3442 if( (aIter
!= maInteractiveSequenceList
.end()) && (nOffset
>= 0) )
3443 return (*aIter
)->getEffectFromOffset( nOffset
);
3446 CustomAnimationEffectPtr pEffect
;
3450 // --------------------------------------------------------------------
3452 bool MainSequence::disposeShape( const Reference
< XShape
>& xShape
)
3454 bool bChanges
= EffectSequenceHelper::disposeShape( xShape
);
3456 InteractiveSequenceList::iterator aIter
;
3457 for( aIter
= maInteractiveSequenceList
.begin(); aIter
!= maInteractiveSequenceList
.end(); )
3459 if( (*aIter
)->getTriggerShape() == xShape
)
3461 aIter
= maInteractiveSequenceList
.erase( aIter
);
3466 bChanges
|= (*aIter
++)->disposeShape( xShape
);
3471 startRebuildTimer();
3476 // --------------------------------------------------------------------
3478 bool MainSequence::hasEffect( const com::sun::star::uno::Reference
< com::sun::star::drawing::XShape
>& xShape
)
3480 if( EffectSequenceHelper::hasEffect( xShape
) )
3483 InteractiveSequenceList::iterator aIter
;
3484 for( aIter
= maInteractiveSequenceList
.begin(); aIter
!= maInteractiveSequenceList
.end(); )
3486 if( (*aIter
)->getTriggerShape() == xShape
)
3489 if( (*aIter
++)->hasEffect( xShape
) )
3496 // --------------------------------------------------------------------
3498 void MainSequence::insertTextRange( const com::sun::star::uno::Any
& aTarget
)
3500 EffectSequenceHelper::insertTextRange( aTarget
);
3502 InteractiveSequenceList::iterator aIter
;
3503 for( aIter
= maInteractiveSequenceList
.begin(); aIter
!= maInteractiveSequenceList
.end(); ++aIter
)
3505 (*aIter
)->insertTextRange( aTarget
);
3508 // --------------------------------------------------------------------
3510 void MainSequence::disposeTextRange( const com::sun::star::uno::Any
& aTarget
)
3512 EffectSequenceHelper::disposeTextRange( aTarget
);
3514 InteractiveSequenceList::iterator aIter
;
3515 for( aIter
= maInteractiveSequenceList
.begin(); aIter
!= maInteractiveSequenceList
.end(); ++aIter
)
3517 (*aIter
)->disposeTextRange( aTarget
);
3521 // --------------------------------------------------------------------
3523 /** callback from the sd::View when an object just left text edit mode */
3524 void MainSequence::onTextChanged( const Reference
< XShape
>& xShape
)
3526 EffectSequenceHelper::onTextChanged( xShape
);
3528 InteractiveSequenceList::iterator aIter
;
3529 for( aIter
= maInteractiveSequenceList
.begin(); aIter
!= maInteractiveSequenceList
.end(); ++aIter
)
3531 (*aIter
)->onTextChanged( xShape
);
3535 // --------------------------------------------------------------------
3537 void EffectSequenceHelper::onTextChanged( const Reference
< XShape
>& xShape
)
3539 bool bChanges
= false;
3541 EffectSequence::iterator aIter
;
3542 for( aIter
= maEffects
.begin(); aIter
!= maEffects
.end(); ++aIter
)
3544 if( (*aIter
)->getTargetShape() == xShape
)
3545 bChanges
|= (*aIter
)->checkForText();
3549 EffectSequenceHelper::implRebuild();
3552 // --------------------------------------------------------------------
3554 void MainSequence::rebuild()
3556 startRebuildTimer();
3559 // --------------------------------------------------------------------
3561 void MainSequence::lockRebuilds()
3563 mnRebuildLockGuard
++;
3566 // --------------------------------------------------------------------
3568 void MainSequence::unlockRebuilds()
3570 DBG_ASSERT( mnRebuildLockGuard
, "sd::MainSequence::unlockRebuilds(), no corresponding lockRebuilds() call!" );
3571 if( mnRebuildLockGuard
)
3572 mnRebuildLockGuard
--;
3574 if( (mnRebuildLockGuard
== 0) && mbPendingRebuildRequest
)
3576 mbPendingRebuildRequest
= false;
3577 startRebuildTimer();
3581 // --------------------------------------------------------------------
3583 void MainSequence::implRebuild()
3585 if( mnRebuildLockGuard
)
3587 mbPendingRebuildRequest
= true;
3591 mbRebuilding
= true;
3593 EffectSequenceHelper::implRebuild();
3595 InteractiveSequenceList::iterator
aIter( maInteractiveSequenceList
.begin() );
3596 const InteractiveSequenceList::iterator
aEnd( maInteractiveSequenceList
.end() );
3597 while( aIter
!= aEnd
)
3599 InteractiveSequencePtr
pIS( (*aIter
) );
3600 if( pIS
->maEffects
.empty() )
3602 // remove empty interactive sequences
3603 aIter
= maInteractiveSequenceList
.erase( aIter
);
3605 Reference
< XChild
> xChild( mxSequenceRoot
, UNO_QUERY_THROW
);
3606 Reference
< XTimeContainer
> xParent( xChild
->getParent(), UNO_QUERY_THROW
);
3607 Reference
< XAnimationNode
> xISNode( pIS
->mxSequenceRoot
, UNO_QUERY_THROW
);
3608 xParent
->removeChild( xISNode
);
3618 mbRebuilding
= false;
3621 // --------------------------------------------------------------------
3623 void MainSequence::notify_change()
3628 // --------------------------------------------------------------------
3630 bool MainSequence::setTrigger( const CustomAnimationEffectPtr
& pEffect
, const ::com::sun::star::uno::Reference
< ::com::sun::star::drawing::XShape
>& xTriggerShape
)
3632 EffectSequenceHelper
* pOldSequence
= pEffect
->getEffectSequence();
3634 EffectSequenceHelper
* pNewSequence
= 0;
3635 if( xTriggerShape
.is() )
3637 InteractiveSequenceList::iterator
aIter( maInteractiveSequenceList
.begin() );
3638 const InteractiveSequenceList::iterator
aEnd( maInteractiveSequenceList
.end() );
3639 while( aIter
!= aEnd
)
3641 InteractiveSequencePtr
pIS( (*aIter
++) );
3642 if( pIS
->getTriggerShape() == xTriggerShape
)
3644 pNewSequence
= pIS
.get();
3650 pNewSequence
= createInteractiveSequence( xTriggerShape
).get();
3654 pNewSequence
= this;
3657 if( pOldSequence
!= pNewSequence
)
3660 pOldSequence
->maEffects
.remove( pEffect
);
3662 pNewSequence
->maEffects
.push_back( pEffect
);
3663 pEffect
->setEffectSequence( pNewSequence
);
3673 // --------------------------------------------------------------------
3675 IMPL_LINK_NOARG(MainSequence
, onTimerHdl
)
3684 createMainSequence();
3690 // --------------------------------------------------------------------
3692 /** starts a timer that recreates the internal structure from the API core after 1 second */
3693 void MainSequence::startRecreateTimer()
3695 if( !mbRebuilding
&& (mbIgnoreChanges
== 0) )
3697 mbTimerMode
= false;
3702 // --------------------------------------------------------------------
3704 /** starts a timer that rebuilds the API core from the internal structure after 1 second */
3705 void MainSequence::startRebuildTimer()
3711 // ====================================================================
3713 InteractiveSequence::InteractiveSequence( const Reference
< XTimeContainer
>& xSequenceRoot
, MainSequence
* pMainSequence
)
3714 : EffectSequenceHelper( xSequenceRoot
), mpMainSequence( pMainSequence
)
3716 mnSequenceType
= EffectNodeType::INTERACTIVE_SEQUENCE
;
3720 if( mxSequenceRoot
.is() )
3722 Reference
< XEnumerationAccess
> xEnumerationAccess( mxSequenceRoot
, UNO_QUERY_THROW
);
3723 Reference
< XEnumeration
> xEnumeration( xEnumerationAccess
->createEnumeration(), UNO_QUERY_THROW
);
3724 while( !mxEventSource
.is() && xEnumeration
->hasMoreElements() )
3726 Reference
< XAnimationNode
> xChildNode( xEnumeration
->nextElement(), UNO_QUERY_THROW
);
3729 if( (xChildNode
->getBegin() >>= aEvent
) && (aEvent
.Trigger
== EventTrigger::ON_CLICK
) )
3730 aEvent
.Source
>>= mxEventSource
;
3736 OSL_FAIL( "sd::InteractiveSequence::InteractiveSequence(), exception caught!" );
3741 // --------------------------------------------------------------------
3743 void InteractiveSequence::rebuild()
3745 mpMainSequence
->rebuild();
3748 void InteractiveSequence::implRebuild()
3750 EffectSequenceHelper::implRebuild();
3753 // --------------------------------------------------------------------
3755 MainSequenceRebuildGuard::MainSequenceRebuildGuard( const MainSequencePtr
& pMainSequence
)
3756 : mpMainSequence( pMainSequence
)
3758 if( mpMainSequence
.get() )
3759 mpMainSequence
->lockRebuilds();
3762 MainSequenceRebuildGuard::~MainSequenceRebuildGuard()
3764 if( mpMainSequence
.get() )
3765 mpMainSequence
->unlockRebuilds();
3771 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */