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