Update ooo320-m1
[ooovba.git] / slideshow / source / engine / animationnodes / basenode.cxx
blob90eb97d86a0aaf2fae569aca2e1fed5464b6d997
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: basenode.cxx,v $
10 * $Revision: 1.13 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_slideshow.hxx"
34 // must be first
35 #include <canvas/debug.hxx>
36 #include <canvas/verbosetrace.hxx>
38 #include <com/sun/star/animations/XAnimate.hpp>
39 #include <com/sun/star/presentation/ParagraphTarget.hpp>
40 #include <com/sun/star/animations/AnimationFill.hpp>
41 #include <com/sun/star/animations/AnimationRestart.hpp>
42 #include <com/sun/star/presentation/EffectNodeType.hpp>
43 #include <com/sun/star/beans/XPropertySet.hpp>
45 #include "basenode.hxx"
46 #include "eventmultiplexer.hxx"
47 #include "basecontainernode.hxx"
48 #include "eventqueue.hxx"
49 #include "delayevent.hxx"
50 #include "tools.hxx"
51 #include "nodetools.hxx"
52 #include "generateevent.hxx"
54 #include <boost/bind.hpp>
55 #include <vector>
56 #include <algorithm>
57 #include <iterator>
59 using namespace ::com::sun::star;
61 namespace slideshow {
62 namespace internal {
64 namespace {
66 typedef int StateTransitionTable[17];
68 // State transition tables
69 // =========================================================================
71 const int* getStateTransitionTable( sal_Int16 nRestartMode,
72 sal_Int16 nFillMode )
74 // TODO(F2): restart issues in below tables
76 // transition table for restart=NEVER, fill=REMOVE
77 static const StateTransitionTable stateTransitionTable_Never_Remove = {
78 AnimationNode::INVALID,
79 AnimationNode::RESOLVED|AnimationNode::ENDED, // active successors for UNRESOLVED
80 AnimationNode::ACTIVE|AnimationNode::ENDED, // active successors for RESOLVED
81 AnimationNode::INVALID,
82 AnimationNode::ENDED, // active successors for ACTIVE: no freeze here
83 AnimationNode::INVALID,
84 AnimationNode::INVALID,
85 AnimationNode::INVALID,
86 AnimationNode::INVALID, // active successors for FROZEN: this state is unreachable here
87 AnimationNode::INVALID,
88 AnimationNode::INVALID,
89 AnimationNode::INVALID,
90 AnimationNode::INVALID,
91 AnimationNode::INVALID,
92 AnimationNode::INVALID,
93 AnimationNode::INVALID,
94 AnimationNode::ENDED // active successors for ENDED: this state is a sink here (cannot restart)
97 // transition table for restart=WHEN_NOT_ACTIVE, fill=REMOVE
98 static const StateTransitionTable stateTransitionTable_NotActive_Remove = {
99 AnimationNode::INVALID,
100 AnimationNode::RESOLVED|AnimationNode::ENDED, // active successors for UNRESOLVED
101 AnimationNode::ACTIVE|AnimationNode::ENDED, // active successors for RESOLVED
102 AnimationNode::INVALID,
103 AnimationNode::ENDED, // active successors for ACTIVE: no freeze here
104 AnimationNode::INVALID,
105 AnimationNode::INVALID,
106 AnimationNode::INVALID,
107 AnimationNode::INVALID, // active successors for FROZEN:
108 // this state is unreachable here
109 AnimationNode::INVALID,
110 AnimationNode::INVALID,
111 AnimationNode::INVALID,
112 AnimationNode::INVALID,
113 AnimationNode::INVALID,
114 AnimationNode::INVALID,
115 AnimationNode::INVALID,
116 AnimationNode::ENDED|AnimationNode::RESOLVED|AnimationNode::ACTIVE // active successors for ENDED:
117 // restart possible when ended
120 // transition table for restart=ALWAYS, fill=REMOVE
121 static const StateTransitionTable stateTransitionTable_Always_Remove = {
122 AnimationNode::INVALID,
123 AnimationNode::RESOLVED|AnimationNode::ENDED, // active successors for UNRESOLVED
124 AnimationNode::ACTIVE|AnimationNode::ENDED, // active successors for RESOLVED
125 AnimationNode::INVALID,
126 AnimationNode::ENDED|AnimationNode::ACTIVE|AnimationNode::RESOLVED, // active successors for ACTIVE: restart
127 AnimationNode::INVALID,
128 AnimationNode::INVALID,
129 AnimationNode::INVALID,
130 AnimationNode::INVALID, // active successors for FROZEN:
131 // this state is unreachable here
132 AnimationNode::INVALID,
133 AnimationNode::INVALID,
134 AnimationNode::INVALID,
135 AnimationNode::INVALID,
136 AnimationNode::INVALID,
137 AnimationNode::INVALID,
138 AnimationNode::INVALID,
139 AnimationNode::ENDED|AnimationNode::ACTIVE|AnimationNode::RESOLVED // active successors for ENDED: restart
142 // transition table for restart=NEVER, fill=FREEZE
143 static const StateTransitionTable stateTransitionTable_Never_Freeze = {
144 AnimationNode::INVALID,
145 AnimationNode::RESOLVED|AnimationNode::ENDED, // active successors for UNRESOLVED
146 AnimationNode::ACTIVE|AnimationNode::ENDED, // active successors for RESOLVED
147 AnimationNode::INVALID,
148 AnimationNode::FROZEN|AnimationNode::ENDED, // active successors for ACTIVE: freeze object
149 AnimationNode::INVALID,
150 AnimationNode::INVALID,
151 AnimationNode::INVALID,
152 AnimationNode::ENDED, // active successors for FROZEN: end
153 AnimationNode::INVALID,
154 AnimationNode::INVALID,
155 AnimationNode::INVALID,
156 AnimationNode::INVALID,
157 AnimationNode::INVALID,
158 AnimationNode::INVALID,
159 AnimationNode::INVALID,
160 AnimationNode::ENDED, // active successors for ENDED: this state is a sink here (cannot restart)
163 // transition table for restart=WHEN_NOT_ACTIVE, fill=FREEZE
164 static const StateTransitionTable stateTransitionTable_NotActive_Freeze = {
165 AnimationNode::INVALID,
166 AnimationNode::RESOLVED|AnimationNode::ENDED, // active successors for UNRESOLVED
167 AnimationNode::ACTIVE|AnimationNode::ENDED, // active successors for RESOLVED
168 AnimationNode::INVALID,
169 AnimationNode::FROZEN|AnimationNode::ENDED, // active successors for ACTIVE: freeze object
170 AnimationNode::INVALID,
171 AnimationNode::INVALID,
172 AnimationNode::INVALID,
173 AnimationNode::ENDED|AnimationNode::RESOLVED|AnimationNode::ACTIVE, // active successors for FROZEN:
174 // restart possible when ended
175 AnimationNode::INVALID,
176 AnimationNode::INVALID,
177 AnimationNode::INVALID,
178 AnimationNode::INVALID,
179 AnimationNode::INVALID,
180 AnimationNode::INVALID,
181 AnimationNode::INVALID,
182 AnimationNode::ENDED|AnimationNode::RESOLVED|AnimationNode::ACTIVE // active successors for ENDED:
183 // restart possible when ended
186 // transition table for restart=ALWAYS, fill=FREEZE
187 static const StateTransitionTable stateTransitionTable_Always_Freeze = {
188 AnimationNode::INVALID,
189 AnimationNode::RESOLVED|AnimationNode::ENDED, // active successors for UNRESOLVED
190 AnimationNode::ACTIVE|AnimationNode::ENDED, // active successors for RESOLVED
191 AnimationNode::INVALID,
192 AnimationNode::FROZEN|AnimationNode::ENDED|AnimationNode::ACTIVE|AnimationNode::RESOLVED, // active successors for ACTIVE:
193 // end object, restart
194 AnimationNode::INVALID,
195 AnimationNode::INVALID,
196 AnimationNode::INVALID,
197 AnimationNode::ENDED|AnimationNode::RESOLVED|AnimationNode::ACTIVE, // active successors for FROZEN: restart possible
198 AnimationNode::INVALID,
199 AnimationNode::INVALID,
200 AnimationNode::INVALID,
201 AnimationNode::INVALID,
202 AnimationNode::INVALID,
203 AnimationNode::INVALID,
204 AnimationNode::INVALID,
205 AnimationNode::ENDED|AnimationNode::ACTIVE|AnimationNode::RESOLVED // active successors for ENDED: restart
208 static const StateTransitionTable* tableGuide[] = {
209 &stateTransitionTable_Never_Remove,
210 &stateTransitionTable_NotActive_Remove,
211 &stateTransitionTable_Always_Remove,
212 &stateTransitionTable_Never_Freeze,
213 &stateTransitionTable_NotActive_Freeze,
214 &stateTransitionTable_Always_Freeze
217 int nRestartValue;
218 switch( nRestartMode ) {
219 default:
220 case animations::AnimationRestart::DEFAULT:
221 // same value: animations::AnimationRestart::INHERIT:
222 OSL_ENSURE(
223 false, "getStateTransitionTable(): unexpected case for restart" );
224 // FALLTHROUGH intended
225 case animations::AnimationRestart::NEVER:
226 nRestartValue = 0;
227 break;
228 case animations::AnimationRestart::WHEN_NOT_ACTIVE:
229 nRestartValue = 1;
230 break;
231 case animations::AnimationRestart::ALWAYS:
232 nRestartValue = 2;
233 break;
236 int nFillValue;
237 switch( nFillMode ) {
238 default:
239 case animations::AnimationFill::AUTO:
240 case animations::AnimationFill::DEFAULT:
241 // same value: animations::AnimationFill::INHERIT:
242 OSL_ENSURE(
243 false, "getStateTransitionTable(): unexpected case for fill" );
244 // FALLTHROUGH intended
245 case animations::AnimationFill::REMOVE:
246 nFillValue = 0;
247 break;
248 case animations::AnimationFill::FREEZE:
249 case animations::AnimationFill::HOLD:
250 case animations::AnimationFill::TRANSITION:
251 nFillValue = 1;
252 break;
255 return *tableGuide[ 3*nFillValue + nRestartValue ];
258 /// Little helper predicate, to detect main sequence root node
259 bool isMainSequenceRootNode_(
260 const uno::Reference< animations::XAnimationNode >& xNode )
262 // detect main sequence root node (need that for
263 // end-of-mainsequence signalling below)
264 beans::NamedValue const aSearchKey(
265 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "node-type" ) ),
266 uno::makeAny( presentation::EffectNodeType::MAIN_SEQUENCE ) );
268 uno::Sequence<beans::NamedValue> const userData(xNode->getUserData());
269 return findNamedValue( userData, aSearchKey );
272 } // anon namespace
274 // BaseNode implementation
275 //=========================================================================
277 /** state transition handling
279 class BaseNode::StateTransition : private boost::noncopyable
281 public:
282 enum Options { NONE, FORCE };
284 explicit StateTransition( BaseNode * pNode )
285 : mpNode(pNode), meToState(INVALID) {}
287 ~StateTransition() {
288 clear();
291 bool enter( NodeState eToState, int options = NONE )
293 OSL_ENSURE( meToState == INVALID,
294 "### commit() before enter()ing again!" );
295 if (meToState != INVALID)
296 return false;
297 bool const bForce = ((options & FORCE) != 0);
298 if (!bForce && !mpNode->isTransition( mpNode->meCurrState, eToState ))
299 return false;
300 // recursion detection:
301 if ((mpNode->meCurrentStateTransition & eToState) != 0)
302 return false; // already in wanted transition
303 // mark transition:
304 mpNode->meCurrentStateTransition |= eToState;
305 meToState = eToState;
306 return true; // in transition
309 void commit() {
310 OSL_ENSURE( meToState != INVALID, "### nothing to commit!" );
311 if (meToState != INVALID) {
312 mpNode->meCurrState = meToState;
313 clear();
317 void clear() {
318 if (meToState != INVALID) {
319 OSL_ASSERT( (mpNode->meCurrentStateTransition & meToState) != 0 );
320 mpNode->meCurrentStateTransition &= ~meToState;
321 meToState = INVALID;
325 private:
326 BaseNode *const mpNode;
327 NodeState meToState;
330 BaseNode::BaseNode( const uno::Reference< animations::XAnimationNode >& xNode,
331 const BaseContainerNodeSharedPtr& rParent,
332 const NodeContext& rContext ) :
333 maContext( rContext.maContext ),
334 maDeactivatingListeners(),
335 mxAnimationNode( xNode ),
336 mpParent( rParent ),
337 mpSelf(),
338 mpStateTransitionTable( NULL ),
339 mnStartDelay( rContext.mnStartDelay ),
340 meCurrState( UNRESOLVED ),
341 meCurrentStateTransition( 0 ),
342 mpCurrentEvent(),
343 mbIsMainSequenceRootNode( isMainSequenceRootNode_( xNode ) )
345 ENSURE_OR_THROW( mxAnimationNode.is(),
346 "BaseNode::BaseNode(): Invalid XAnimationNode" );
348 // setup state transition table
349 mpStateTransitionTable = getStateTransitionTable( getRestartMode(),
350 getFillMode() );
353 void BaseNode::dispose()
355 meCurrState = INVALID;
357 // discharge a loaded event, if any:
358 if (mpCurrentEvent) {
359 mpCurrentEvent->dispose();
360 mpCurrentEvent.reset();
362 maDeactivatingListeners.clear();
363 mxAnimationNode.clear();
364 mpParent.reset();
365 mpSelf.reset();
366 maContext.dispose();
370 sal_Int16 BaseNode::getRestartMode()
372 const sal_Int16 nTmp( mxAnimationNode->getRestart() );
373 return (nTmp != animations::AnimationRestart::DEFAULT &&
374 nTmp != animations::AnimationRestart::INHERIT)
375 ? nTmp : getRestartDefaultMode();
378 sal_Int16 BaseNode::getFillMode()
380 const sal_Int16 nTmp( mxAnimationNode->getFill() );
381 const sal_Int16 nFill((nTmp != animations::AnimationFill::DEFAULT &&
382 nTmp != animations::AnimationFill::INHERIT)
383 ? nTmp : getFillDefaultMode());
385 // For AUTO fill mode, SMIL specifies that fill mode is FREEZE,
386 // if no explicit active duration is given
387 // (no duration, end, repeatCount or repeatDuration given),
388 // and REMOVE otherwise
389 if( nFill == animations::AnimationFill::AUTO ) {
390 return (isIndefiniteTiming( mxAnimationNode->getDuration() ) &&
391 isIndefiniteTiming( mxAnimationNode->getEnd() ) &&
392 !mxAnimationNode->getRepeatCount().hasValue() &&
393 isIndefiniteTiming( mxAnimationNode->getRepeatDuration() ))
394 ? animations::AnimationFill::FREEZE
395 : animations::AnimationFill::REMOVE;
397 else {
398 return nFill;
402 sal_Int16 BaseNode::getFillDefaultMode() const
404 sal_Int16 nFillDefault = mxAnimationNode->getFillDefault();
405 if (nFillDefault == animations::AnimationFill::DEFAULT) {
406 nFillDefault = (mpParent != 0
407 ? mpParent->getFillDefaultMode()
408 : animations::AnimationFill::AUTO);
410 return nFillDefault;
413 sal_Int16 BaseNode::getRestartDefaultMode() const
415 sal_Int16 nRestartDefaultMode = mxAnimationNode->getRestartDefault();
416 if (nRestartDefaultMode == animations::AnimationRestart::DEFAULT) {
417 nRestartDefaultMode = (mpParent != 0
418 ? mpParent->getRestartDefaultMode()
419 : animations::AnimationRestart::ALWAYS);
421 return nRestartDefaultMode;
424 uno::Reference<animations::XAnimationNode> BaseNode::getXAnimationNode() const
426 return mxAnimationNode;
429 bool BaseNode::init()
431 if (! checkValidNode())
432 return false;
433 meCurrState = UNRESOLVED;
434 // discharge a loaded event, if any:
435 if (mpCurrentEvent) {
436 mpCurrentEvent->dispose();
437 mpCurrentEvent.reset();
439 return init_st(); // may call derived class
442 bool BaseNode::init_st()
444 return true;
447 bool BaseNode::resolve()
449 if (! checkValidNode())
450 return false;
452 OSL_ASSERT( meCurrState != RESOLVED );
453 if (inStateOrTransition( RESOLVED ))
454 return true;
456 StateTransition st(this);
457 if (st.enter( RESOLVED ) &&
458 isTransition( RESOLVED, ACTIVE ) &&
459 resolve_st() /* may call derived class */)
461 st.commit(); // changing state
463 // discharge a loaded event, if any:
464 if (mpCurrentEvent)
465 mpCurrentEvent->dispose();
467 // schedule activation event:
469 // This method takes the NodeContext::mnStartDelay value into account,
470 // to cater for iterate container time shifts. We cannot put different
471 // iterations of the iterate container's children into different
472 // subcontainer (such as a 'DelayContainer', which delays resolving its
473 // children by a fixed amount), since all iterations' nodes must be
474 // resolved at the same time (otherwise, the delayed subset creation
475 // will not work, i.e. deactivate the subsets too late in the master
476 // shape).
477 uno::Any const aBegin( mxAnimationNode->getBegin() );
478 if (aBegin.hasValue()) {
479 mpCurrentEvent = generateEvent(
480 aBegin, boost::bind( &AnimationNode::activate, mpSelf ),
481 maContext, mnStartDelay );
483 else {
484 // For some leaf nodes, PPT import yields empty begin time,
485 // although semantically, it should be 0.0
486 // TODO(F3): That should really be provided by the PPT import
488 // schedule delayed activation event. Take iterate node
489 // timeout into account
490 mpCurrentEvent = makeDelay(
491 boost::bind( &AnimationNode::activate, mpSelf ), mnStartDelay );
492 maContext.mrEventQueue.addEvent( mpCurrentEvent );
495 return true;
497 return false;
500 bool BaseNode::resolve_st()
502 return true;
506 bool BaseNode::activate()
508 if (! checkValidNode())
509 return false;
511 OSL_ASSERT( meCurrState != ACTIVE );
512 if (inStateOrTransition( ACTIVE ))
513 return true;
515 StateTransition st(this);
516 if (st.enter( ACTIVE )) {
518 activate_st(); // calling derived class
520 st.commit(); // changing state
522 maContext.mrEventMultiplexer.notifyAnimationStart( mpSelf );
524 return true;
527 return false;
530 void BaseNode::activate_st()
532 scheduleDeactivationEvent();
535 void BaseNode::scheduleDeactivationEvent( EventSharedPtr const& pEvent )
537 if (mpCurrentEvent) {
538 mpCurrentEvent->dispose();
539 mpCurrentEvent.reset();
541 if (pEvent) {
542 if (maContext.mrEventQueue.addEvent( pEvent ))
543 mpCurrentEvent = pEvent;
545 else {
546 // This method need not take the
547 // NodeContext::mnStartDelay value into account,
548 // because the deactivation event is only scheduled
549 // when the effect is started: the timeout is then
550 // already respected.
552 // xxx todo:
553 // think about set node, anim base node!
554 // if anim base node has no activity, this is called to schedule deactivatiion,
555 // but what if it does not schedule anything?
557 // TODO(F2): Handle end time attribute, too
558 mpCurrentEvent = generateEvent(
559 mxAnimationNode->getDuration(),
560 boost::bind( &AnimationNode::deactivate, mpSelf ),
561 maContext, 0.0 );
565 void BaseNode::deactivate()
567 if (inStateOrTransition( ENDED | FROZEN ) || !checkValidNode())
568 return;
570 if (isTransition( meCurrState, FROZEN, false /* no OSL_ASSERT */ )) {
571 // do transition to FROZEN:
572 StateTransition st(this);
573 if (st.enter( FROZEN, StateTransition::FORCE )) {
575 deactivate_st( FROZEN );
576 st.commit();
578 notifyEndListeners();
580 // discharge a loaded event, before going on:
581 if (mpCurrentEvent) {
582 mpCurrentEvent->dispose();
583 mpCurrentEvent.reset();
587 else {
588 // use end instead:
589 end();
591 // state has changed either to FROZEN or ENDED
594 void BaseNode::deactivate_st( NodeState )
598 void BaseNode::end()
600 bool const bIsFrozenOrInTransitionToFrozen = inStateOrTransition( FROZEN );
601 if (inStateOrTransition( ENDED ) || !checkValidNode())
602 return;
604 // END must always be reachable. If not, that's an error in the
605 // transition tables
606 OSL_ENSURE( isTransition( meCurrState, ENDED ),
607 "end state not reachable in transition table" );
609 StateTransition st(this);
610 if (st.enter( ENDED, StateTransition::FORCE )) {
612 deactivate_st( ENDED );
613 st.commit(); // changing state
615 // if is FROZEN or is to be FROZEN, then
616 // will/already notified deactivating listeners
617 if (!bIsFrozenOrInTransitionToFrozen)
618 notifyEndListeners();
620 // discharge a loaded event, before going on:
621 if (mpCurrentEvent) {
622 mpCurrentEvent->dispose();
623 mpCurrentEvent.reset();
628 void BaseNode::notifyDeactivating( const AnimationNodeSharedPtr& rNotifier )
630 (void) rNotifier; // avoid warning
631 OSL_ASSERT( rNotifier->getState() == FROZEN ||
632 rNotifier->getState() == ENDED );
633 // TODO(F1): for end sync functionality, this might indeed be used some day
636 void BaseNode::notifyEndListeners() const
638 // notify all listeners
639 std::for_each( maDeactivatingListeners.begin(),
640 maDeactivatingListeners.end(),
641 boost::bind( &AnimationNode::notifyDeactivating, _1,
642 boost::cref(mpSelf) ) );
644 // notify state change
645 maContext.mrEventMultiplexer.notifyAnimationEnd( mpSelf );
647 // notify main sequence end (iff we're the main
648 // sequence root node). This is because the main
649 // sequence determines the active duration of the
650 // slide. All other sequences are secondary, in that
651 // they don't prevent a slide change from happening,
652 // even if they have not been completed. In other
653 // words, all sequences except the main sequence are
654 // optional for the slide lifetime.
655 if (isMainSequenceRootNode())
656 maContext.mrEventMultiplexer.notifySlideAnimationsEnd();
659 AnimationNode::NodeState BaseNode::getState() const
661 return meCurrState;
664 bool BaseNode::registerDeactivatingListener(
665 const AnimationNodeSharedPtr& rNotifee )
667 if (! checkValidNode())
668 return false;
670 ENSURE_OR_RETURN(
671 rNotifee,
672 "BaseNode::registerDeactivatingListener(): invalid notifee" );
673 maDeactivatingListeners.push_back( rNotifee );
675 return true;
678 void BaseNode::setSelf( const BaseNodeSharedPtr& rSelf )
680 ENSURE_OR_THROW( rSelf.get() == this,
681 "BaseNode::setSelf(): got ptr to different object" );
682 ENSURE_OR_THROW( !mpSelf,
683 "BaseNode::setSelf(): called multiple times" );
685 mpSelf = rSelf;
688 // Debug
689 //=========================================================================
691 #if defined(VERBOSE) && defined(DBG_UTIL)
692 void BaseNode::showState() const
694 const AnimationNode::NodeState eNodeState( getState() );
696 if( eNodeState == AnimationNode::INVALID )
697 VERBOSE_TRACE( "Node state: n0x%X [label=\"%s\",style=filled,"
698 "fillcolor=\"0.5,0.2,0.5\"]",
699 (const char*)this+debugGetCurrentOffset(),
700 getDescription() );
701 else
702 VERBOSE_TRACE( "Node state: n0x%X [label=\"%s\",style=filled,"
703 "fillcolor=\"%f,1.0,1.0\"]",
704 (const char*)this+debugGetCurrentOffset(),
705 getDescription(),
706 log(double(getState()))/4.0 );
708 // determine additional node information
709 uno::Reference<animations::XAnimate> const xAnimate( mxAnimationNode,
710 uno::UNO_QUERY );
711 if( xAnimate.is() )
713 uno::Reference< drawing::XShape > xTargetShape( xAnimate->getTarget(),
714 uno::UNO_QUERY );
716 if( !xTargetShape.is() )
718 ::com::sun::star::presentation::ParagraphTarget aTarget;
720 // no shape provided. Maybe a ParagraphTarget?
721 if( (xAnimate->getTarget() >>= aTarget) )
722 xTargetShape = aTarget.Shape;
725 if( xTargetShape.is() )
727 uno::Reference< beans::XPropertySet > xPropSet( xTargetShape,
728 uno::UNO_QUERY );
730 // read shape name
731 ::rtl::OUString aName;
732 if( (xPropSet->getPropertyValue(
733 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("Name") ) )
734 >>= aName) )
736 const ::rtl::OString& rAsciiName(
737 ::rtl::OUStringToOString( aName,
738 RTL_TEXTENCODING_ASCII_US ) );
740 VERBOSE_TRACE( "Node info: n0x%X, name \"%s\"",
741 (const char*)this+debugGetCurrentOffset(),
742 rAsciiName.getStr() );
748 const char* BaseNode::getDescription() const
750 return "BaseNode";
753 void BaseNode::showTreeFromWithin() const
755 // find root node
756 BaseNodeSharedPtr pCurrNode( mpSelf );
757 while( pCurrNode->mpParent ) pCurrNode = pCurrNode->mpParent;
759 pCurrNode->showState();
761 #endif
763 } // namespace internal
764 } // namespace slideshow