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