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