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