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